From d29c450ec36a4f0aa48cad3c98cf69de63e346dd Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Tue, 22 Jun 2021 23:50:39 -0400 Subject: [PATCH] hal/gles: bind group creation --- wgpu-core/src/device/mod.rs | 3 +- wgpu-hal/src/gles/command.rs | 6 +- wgpu-hal/src/gles/device.rs | 119 +++++++++++++++++++++++++++++++--- wgpu-hal/src/gles/mod.rs | 54 ++++++++++++++- wgpu-hal/src/lib.rs | 5 ++ wgpu-hal/src/metal/device.rs | 5 +- wgpu-hal/src/metal/mod.rs | 2 +- wgpu-hal/src/vulkan/device.rs | 2 +- wgpu-hal/src/vulkan/mod.rs | 2 +- 9 files changed, 174 insertions(+), 24 deletions(-) diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 50d5ae839f..7de5970bc2 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -1035,7 +1035,8 @@ impl Device { })?; } - let hal_bindings = entry_map.values().cloned().collect::>(); + let mut hal_bindings = entry_map.values().cloned().collect::>(); + hal_bindings.sort_by_key(|b| b.binding); let hal_desc = hal::BindGroupLayoutDescriptor { label, entries: &hal_bindings, diff --git a/wgpu-hal/src/gles/command.rs b/wgpu-hal/src/gles/command.rs index b2e7fc8d97..525afe05be 100644 --- a/wgpu-hal/src/gles/command.rs +++ b/wgpu-hal/src/gles/command.rs @@ -173,15 +173,15 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn set_bind_group( &mut self, - layout: &Resource, + layout: &super::PipelineLayout, index: u32, - group: &Resource, + group: &super::BindGroup, dynamic_offsets: &[wgt::DynamicOffset], ) { } unsafe fn set_push_constants( &mut self, - layout: &Resource, + layout: &super::PipelineLayout, stages: wgt::ShaderStage, offset: u32, data: &[u32], diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index 97cb3f95f9..404ba13037 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -1,6 +1,6 @@ use super::{DeviceResult, Resource}; //TEMP use glow::HasContext; -use std::{convert::TryInto, ptr::NonNull}; +use std::{convert::TryInto, ptr::NonNull, sync::Arc}; impl crate::Device for super::Device { unsafe fn exit(self) { @@ -46,6 +46,7 @@ impl crate::Device for super::Device { Ok(super::Buffer { raw, target, + size: desc.size, map_flags, }) } @@ -269,24 +270,122 @@ impl crate::Device for super::Device { unsafe fn create_bind_group_layout( &self, desc: &crate::BindGroupLayoutDescriptor, - ) -> DeviceResult { - Ok(Resource) + ) -> Result { + Ok(super::BindGroupLayout { + entries: Arc::from(desc.entries), + }) } - unsafe fn destroy_bind_group_layout(&self, bg_layout: Resource) {} + unsafe fn destroy_bind_group_layout(&self, _bg_layout: super::BindGroupLayout) {} + unsafe fn create_pipeline_layout( &self, desc: &crate::PipelineLayoutDescriptor, - ) -> DeviceResult { - Ok(Resource) + ) -> Result { + let mut group_infos = Vec::with_capacity(desc.bind_group_layouts.len()); + let mut num_samplers = 0u8; + let mut num_textures = 0u8; + let mut num_uniform_buffers = 0u8; + let mut num_storage_buffers = 0u8; + + for bg_layout in desc.bind_group_layouts { + // create a vector with the size enough to hold all the bindings, filled with `!0` + let mut binding_to_slot = vec![ + !0; + bg_layout + .entries + .last() + .map_or(0, |b| b.binding as usize + 1) + ] + .into_boxed_slice(); + + for entry in bg_layout.entries.iter() { + let counter = match entry.ty { + wgt::BindingType::Sampler { .. } => &mut num_samplers, + wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => { + &mut num_textures + } + wgt::BindingType::Buffer { + ty: wgt::BufferBindingType::Uniform, + .. + } => &mut num_uniform_buffers, + wgt::BindingType::Buffer { + ty: wgt::BufferBindingType::Storage { .. }, + .. + } => &mut num_storage_buffers, + }; + + binding_to_slot[entry.binding as usize] = *counter; + *counter += entry.count.map_or(1, |c| c.get() as u8); + } + + group_infos.push(super::BindGroupLayoutInfo { + entries: Arc::clone(&bg_layout.entries), + binding_to_slot, + }); + } + + Ok(super::PipelineLayout { + group_infos: group_infos.into_boxed_slice(), + }) } - unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Resource) {} + unsafe fn destroy_pipeline_layout(&self, pipeline_layout: super::PipelineLayout) {} + unsafe fn create_bind_group( &self, desc: &crate::BindGroupDescriptor, - ) -> DeviceResult { - Ok(Resource) + ) -> Result { + let mut contents = Vec::new(); + + for (entry, layout) in desc.entries.iter().zip(desc.layout.entries.iter()) { + let binding = match layout.ty { + wgt::BindingType::Buffer { ty, .. } => { + let bb = &desc.buffers[entry.resource_index as usize]; + let register = match ty { + wgt::BufferBindingType::Uniform => super::BindingRegister::UniformBuffers, + wgt::BufferBindingType::Storage { .. } => { + super::BindingRegister::StorageBuffers + } + }; + super::RawBinding::Buffer { + register, + raw: bb.buffer.raw, + offset: bb.offset as i32, + size: match bb.size { + Some(s) => s.get() as i32, + None => (bb.buffer.size - bb.offset) as i32, + }, + } + } + wgt::BindingType::Sampler { .. } => { + let sampler = desc.samplers[entry.resource_index as usize]; + super::RawBinding::Sampler(sampler.raw) + } + wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => { + match *desc.textures[entry.resource_index as usize].view { + super::TextureView::Renderbuffer { .. } => { + panic!("Unable to use a renderbuffer in a group") + } + super::TextureView::Texture { + raw, + target, + ref range, + } => super::RawBinding::Texture { + raw, + target, + range: range.clone(), + }, + } + } + }; + contents.push(binding); + } + + Ok(super::BindGroup { + layout_entries: Arc::clone(&desc.layout.entries), + contents: contents.into_boxed_slice(), + }) } - unsafe fn destroy_bind_group(&self, group: Resource) {} + unsafe fn destroy_bind_group(&self, _group: super::BindGroup) {} unsafe fn create_shader_module( &self, diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index a335a66ddd..0e5bed313c 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -41,9 +41,9 @@ impl crate::Api for Api { type QuerySet = Resource; type Fence = Resource; - type BindGroupLayout = Resource; - type BindGroup = Resource; - type PipelineLayout = Resource; + type BindGroupLayout = BindGroupLayout; + type BindGroup = BindGroup; + type PipelineLayout = PipelineLayout; type ShaderModule = Resource; type RenderPipeline = Resource; type ComputePipeline = Resource; @@ -190,6 +190,7 @@ pub struct Queue { pub struct Buffer { raw: glow::Buffer, target: BindTarget, + size: wgt::BufferAddress, map_flags: u32, } @@ -239,6 +240,53 @@ pub struct Sampler { raw: glow::Sampler, } +pub struct BindGroupLayout { + entries: Arc<[wgt::BindGroupLayoutEntry]>, +} + +struct BindGroupLayoutInfo { + entries: Arc<[wgt::BindGroupLayoutEntry]>, + /// Mapping of resources, indexed by `binding`, into the whole layout space. + /// For texture resources, the value is the texture slot index. + /// For sampler resources, the value is the index of the sampler in the whole layout. + /// For buffers, the value is the uniform or storage slot index. + /// For unused bindings, the value is `!0` + binding_to_slot: Box<[u8]>, +} + +pub struct PipelineLayout { + group_infos: Box<[BindGroupLayoutInfo]>, +} + +#[derive(Debug)] +enum BindingRegister { + Textures, + UniformBuffers, + StorageBuffers, +} + +#[derive(Debug)] +enum RawBinding { + Buffer { + register: BindingRegister, + raw: glow::Buffer, + offset: i32, + size: i32, + }, + Texture { + raw: glow::Texture, + target: BindTarget, + range: wgt::ImageSubresourceRange, + }, + Sampler(glow::Sampler), +} + +#[derive(Debug)] +pub struct BindGroup { + layout_entries: Arc<[wgt::BindGroupLayoutEntry]>, + contents: Box<[RawBinding]>, +} + #[derive(Debug)] struct TextureCopyInfo { external_format: u32, diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index df37f55403..70adcff4a4 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -238,6 +238,7 @@ pub trait Device: Send + Sync { ) -> Result; unsafe fn destroy_command_encoder(&self, pool: A::CommandEncoder); + /// Creates a bind group layout. unsafe fn create_bind_group_layout( &self, desc: &BindGroupLayoutDescriptor, @@ -753,6 +754,10 @@ pub struct SamplerDescriptor<'a> { pub border_color: Option, } +/// BindGroupLayout descriptor. +/// +/// Valid usage: +/// - `entries` are sorted by ascending `wgt::BindGroupLayoutEntry::binding` #[derive(Clone, Debug)] pub struct BindGroupLayoutDescriptor<'a> { pub label: Label<'a>, diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index 4d02f94564..c105aee316 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -363,11 +363,8 @@ impl crate::Device for super::Device { &self, desc: &crate::BindGroupLayoutDescriptor, ) -> DeviceResult { - let mut map = desc.entries.to_vec(); - map.sort_by_key(|e| e.binding); - Ok(super::BindGroupLayout { - entries: Arc::new(map), + entries: Arc::from(desc.entries), }) } unsafe fn destroy_bind_group_layout(&self, _bg_layout: super::BindGroupLayout) {} diff --git a/wgpu-hal/src/metal/mod.rs b/wgpu-hal/src/metal/mod.rs index bb0720ae9c..0a4f1b545e 100644 --- a/wgpu-hal/src/metal/mod.rs +++ b/wgpu-hal/src/metal/mod.rs @@ -412,7 +412,7 @@ impl Sampler { #[derive(Debug)] pub struct BindGroupLayout { /// Sorted list of BGL entries. - entries: Arc>, + entries: Arc<[wgt::BindGroupLayoutEntry]>, } #[derive(Clone, Debug, Default)] diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 3248921d2c..5574dca7f9 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -937,7 +937,7 @@ impl crate::Device for super::Device { Ok(super::BindGroupLayout { raw, desc_count, - types, + types: types.into_boxed_slice(), }) } unsafe fn destroy_bind_group_layout(&self, bg_layout: super::BindGroupLayout) { diff --git a/wgpu-hal/src/vulkan/mod.rs b/wgpu-hal/src/vulkan/mod.rs index ffc6d66c61..a235c115d0 100644 --- a/wgpu-hal/src/vulkan/mod.rs +++ b/wgpu-hal/src/vulkan/mod.rs @@ -271,7 +271,7 @@ pub struct Sampler { pub struct BindGroupLayout { raw: vk::DescriptorSetLayout, desc_count: gpu_descriptor::DescriptorTotalCount, - types: Vec<(vk::DescriptorType, u32)>, + types: Box<[(vk::DescriptorType, u32)]>, } #[derive(Debug)]