Skip to content

Commit

Permalink
Adds basic descriptor set support to the opengl backend
Browse files Browse the repository at this point in the history
Signed-off-by: Hal Gentz <[email protected]>
  • Loading branch information
goddessfreya committed May 30, 2018
1 parent 1e959ac commit 9e92025
Show file tree
Hide file tree
Showing 6 changed files with 287 additions and 27 deletions.
42 changes: 38 additions & 4 deletions src/backend/gl/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ pub enum Command {
CopySurfaceToBuffer(n::Surface, n::RawBuffer, command::BufferImageCopy),
CopyImageToTexture(n::ImageKind, n::Texture, command::ImageCopy),
CopyImageToSurface(n::ImageKind, n::Surface, command::ImageCopy),

BindBufferRange(gl::types::GLenum, gl::types::GLuint, n::RawBuffer, gl::types::GLintptr, gl::types::GLsizeiptr),
BindTexture(gl::types::GLenum, n::Texture),
BindSampler(gl::types::GLuint, n::Texture),
}

pub type FrameBufferTarget = gl::types::GLenum;
Expand Down Expand Up @@ -832,14 +836,44 @@ impl command::RawCommandBuffer<Backend> for RawCommandBuffer {

fn bind_graphics_descriptor_sets<T>(
&mut self,
_layout: &n::PipelineLayout,
_first_set: usize,
_sets: T,
layout: &n::PipelineLayout,
first_set: usize,
sets: T,
) where
T: IntoIterator,
T::Item: Borrow<n::DescriptorSet>,
{
// TODO
let mut set = first_set as _;

for desc_set in sets {
let desc_set = desc_set.borrow();
for new_binding in desc_set.bindings.read().unwrap().iter() {
match new_binding {
n::DescSetBindings::Buffer(btype, binding, buffer, offset, size) => {
self.push_cmd(Command::BindBufferRange(
gl::UNIFORM_BUFFER,
*layout.desc_remap_data.read().unwrap().get_binding(*btype, set, *binding).unwrap(),
*buffer,
*offset,
*size,
))
}
n::DescSetBindings::Texture(binding, texture) => {
self.push_cmd(Command::BindTexture(
*binding,
*texture,
))
}
n::DescSetBindings::Sampler(binding, sampler) => {
self.push_cmd(Command::BindSampler(
*binding,
*sampler,
))
}
}
}
set += 1;
}
}

fn bind_compute_pipeline(&mut self, pipeline: &n::ComputePipeline) {
Expand Down
144 changes: 130 additions & 14 deletions src/backend/gl/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::collections::HashMap;
use std::iter::repeat;
use std::ops::Range;
use std::{ptr, mem, slice};
use std::sync::{Arc, Mutex};
use std::sync::{Arc, Mutex, RwLock};

use gl;
use gl::types::{GLint, GLenum, GLfloat};
Expand Down Expand Up @@ -284,21 +284,86 @@ impl Device {
})
}

fn remap_desc_sets(
&self,
ast: &mut spirv::Ast<glsl::Target>,
desc_remap_data: &mut n::DescRemapData,
) {
let res = ast.get_shader_resources().unwrap();

self.remap_desc_set(ast, desc_remap_data, &res.uniform_buffers, n::BindingTypes::UniformBuffers);
self.remap_desc_set(ast, desc_remap_data, &res.storage_buffers, n::BindingTypes::StorageBuffers);
self.remap_desc_set(ast, desc_remap_data, &res.storage_images, n::BindingTypes::StorageImages);
self.remap_desc_set(ast, desc_remap_data, &res.sampled_images, n::BindingTypes::SampledImages);
self.remap_desc_set(ast, desc_remap_data, &res.separate_images, n::BindingTypes::SeparateImages);
self.remap_desc_set(ast, desc_remap_data, &res.separate_samplers, n::BindingTypes::SeparateSamplers);
self.remap_desc_set(ast, desc_remap_data, &res.subpass_inputs, n::BindingTypes::SubpassInputs);

// Everything but these four, I think
//all_res.append(&mut res.stage_inputs);
//all_res.append(&mut res.stage_outputs);
//all_res.append(&mut res.atomic_counters);
//all_res.append(&mut res.push_constants);
}

fn remap_desc_set(
&self,
ast: &mut spirv::Ast<glsl::Target>,
desc_remap_data: &mut n::DescRemapData,
all_res: &[spirv::Resource],
btype: n::BindingTypes,
) {
for res in all_res {
let set = ast.get_decoration(res.id, spirv::Decoration::DescriptorSet).unwrap();
let binding = ast.get_decoration(res.id, spirv::Decoration::Binding).unwrap();
let mut new_binding = desc_remap_data.get_binding_insert(btype, set, binding);
desc_remap_data.associate_name(res.name.clone(), btype, set, binding);

if self.share.legacy_features.contains(LegacyFeatures::NO_EXPLICIT_LAYOUTS_IN_SHADER) {
debug!("Next remap is going to be to zero because explicit layouts in shaders aren't supported prior to OpenGL4.2");
new_binding = 0
}

debug!("Uniform {} has been remaped from set {} binding {} to binding {}", res.name, set, binding, new_binding);

ast.set_decoration(res.id, spirv::Decoration::DescriptorSet, 0).unwrap();
ast.set_decoration(res.id, spirv::Decoration::Binding, new_binding).unwrap();
}
}

fn compile_shader(
&self, point: &pso::EntryPoint<B>, stage: pso::Stage
&self, point: &pso::EntryPoint<B>, stage: pso::Stage, desc_remap_data: &mut n::DescRemapData
) -> n::Shader {
assert_eq!(point.entry, "main");
match *point.module {
n::ShaderModule::Raw(raw) => raw,
n::ShaderModule::Raw(raw) => {
debug!("Can't remap bindings for raw shaders. Assuming they are already rebound.");
raw
}
n::ShaderModule::Spirv(ref spirv) => {
let mut ast = self.parse_spirv(spirv).unwrap();

self.specialize_ast(&mut ast, point.specialization).unwrap();
self.remap_desc_sets(&mut ast, desc_remap_data);

let glsl = self.translate_spirv(&mut ast).unwrap();
info!("Generated:\n{:?}", glsl);
match self.create_shader_module_from_source(glsl.as_bytes(), stage).unwrap() {
let program = match self.create_shader_module_from_source(glsl.as_bytes(), stage).unwrap() {
n::ShaderModule::Raw(raw) => raw,
_ => panic!("Unhandled")
};

if self.share.legacy_features.contains(LegacyFeatures::NO_EXPLICIT_LAYOUTS_IN_SHADER) {
for (name, (btype, set, binding)) in desc_remap_data.get_names_and_data() {
let gl = &self.share.context;
unsafe {
let index = gl.GetUniformBlockIndex(program, name.as_ptr() as _);
gl.UniformBlockBinding(program, index, *desc_remap_data.get_binding(*btype, *set, *binding).unwrap())
}
}
}

program
}
}
}
Expand Down Expand Up @@ -386,11 +451,13 @@ impl d::Device<B> for Device {
fn create_pipeline_layout<IS, IR>(&self, _: IS, _: IR) -> n::PipelineLayout
where
IS: IntoIterator,
IS::Item: Borrow<n::DescriptorSetLayout>,
IS::Item: Borrow<Vec<pso::DescriptorSetLayoutBinding>>,
IR: IntoIterator,
IR::Item: Borrow<(pso::ShaderStageFlags, Range<u32>)>,
{
n::PipelineLayout
n::PipelineLayout {
desc_remap_data: Arc::new(RwLock::new(n::DescRemapData::new())),
}
}

fn create_graphics_pipeline<'a>(
Expand Down Expand Up @@ -423,7 +490,7 @@ impl d::Device<B> for Device {
.iter()
.filter_map(|&(stage, point_maybe)| {
point_maybe.map(|point| {
let shader_name = self.compile_shader(point, stage);
let shader_name = self.compile_shader(point, stage, &mut *desc.layout.desc_remap_data.write().unwrap());
unsafe { gl.AttachShader(name, shader_name); }
shader_name
})
Expand Down Expand Up @@ -507,10 +574,11 @@ impl d::Device<B> for Device {
) -> Result<n::ComputePipeline, pso::CreationError> {
let gl = &self.share.context;
let share = &self.share;

let program = {
let name = unsafe { gl.CreateProgram() };

let shader = self.compile_shader(&desc.shader, pso::Stage::Compute);
let shader = self.compile_shader(&desc.shader, pso::Stage::Compute, &mut *desc.layout.desc_remap_data.write().unwrap());
unsafe { gl.AttachShader(name, shader) };

unsafe { gl.LinkProgram(name) };
Expand Down Expand Up @@ -764,6 +832,7 @@ impl d::Device<B> for Device {
Ok(n::Buffer {
raw: unbound.name,
target,
size: unbound.requirements.size,
})
}

Expand Down Expand Up @@ -973,12 +1042,13 @@ impl d::Device<B> for Device {
n::DescriptorPool { }
}

fn create_descriptor_set_layout<I>(&self, _: I) -> n::DescriptorSetLayout
fn create_descriptor_set_layout<I>(&self, layout: I) -> Vec<pso::DescriptorSetLayoutBinding>
where
I: IntoIterator,
I::Item: Borrow<pso::DescriptorSetLayoutBinding>,
{
n::DescriptorSetLayout
// Just return it
layout.into_iter().map(|l| l.borrow().clone()).collect()
}

fn write_descriptor_sets<'a, I, J>(&self, writes: I)
Expand All @@ -987,9 +1057,55 @@ impl d::Device<B> for Device {
J: IntoIterator,
J::Item: Borrow<pso::Descriptor<'a, B>>,
{
for _write in writes {
//unimplemented!() // not panicing because of Warden
warn!("TODO: implement `write_descriptor_sets`");
for mut write in writes {
let set = &mut write.set;
let binding = write.binding;
let mut offset = write.array_offset as _;

for descriptor in write.descriptors {
match descriptor.borrow() {
pso::Descriptor::Buffer(buffer, ref range) => {
let start = range.start.unwrap_or(0);
let end = range.end.unwrap_or(buffer.size);
let size = (end - start) as _;

set.bindings
.write()
.unwrap()
.push(n::DescSetBindings::Buffer(
n::BindingTypes::UniformBuffers,
binding,
buffer.raw,
offset,
size,
));

offset += size;
}
pso::Descriptor::CombinedImageSampler(view, layout, sampler) => {
match view {
n::ImageView::Texture(tex, _)
| n::ImageView::TextureLayer(tex, _, _) => set
.bindings
.write()
.unwrap()
.push(n::DescSetBindings::Texture(binding, *tex)),
n::ImageView::Surface(_) => unimplemented!(),
}
match sampler {
n::FatSampler::Sampler(sampler) => set.bindings
.write()
.unwrap()
.push(n::DescSetBindings::Sampler(binding, *sampler)),
n::FatSampler::Info(_) => unimplemented!(),
}
}
pso::Descriptor::Image(view, layout) => unimplemented!(),
pso::Descriptor::Sampler(sampler) => unimplemented!(),
pso::Descriptor::UniformTexelBuffer(view) => unimplemented!(),
pso::Descriptor::StorageTexelBuffer(view) => unimplemented!(),
}
}
}
}

Expand Down Expand Up @@ -1133,7 +1249,7 @@ impl d::Device<B> for Device {
// Nothing to do
}

fn destroy_descriptor_set_layout(&self, _: n::DescriptorSetLayout) {
fn destroy_descriptor_set_layout(&self, _: Vec<pso::DescriptorSetLayoutBinding>) {
// Nothing to do
}

Expand Down
7 changes: 7 additions & 0 deletions src/backend/gl/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ bitflags! {
const SAMPLER_LOD_BIAS = 0x2000;
/// Support setting border texel colors.
const SAMPLER_BORDER_COLOR = 0x4000;
/// No explicit layouts in shader support
const NO_EXPLICIT_LAYOUTS_IN_SHADER = 0x8000;
}
}

Expand Down Expand Up @@ -347,6 +349,11 @@ pub fn query_all(gl: &gl::Gl) -> (Info, Features, LegacyFeatures, Limits, Privat
]) {
features |= Features::SAMPLER_ANISOTROPY;
}
if !info.is_supported(&[
Core(4, 2),
]) {
legacy |= LegacyFeatures::NO_EXPLICIT_LAYOUTS_IN_SHADER;
}
if info.is_supported(&[
Core(3, 3),
Es(3, 0),
Expand Down
4 changes: 2 additions & 2 deletions src/backend/gl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use std::sync::Arc;
use std::ops::Deref;
use std::thread::{self, ThreadId};

use hal::{error, image};
use hal::{error, image, pso};
use hal::queue::{Queues, QueueFamilyId};

pub use self::device::Device;
Expand Down Expand Up @@ -70,7 +70,7 @@ impl hal::Backend for Backend {
type ComputePipeline = native::ComputePipeline;
type GraphicsPipeline = native::GraphicsPipeline;
type PipelineLayout = native::PipelineLayout;
type DescriptorSetLayout = native::DescriptorSetLayout;
type DescriptorSetLayout = Vec<pso::DescriptorSetLayoutBinding>;
type DescriptorPool = native::DescriptorPool;
type DescriptorSet = native::DescriptorSet;

Expand Down
Loading

0 comments on commit 9e92025

Please sign in to comment.