Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 83f0ee6
Author: Hal Gentz <[email protected]>
Date:   Tue May 29 18:41:06 2018 -0600

    Changed example to use a combined image sampler so it works with the GL
    backend

    Signed-off-by: Hal Gentz <[email protected]>

commit 9e92025
Author: Hal Gentz <[email protected]>
Date:   Mon May 28 17:18:34 2018 -0600

    Adds basic descriptor set support to the opengl backend

    Signed-off-by: Hal Gentz <[email protected]>

Signed-off-by: Hal Gentz <[email protected]>
  • Loading branch information
goddessfreya committed Jun 5, 2018
1 parent 92c09cf commit 55a158d
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 49 deletions.
Binary file modified examples/hal/quad/data/frag.spv
Binary file not shown.
25 changes: 3 additions & 22 deletions examples/hal/quad/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,7 @@ fn main() {
&[
pso::DescriptorSetLayoutBinding {
binding: 0,
ty: pso::DescriptorType::SampledImage,
count: 1,
stage_flags: ShaderStageFlags::FRAGMENT,
immutable_samplers: false,
},
pso::DescriptorSetLayoutBinding {
binding: 1,
ty: pso::DescriptorType::Sampler,
ty: pso::DescriptorType::CombinedImageSampler,
count: 1,
stage_flags: ShaderStageFlags::FRAGMENT,
immutable_samplers: false,
Expand Down Expand Up @@ -316,11 +309,7 @@ fn main() {
1, // sets
&[
pso::DescriptorRangeDesc {
ty: pso::DescriptorType::SampledImage,
count: 1,
},
pso::DescriptorRangeDesc {
ty: pso::DescriptorType::Sampler,
ty: pso::DescriptorType::CombinedImageSampler,
count: 1,
},
],
Expand Down Expand Up @@ -449,15 +438,7 @@ fn main() {
binding: 0,
array_offset: 0,
descriptors: Some(
pso::Descriptor::Image(&image_srv, i::Layout::Undefined)
),
},
pso::DescriptorSetWrite {
set: &desc_set,
binding: 1,
array_offset: 0,
descriptors: Some(
pso::Descriptor::Sampler(&sampler)
pso::Descriptor::CombinedImageSampler(&image_srv, i::Layout::ShaderReadOnlyOptimal, &sampler)
),
},
]);
Expand Down
5 changes: 2 additions & 3 deletions examples/hal/quad/shader/quad.frag
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
layout(location = 0) in vec2 v_Uv;
layout(location = 0) out vec4 Target0;

layout(set = 0, binding = 0) uniform texture2D u_Texture;
layout(set = 0, binding = 1) uniform sampler u_Sampler;
layout(set = 0, binding = 0) uniform sampler2D u_Texture;

void main() {
Target0 = texture(sampler2D(u_Texture, u_Sampler), v_Uv);
Target0 = texture(u_Texture, v_Uv);
}
46 changes: 41 additions & 5 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 @@ -836,17 +840,49 @@ impl command::RawCommandBuffer<Backend> for RawCommandBuffer {

fn bind_graphics_descriptor_sets<I, J>(
&mut self,
_layout: &n::PipelineLayout,
_first_set: usize,
_sets: I,
_offsets: J,
layout: &n::PipelineLayout,
first_set: usize,
sets: I,
offsets: J,
) where
I: IntoIterator,
I::Item: Borrow<n::DescriptorSet>,
J: IntoIterator,
J::Item: Borrow<command::DescriptorSetOffset>,
{
// TODO
assert!(offsets.into_iter().next().is_none()); // TODO: offsets unsupported

let mut set = first_set as _;

for desc_set in sets {
let desc_set = desc_set.borrow();
for new_binding in &*desc_set.bindings.lock().unwrap() {
match new_binding {
n::DescSetBindings::Buffer {ty: 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
136 changes: 124 additions & 12 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.insert_missing_binding(btype, set as _, binding);
desc_remap_data.associate_name(res.name.clone(), btype, set as _, 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 @@ -390,7 +455,9 @@ impl d::Device<B> for Device {
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,14 +1042,15 @@ impl d::Device<B> for Device {
n::DescriptorPool { }
}

fn create_descriptor_set_layout<I, J>(&self, _: I, _: J) -> n::DescriptorSetLayout
fn create_descriptor_set_layout<I, J>(&self, layout: I, _: J) -> n::DescriptorSetLayout
where
I: IntoIterator,
I::Item: Borrow<pso::DescriptorSetLayoutBinding>,
J: IntoIterator,
J::Item: Borrow<n::FatSampler>,
{
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 @@ -989,9 +1059,51 @@ 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 mut bindings = set.bindings.lock().unwrap();
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 _;

bindings
.push(n::DescSetBindings::Buffer {
ty: n::BindingTypes::UniformBuffers,
binding,
buffer: buffer.raw,
offset,
size,
});

offset += size;
}
pso::Descriptor::CombinedImageSampler(view, _layout, sampler) => {
match view {
n::ImageView::Texture(tex, _)
| n::ImageView::TextureLayer(tex, _, _) =>
bindings
.push(n::DescSetBindings::Texture(binding, *tex)),
n::ImageView::Surface(_) => unimplemented!(),
}
match sampler {
n::FatSampler::Sampler(sampler) =>
bindings
.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
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
2 changes: 1 addition & 1 deletion 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
Loading

0 comments on commit 55a158d

Please sign in to comment.