diff --git a/wgpu-native/src/command/bind.rs b/wgpu-native/src/command/bind.rs index 29c2c9e25..492dcb198 100644 --- a/wgpu-native/src/command/bind.rs +++ b/wgpu-native/src/command/bind.rs @@ -8,6 +8,12 @@ pub struct BindGroupPair { group_id: Stored, } +pub enum Expectation { + Unchanged, + Match(BindGroupId), + Mismatch, +} + #[derive(Default)] pub struct BindGroupEntry { expected_layout_id: Option, @@ -41,7 +47,7 @@ impl BindGroupEntry { pub fn expect_layout( &mut self, bind_group_layout_id: BindGroupLayoutId, - ) -> Option { + ) -> Expectation { let some = Some(bind_group_layout_id); if self.expected_layout_id != some { self.expected_layout_id = some; @@ -49,13 +55,20 @@ impl BindGroupEntry { Some(BindGroupPair { layout_id, ref group_id, - }) if layout_id == bind_group_layout_id => Some(group_id.value), - Some(_) | None => None, + }) if layout_id == bind_group_layout_id => Expectation::Match(group_id.value), + Some(_) | None => Expectation::Mismatch, } } else { - None + Expectation::Unchanged } } + + pub fn _info(&self) -> (BindGroupLayoutId, Option<(BindGroupLayoutId, BindGroupId)>) { + ( + self.expected_layout_id.unwrap(), + self.provided.as_ref().map(|pair| (pair.layout_id, pair.group_id.value)), + ) + } } #[derive(Default)] diff --git a/wgpu-native/src/command/compute.rs b/wgpu-native/src/command/compute.rs index 4c49879f0..23fc96afe 100644 --- a/wgpu-native/src/command/compute.rs +++ b/wgpu-native/src/command/compute.rs @@ -1,5 +1,5 @@ use crate::{ - command::bind::Binder, + command::bind::{Binder, Expectation}, hub::HUB, track::{Stitch, TrackerSet}, BindGroupId, CommandBuffer, CommandBufferId, ComputePassId, ComputePipelineId, Stored, @@ -122,7 +122,7 @@ pub extern "C" fn wgpu_compute_pass_set_pipeline( .zip(&pipeline_layout.bind_group_layout_ids) .enumerate() { - if let Some(bg_id) = entry.expect_layout(bgl_id) { + if let Expectation::Match(bg_id) = entry.expect_layout(bgl_id) { let desc_set = &bing_group_guard[bg_id].raw; unsafe { pass.raw.bind_compute_descriptor_sets( diff --git a/wgpu-native/src/command/render.rs b/wgpu-native/src/command/render.rs index 9849c2237..ea2e2cd06 100644 --- a/wgpu-native/src/command/render.rs +++ b/wgpu-native/src/command/render.rs @@ -1,6 +1,5 @@ - use crate::{ - command::bind::Binder, + command::bind::{Binder, Expectation}, conv, device::RenderPassContext, hub::HUB, @@ -15,9 +14,22 @@ use hal::command::RawCommandBuffer; use std::{iter, slice}; +type BindGroupMask = u8; +#[derive(Debug, PartialEq)] +enum BlendColorStatus { + Unused, + Required, + Set, +} + #[derive(Debug, PartialEq)] enum DrawError { MissingBlendColor, + IncompatibleBindGroup { + index: u32, + //expected: BindGroupLayoutId, + //provided: Option<(BindGroupLayoutId, BindGroupId)>, + }, } pub struct RenderPass { @@ -26,7 +38,8 @@ pub struct RenderPass { context: RenderPassContext, binder: Binder, trackers: TrackerSet, - blend_color_set: i8, + incompatible_bind_group_mask: BindGroupMask, + blend_color_status: BlendColorStatus, } impl RenderPass { @@ -41,14 +54,21 @@ impl RenderPass { context, binder: Binder::default(), trackers: TrackerSet::new(), - blend_color_set: -1, + incompatible_bind_group_mask: 0, + blend_color_status: BlendColorStatus::Unused, } } fn is_ready(&self) -> Result<(), DrawError> { //TODO: vertex buffers - //TODO: bind groups - if self.blend_color_set == 0 { + if self.incompatible_bind_group_mask != 0 { + let index = self.incompatible_bind_group_mask.trailing_zeros() as u32; + //let (expected, provided) = self.binder.entries[index as usize].info(); + return Err(DrawError::IncompatibleBindGroup { + index, + }); + } + if self.blend_color_status == BlendColorStatus::Required { return Err(DrawError::MissingBlendColor) } Ok(()) @@ -202,6 +222,7 @@ pub extern "C" fn wgpu_render_pass_set_bind_group( pass.binder .provide_entry(index as usize, bind_group_id, bind_group) { + pass.incompatible_bind_group_mask &= !(1u8 << index); let pipeline_layout_guard = HUB.pipeline_layouts.read(); let pipeline_layout = &pipeline_layout_guard[pipeline_layout_id]; unsafe { @@ -230,8 +251,8 @@ pub extern "C" fn wgpu_render_pass_set_pipeline( "The render pipeline is not compatible with the pass!" ); - if pipeline.flags.contains(PipelineFlags::BLEND_COLOR) && pass.blend_color_set < 0 { - pass.blend_color_set = 0; + if pipeline.flags.contains(PipelineFlags::BLEND_COLOR) && pass.blend_color_status == BlendColorStatus::Unused { + pass.blend_color_status = BlendColorStatus::Required; } unsafe { @@ -246,6 +267,7 @@ pub extern "C" fn wgpu_render_pass_set_pipeline( let pipeline_layout = &pipeline_layout_guard[pipeline.layout_id]; let bind_group_guard = HUB.bind_groups.read(); + pass.incompatible_bind_group_mask &= (1u8 << pipeline_layout.bind_group_layout_ids.len()) - 1; pass.binder.pipeline_layout_id = Some(pipeline.layout_id.clone()); pass.binder .ensure_length(pipeline_layout.bind_group_layout_ids.len()); @@ -257,15 +279,22 @@ pub extern "C" fn wgpu_render_pass_set_pipeline( .zip(&pipeline_layout.bind_group_layout_ids) .enumerate() { - if let Some(bg_id) = entry.expect_layout(bgl_id) { - let desc_set = &bind_group_guard[bg_id].raw; - unsafe { - pass.raw.bind_graphics_descriptor_sets( - &pipeline_layout.raw, - index, - iter::once(desc_set), - &[], - ); + match entry.expect_layout(bgl_id) { + Expectation::Unchanged => {} + Expectation::Mismatch => { + pass.incompatible_bind_group_mask |= 1u8 << index; + } + Expectation::Match(bg_id) => { + pass.incompatible_bind_group_mask &= !(1u8 << index); + let desc_set = &bind_group_guard[bg_id].raw; + unsafe { + pass.raw.bind_graphics_descriptor_sets( + &pipeline_layout.raw, + index, + iter::once(desc_set), + &[], + ); + } } } } @@ -279,7 +308,7 @@ pub extern "C" fn wgpu_render_pass_set_blend_color( let mut pass_guard = HUB.render_passes.write(); let pass = &mut pass_guard[pass_id]; - pass.blend_color_set = 1; + pass.blend_color_status = BlendColorStatus::Set; unsafe { pass.raw.set_blend_constants(conv::map_color(color));