diff --git a/CHANGELOG.md b/CHANGELOG.md index e03c86f1f68..93186e890ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -165,6 +165,39 @@ event happens. Our new log policy is as follows: By @cwfitzgerald in [#8579](https://github.com/gfx-rs/wgpu/pull/8579). +#### Push constants renamed immediates, API brought in line with spec. + +As the "immediate data" api is getting close to stabilization in the WebGPU specification, +we're bringing our implementation in line with what the spec dictates. + +First, in the `PipelineLayoutDescriptor`, you now pass a unified size for all stages: + +```diff +- push_constant_ranges: &[wgpu::PushConstantRange { +- stages: wgpu::ShaderStages::VERTEX_FRAGMENT, +- range: 0..12, +- }] ++ immediate_size: 12, +``` + +Second, on the command encoder you no longer specify a shader stage, uploads apply +to all shader stages that use immediate data. + +```diff +- rpass.set_push_constants(wgpu::ShaderStages::FRAGMENT, 0, bytes); ++ rpass.set_immediates(0, bytes); +``` + +Finally, our implementation currently still zero-initializes the immediate data +range you declared in the pipeline layout. This is not spec compliant and failing +to populate immediate "slots" that are used in the shader will be a validation error +in a future version. See [the proposal][immediate-data-spec] for details for determining +which slots are populated in a given shader. + +By @cwfitzgerald in [#8724](https://github.com/gfx-rs/wgpu/pull/8724). + +[immediate-data-spec]: https://github.com/gpuweb/gpuweb/blob/main/proposals/immediate-data.md#immediate-slots + #### `subgroup_{min,max}_size` renamed and moved from `Limits` -> `AdapterInfo` To bring our code in line with the WebGPU spec, we have moved information about subgroup size diff --git a/benches/benches/wgpu-benchmark/computepass.rs b/benches/benches/wgpu-benchmark/computepass.rs index 05dbdd10fc7..0f6d8e3afb6 100644 --- a/benches/benches/wgpu-benchmark/computepass.rs +++ b/benches/benches/wgpu-benchmark/computepass.rs @@ -251,7 +251,7 @@ impl ComputepassState { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = @@ -346,7 +346,7 @@ impl ComputepassState { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bindless_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let bindless_pipeline = diff --git a/benches/benches/wgpu-benchmark/renderpass.rs b/benches/benches/wgpu-benchmark/renderpass.rs index 5f8c6100242..cb21ecb6284 100644 --- a/benches/benches/wgpu-benchmark/renderpass.rs +++ b/benches/benches/wgpu-benchmark/renderpass.rs @@ -151,7 +151,7 @@ impl RenderpassState { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let mut vertex_buffers = Vec::with_capacity(vertex_buffer_count as usize); @@ -287,7 +287,7 @@ impl RenderpassState { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bindless_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); bindless_pipeline = Some(device_state.device.create_render_pipeline( diff --git a/deno_webgpu/device.rs b/deno_webgpu/device.rs index 2b9c585046b..a9d0048b694 100644 --- a/deno_webgpu/device.rs +++ b/deno_webgpu/device.rs @@ -380,7 +380,7 @@ impl GPUDevice { let wgpu_descriptor = wgpu_core::binding_model::PipelineLayoutDescriptor { label: crate::transform_label(descriptor.label.clone()), bind_group_layouts: Cow::Owned(bind_group_layouts), - immediates_ranges: Default::default(), + immediate_size: 0, }; let (id, err) = self.instance.device_create_pipeline_layout( diff --git a/examples/features/src/big_compute_buffers/mod.rs b/examples/features/src/big_compute_buffers/mod.rs index 10a3039ecac..740b88a099a 100644 --- a/examples/features/src/big_compute_buffers/mod.rs +++ b/examples/features/src/big_compute_buffers/mod.rs @@ -127,7 +127,7 @@ fn setup_pipeline( let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Compute Pipeline Layout"), bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { diff --git a/examples/features/src/boids/mod.rs b/examples/features/src/boids/mod.rs index f48d02033d0..e115dc7990a 100644 --- a/examples/features/src/boids/mod.rs +++ b/examples/features/src/boids/mod.rs @@ -107,7 +107,7 @@ impl crate::framework::Example for Example { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("compute"), bind_group_layouts: &[&compute_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); // create render pipeline with empty bind group layout @@ -116,7 +116,7 @@ impl crate::framework::Example for Example { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("render"), bind_group_layouts: &[], - immediates_ranges: &[], + immediate_size: 0, }); let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { diff --git a/examples/features/src/bunnymark/mod.rs b/examples/features/src/bunnymark/mod.rs index 8299083cd31..abd8e569c5c 100644 --- a/examples/features/src/bunnymark/mod.rs +++ b/examples/features/src/bunnymark/mod.rs @@ -201,7 +201,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&global_bind_group_layout, &local_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { diff --git a/examples/features/src/conservative_raster/mod.rs b/examples/features/src/conservative_raster/mod.rs index ad46fcc85b7..ccd03655ba7 100644 --- a/examples/features/src/conservative_raster/mod.rs +++ b/examples/features/src/conservative_raster/mod.rs @@ -78,7 +78,7 @@ impl crate::framework::Example for Example { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[], - immediates_ranges: &[], + immediate_size: 0, }); let shader_triangle_and_lines = @@ -195,7 +195,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let shader = device.create_shader_module(wgpu::include_wgsl!("upscale.wgsl")); ( diff --git a/examples/features/src/cube/mod.rs b/examples/features/src/cube/mod.rs index 66dc0503273..e3efd32f2ab 100644 --- a/examples/features/src/cube/mod.rs +++ b/examples/features/src/cube/mod.rs @@ -158,7 +158,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); // Create the texture diff --git a/examples/features/src/hello_synchronization/mod.rs b/examples/features/src/hello_synchronization/mod.rs index bce618fba79..804b5800f5e 100644 --- a/examples/features/src/hello_synchronization/mod.rs +++ b/examples/features/src/hello_synchronization/mod.rs @@ -91,7 +91,7 @@ async fn execute( let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let patient_pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { label: None, diff --git a/examples/features/src/hello_triangle/mod.rs b/examples/features/src/hello_triangle/mod.rs index 76afa12256d..67aa7f4b4fe 100644 --- a/examples/features/src/hello_triangle/mod.rs +++ b/examples/features/src/hello_triangle/mod.rs @@ -47,7 +47,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[], - immediates_ranges: &[], + immediate_size: 0, }); let swapchain_capabilities = surface.get_capabilities(&adapter); diff --git a/examples/features/src/hello_workgroups/mod.rs b/examples/features/src/hello_workgroups/mod.rs index a2ed610ad82..33d3c183d2e 100644 --- a/examples/features/src/hello_workgroups/mod.rs +++ b/examples/features/src/hello_workgroups/mod.rs @@ -100,7 +100,7 @@ async fn run() { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { label: None, diff --git a/examples/features/src/mesh_shader/mod.rs b/examples/features/src/mesh_shader/mod.rs index 76f6da1636f..6dfe1d7bbd4 100644 --- a/examples/features/src/mesh_shader/mod.rs +++ b/examples/features/src/mesh_shader/mod.rs @@ -104,7 +104,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = device.create_mesh_pipeline(&wgpu::MeshPipelineDescriptor { label: None, diff --git a/examples/features/src/msaa_line/mod.rs b/examples/features/src/msaa_line/mod.rs index b1a7d26ff08..bcf931681ae 100644 --- a/examples/features/src/msaa_line/mod.rs +++ b/examples/features/src/msaa_line/mod.rs @@ -161,7 +161,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[], - immediates_ranges: &[], + immediate_size: 0, }); let multisampled_framebuffer = diff --git a/examples/features/src/multiple_render_targets/mod.rs b/examples/features/src/multiple_render_targets/mod.rs index b5ef9fa2c4d..b343328a313 100644 --- a/examples/features/src/multiple_render_targets/mod.rs +++ b/examples/features/src/multiple_render_targets/mod.rs @@ -112,7 +112,7 @@ impl MultiTargetRenderer { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&texture_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let sampler = device.create_sampler(&wgpu::SamplerDescriptor { @@ -232,7 +232,7 @@ impl TargetRenderer { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&texture_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let sampler = device.create_sampler(&wgpu::SamplerDescriptor { diff --git a/examples/features/src/ray_shadows/mod.rs b/examples/features/src/ray_shadows/mod.rs index 05baf1a82fb..896c237cd4a 100644 --- a/examples/features/src/ray_shadows/mod.rs +++ b/examples/features/src/ray_shadows/mod.rs @@ -186,10 +186,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[wgpu::ImmediateRange { - stages: wgpu::ShaderStages::FRAGMENT, - range: 0..12, - }], + immediate_size: 12, }); let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { @@ -331,9 +328,9 @@ impl crate::framework::Example for Example { rpass.set_pipeline(&self.pipeline); rpass.set_bind_group(0, Some(&self.bind_group), &[]); - rpass.set_immediates(wgpu::ShaderStages::FRAGMENT, 0, &0.0_f32.to_ne_bytes()); - rpass.set_immediates(wgpu::ShaderStages::FRAGMENT, 4, &cos.to_ne_bytes()); - rpass.set_immediates(wgpu::ShaderStages::FRAGMENT, 8, &sin.to_ne_bytes()); + rpass.set_immediates(0, &0.0_f32.to_ne_bytes()); + rpass.set_immediates(4, &cos.to_ne_bytes()); + rpass.set_immediates(8, &sin.to_ne_bytes()); rpass.set_vertex_buffer(0, self.vertex_buf.slice(..)); rpass.set_index_buffer(self.index_buf.slice(..), IndexFormat::Uint16); rpass.draw_indexed(0..12, 0, 0..1); diff --git a/examples/features/src/ray_traced_triangle/mod.rs b/examples/features/src/ray_traced_triangle/mod.rs index 552a04dac2e..32ada309428 100644 --- a/examples/features/src/ray_traced_triangle/mod.rs +++ b/examples/features/src/ray_traced_triangle/mod.rs @@ -269,7 +269,7 @@ impl crate::framework::Example for Example { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("pipeline layout for shader.wgsl"), bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let compute_pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { @@ -284,7 +284,7 @@ impl crate::framework::Example for Example { let blit_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("pipeline layout for blit.wgsl"), bind_group_layouts: &[&blit_bgl], - immediates_ranges: &[], + immediate_size: 0, }); let blit_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { diff --git a/examples/features/src/repeated_compute/mod.rs b/examples/features/src/repeated_compute/mod.rs index ebdfeea8296..846e0f3f5ce 100644 --- a/examples/features/src/repeated_compute/mod.rs +++ b/examples/features/src/repeated_compute/mod.rs @@ -229,7 +229,7 @@ impl WgpuContext { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { label: None, diff --git a/examples/features/src/shadow/mod.rs b/examples/features/src/shadow/mod.rs index 6f3e325070c..7a4fb9ea97d 100644 --- a/examples/features/src/shadow/mod.rs +++ b/examples/features/src/shadow/mod.rs @@ -466,7 +466,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("shadow"), bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { @@ -582,7 +582,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("main"), bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let mx_total = Self::generate_matrix(config.width as f32 / config.height as f32); diff --git a/examples/features/src/skybox/mod.rs b/examples/features/src/skybox/mod.rs index f121d3b9398..e5c5df7ff75 100644 --- a/examples/features/src/skybox/mod.rs +++ b/examples/features/src/skybox/mod.rs @@ -187,7 +187,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); // Create the render pipelines diff --git a/examples/features/src/srgb_blend/mod.rs b/examples/features/src/srgb_blend/mod.rs index 854f0bb26ac..5b25d870021 100644 --- a/examples/features/src/srgb_blend/mod.rs +++ b/examples/features/src/srgb_blend/mod.rs @@ -92,7 +92,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); // Create bind group diff --git a/examples/features/src/stencil_triangles/mod.rs b/examples/features/src/stencil_triangles/mod.rs index 44560468196..05e782470e1 100644 --- a/examples/features/src/stencil_triangles/mod.rs +++ b/examples/features/src/stencil_triangles/mod.rs @@ -48,7 +48,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[], - immediates_ranges: &[], + immediate_size: 0, }); let shader = device.create_shader_module(wgpu::include_wgsl!("shader.wgsl")); diff --git a/examples/features/src/storage_texture/mod.rs b/examples/features/src/storage_texture/mod.rs index a2448bd266c..1d1cc0bb2c9 100644 --- a/examples/features/src/storage_texture/mod.rs +++ b/examples/features/src/storage_texture/mod.rs @@ -90,7 +90,7 @@ async fn run(_path: Option) { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { label: None, diff --git a/examples/features/src/texture_arrays/mod.rs b/examples/features/src/texture_arrays/mod.rs index 3149f99c488..09135d6bd22 100644 --- a/examples/features/src/texture_arrays/mod.rs +++ b/examples/features/src/texture_arrays/mod.rs @@ -328,7 +328,7 @@ impl crate::framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("main"), bind_group_layouts: &[&bind_group_layout, &uniform_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let index_format = wgpu::IndexFormat::Uint16; diff --git a/examples/features/src/timestamp_queries/mod.rs b/examples/features/src/timestamp_queries/mod.rs index 81b8ae76cb7..e747fa73787 100644 --- a/examples/features/src/timestamp_queries/mod.rs +++ b/examples/features/src/timestamp_queries/mod.rs @@ -351,7 +351,7 @@ fn render_pass( let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[], - immediates_ranges: &[], + immediate_size: 0, }); let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { diff --git a/examples/features/src/uniform_values/mod.rs b/examples/features/src/uniform_values/mod.rs index 11777367bbf..7924b93a836 100644 --- a/examples/features/src/uniform_values/mod.rs +++ b/examples/features/src/uniform_values/mod.rs @@ -162,7 +162,7 @@ impl WgpuContext { label: None, // (4) bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let swapchain_capabilities = surface.get_capabilities(&adapter); diff --git a/examples/features/src/water/mod.rs b/examples/features/src/water/mod.rs index 63a656750fe..e07200fb7b4 100644 --- a/examples/features/src/water/mod.rs +++ b/examples/features/src/water/mod.rs @@ -428,14 +428,14 @@ impl crate::framework::Example for Example { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("water"), bind_group_layouts: &[&water_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let terrain_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("terrain"), bind_group_layouts: &[&terrain_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let water_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { diff --git a/examples/standalone/01_hello_compute/src/main.rs b/examples/standalone/01_hello_compute/src/main.rs index ffc78fa900e..b9b5c431864 100644 --- a/examples/standalone/01_hello_compute/src/main.rs +++ b/examples/standalone/01_hello_compute/src/main.rs @@ -168,7 +168,7 @@ fn main() { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); // The pipeline is the ready-to-go program state for the GPU. It contains the shader modules, diff --git a/player/src/lib.rs b/player/src/lib.rs index a33c2fbb8f2..369e34043a6 100644 --- a/player/src/lib.rs +++ b/player/src/lib.rs @@ -202,7 +202,7 @@ impl Player { let resolved_desc = wgc::binding_model::ResolvedPipelineLayoutDescriptor { label: desc.label.clone(), bind_group_layouts: Cow::from(&bind_group_layouts), - immediates_ranges: Cow::Borrowed(&*desc.immediates_ranges), + immediate_size: desc.immediate_size, }; let pipeline_layout = device @@ -1058,12 +1058,10 @@ impl Player { }, C::SetScissor(rect) => C::SetScissor(rect), C::SetImmediate { - stages, offset, size_bytes, values_offset, } => C::SetImmediate { - stages, offset, size_bytes, values_offset, diff --git a/player/tests/player/data/bind-group.ron b/player/tests/player/data/bind-group.ron index 2a57c99000e..edc72cd7b29 100644 --- a/player/tests/player/data/bind-group.ron +++ b/player/tests/player/data/bind-group.ron @@ -39,7 +39,7 @@ bind_group_layouts: [ PointerId(0x10), ], - immediates_ranges: [], + immediate_size: 0, )), CreateShaderModule( id: PointerId(0x10), diff --git a/player/tests/player/data/pipeline-statistics-query.ron b/player/tests/player/data/pipeline-statistics-query.ron index fc56852bc8a..eea8cfbe181 100644 --- a/player/tests/player/data/pipeline-statistics-query.ron +++ b/player/tests/player/data/pipeline-statistics-query.ron @@ -12,7 +12,7 @@ CreatePipelineLayout(PointerId(0x10), ( label: Some("empty"), bind_group_layouts: [], - immediates_ranges: [], + immediate_size: 0, )), CreateShaderModule( id: PointerId(0x10), diff --git a/player/tests/player/data/quad.ron b/player/tests/player/data/quad.ron index 3aed1dec0ff..1bef1ddd474 100644 --- a/player/tests/player/data/quad.ron +++ b/player/tests/player/data/quad.ron @@ -47,7 +47,7 @@ CreatePipelineLayout(PointerId(0x10), ( label: None, bind_group_layouts: [], - immediates_ranges: [], + immediate_size: 0, )), CreateGeneralRenderPipeline( id: PointerId(0x10), diff --git a/player/tests/player/data/zero-init-buffer.ron b/player/tests/player/data/zero-init-buffer.ron index e727bfd4b23..508651d9e81 100644 --- a/player/tests/player/data/zero-init-buffer.ron +++ b/player/tests/player/data/zero-init-buffer.ron @@ -124,7 +124,7 @@ bind_group_layouts: [ PointerId(0x10), ], - immediates_ranges: [], + immediate_size: 0, )), CreateComputePipeline( id: PointerId(0x10), diff --git a/player/tests/player/data/zero-init-texture-binding.ron b/player/tests/player/data/zero-init-texture-binding.ron index 4825bb8a056..6fa104cfaa0 100644 --- a/player/tests/player/data/zero-init-texture-binding.ron +++ b/player/tests/player/data/zero-init-texture-binding.ron @@ -117,7 +117,7 @@ bind_group_layouts: [ PointerId(0x10), ], - immediates_ranges: [], + immediate_size: 0, )), CreateShaderModule( id: PointerId(0x10), diff --git a/tests/src/image.rs b/tests/src/image.rs index 9a1bd06ae45..659089c5eff 100644 --- a/tests/src/image.rs +++ b/tests/src/image.rs @@ -347,7 +347,7 @@ fn copy_via_compute( let pll = device.create_pipeline_layout(&PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let source = String::from(include_str!("copy_texture_to_buffer.wgsl")); diff --git a/tests/tests/wgpu-gpu/bgra8unorm_storage.rs b/tests/tests/wgpu-gpu/bgra8unorm_storage.rs index 1f85c7f5fdc..abca6ca9169 100644 --- a/tests/tests/wgpu-gpu/bgra8unorm_storage.rs +++ b/tests/tests/wgpu-gpu/bgra8unorm_storage.rs @@ -89,7 +89,7 @@ static BGRA8_UNORM_STORAGE: GpuTestConfiguration = GpuTestConfiguration::new() let pl = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let module = device.create_shader_module(wgpu::ShaderModuleDescriptor { diff --git a/tests/tests/wgpu-gpu/bind_group_layout_dedup.rs b/tests/tests/wgpu-gpu/bind_group_layout_dedup.rs index 7cf5ef7eb84..f57a2d149a4 100644 --- a/tests/tests/wgpu-gpu/bind_group_layout_dedup.rs +++ b/tests/tests/wgpu-gpu/bind_group_layout_dedup.rs @@ -81,7 +81,7 @@ async fn bgl_dedupe(ctx: TestingContext) { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl_1b], - immediates_ranges: &[], + immediate_size: 0, }); let module = ctx @@ -145,7 +145,7 @@ fn bgl_dedupe_with_dropped_user_handle(ctx: TestingContext) { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl_1], - immediates_ranges: &[], + immediate_size: 0, }); // We drop bgl_1 here. As bgl_1 is still alive, referenced by the pipeline layout, diff --git a/tests/tests/wgpu-gpu/bind_groups.rs b/tests/tests/wgpu-gpu/bind_groups.rs index 66b28b94dd9..3fece97ec03 100644 --- a/tests/tests/wgpu-gpu/bind_groups.rs +++ b/tests/tests/wgpu-gpu/bind_groups.rs @@ -70,7 +70,7 @@ fn multiple_bindings_with_differing_sizes(ctx: TestingContext) { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("pipeline_layout"), bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let pipelines = SHADER_SRC diff --git a/tests/tests/wgpu-gpu/binding_array/buffers.rs b/tests/tests/wgpu-gpu/binding_array/buffers.rs index 913cc2934ad..e3c4c142512 100644 --- a/tests/tests/wgpu-gpu/binding_array/buffers.rs +++ b/tests/tests/wgpu-gpu/binding_array/buffers.rs @@ -228,7 +228,7 @@ async fn binding_array_buffers( .create_pipeline_layout(&PipelineLayoutDescriptor { label: Some("Pipeline Layout"), bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = ctx diff --git a/tests/tests/wgpu-gpu/binding_array/sampled_textures.rs b/tests/tests/wgpu-gpu/binding_array/sampled_textures.rs index 8c67b9ac226..048e41077cc 100644 --- a/tests/tests/wgpu-gpu/binding_array/sampled_textures.rs +++ b/tests/tests/wgpu-gpu/binding_array/sampled_textures.rs @@ -181,7 +181,7 @@ async fn binding_array_sampled_textures(ctx: TestingContext, partially_bound: bo .create_pipeline_layout(&PipelineLayoutDescriptor { label: Some("Pipeline Layout"), bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = ctx diff --git a/tests/tests/wgpu-gpu/binding_array/samplers.rs b/tests/tests/wgpu-gpu/binding_array/samplers.rs index 61407b53057..1375aeeb1ba 100644 --- a/tests/tests/wgpu-gpu/binding_array/samplers.rs +++ b/tests/tests/wgpu-gpu/binding_array/samplers.rs @@ -214,7 +214,7 @@ async fn binding_array_samplers(ctx: TestingContext, partially_bound: bool) { .create_pipeline_layout(&PipelineLayoutDescriptor { label: Some("Pipeline Layout"), bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = ctx diff --git a/tests/tests/wgpu-gpu/binding_array/storage_textures.rs b/tests/tests/wgpu-gpu/binding_array/storage_textures.rs index 0acc84f1eb2..b5045c13c02 100644 --- a/tests/tests/wgpu-gpu/binding_array/storage_textures.rs +++ b/tests/tests/wgpu-gpu/binding_array/storage_textures.rs @@ -174,7 +174,7 @@ async fn binding_array_storage_textures(ctx: TestingContext, partially_bound: bo .create_pipeline_layout(&PipelineLayoutDescriptor { label: Some("Pipeline Layout"), bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = ctx diff --git a/tests/tests/wgpu-gpu/buffer.rs b/tests/tests/wgpu-gpu/buffer.rs index 4e51038d39d..4578ff4fff4 100644 --- a/tests/tests/wgpu-gpu/buffer.rs +++ b/tests/tests/wgpu-gpu/buffer.rs @@ -233,7 +233,7 @@ static MINIMUM_BUFFER_BINDING_SIZE_LAYOUT: GpuTestConfiguration = GpuTestConfigu .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); wgpu_test::fail( @@ -307,7 +307,7 @@ static MINIMUM_BUFFER_BINDING_SIZE_DISPATCH: GpuTestConfiguration = GpuTestConfi .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = ctx diff --git a/tests/tests/wgpu-gpu/compute_pass_ownership.rs b/tests/tests/wgpu-gpu/compute_pass_ownership.rs index 1a6e34ead4d..f5855cb9705 100644 --- a/tests/tests/wgpu-gpu/compute_pass_ownership.rs +++ b/tests/tests/wgpu-gpu/compute_pass_ownership.rs @@ -323,7 +323,7 @@ fn resource_setup(ctx: &TestingContext) -> ResourceSetup { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("pipeline_layout"), bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = ctx diff --git a/tests/tests/wgpu-gpu/device.rs b/tests/tests/wgpu-gpu/device.rs index aca0e619857..7c802afcc83 100644 --- a/tests/tests/wgpu-gpu/device.rs +++ b/tests/tests/wgpu-gpu/device.rs @@ -440,7 +440,7 @@ static DEVICE_DESTROY_THEN_MORE: GpuTestConfiguration = GpuTestConfiguration::ne .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&invalid_bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let _ = ctx diff --git a/tests/tests/wgpu-gpu/dispatch_workgroups_indirect.rs b/tests/tests/wgpu-gpu/dispatch_workgroups_indirect.rs index 900f84b3bb2..d8a6e3a4baa 100644 --- a/tests/tests/wgpu-gpu/dispatch_workgroups_indirect.rs +++ b/tests/tests/wgpu-gpu/dispatch_workgroups_indirect.rs @@ -207,10 +207,7 @@ impl TestResources { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl], - immediates_ranges: &[wgpu::ImmediateRange { - stages: wgpu::ShaderStages::COMPUTE, - range: 0..4, - }], + immediate_size: 4, }); let pipeline = ctx diff --git a/tests/tests/wgpu-gpu/image_atomics/mod.rs b/tests/tests/wgpu-gpu/image_atomics/mod.rs index e6babc0e385..8cc092b2186 100644 --- a/tests/tests/wgpu-gpu/image_atomics/mod.rs +++ b/tests/tests/wgpu-gpu/image_atomics/mod.rs @@ -101,7 +101,7 @@ async fn test_format( .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let shader = ctx.device.create_shader_module(desc); let pipeline = ctx diff --git a/tests/tests/wgpu-gpu/immediates.rs b/tests/tests/wgpu-gpu/immediates.rs index 629d0ef242c..e938451fd49 100644 --- a/tests/tests/wgpu-gpu/immediates.rs +++ b/tests/tests/wgpu-gpu/immediates.rs @@ -99,10 +99,7 @@ async fn partial_update_test(ctx: TestingContext) { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("pipeline_layout"), bind_group_layouts: &[&bgl], - immediates_ranges: &[wgpu::ImmediateRange { - stages: wgpu::ShaderStages::COMPUTE, - range: 0..32, - }], + immediate_size: 32, }); let pipeline = ctx @@ -271,10 +268,7 @@ async fn render_pass_test(ctx: &TestingContext, use_render_bundle: bool) { .device .create_pipeline_layout(&PipelineLayoutDescriptor { bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[ImmediateRange { - stages: ShaderStages::VERTEX_FRAGMENT, - range: 0..8 * size_of::() as u32, - }], + immediate_size: 8 * size_of::() as u32, ..Default::default() }); @@ -338,7 +332,7 @@ async fn render_pass_test(ctx: &TestingContext, use_render_bundle: bool) { ) { let data_as_u8: &[u8] = bytemuck::cast_slice(data.as_slice()); encoder.set_pipeline(pipeline); - encoder.set_immediates(ShaderStages::VERTEX_FRAGMENT, 0, data_as_u8); + encoder.set_immediates(0, data_as_u8); encoder.set_bind_group(0, Some(bind_group), &[]); encoder.draw(0..4, 0..1); } diff --git a/tests/tests/wgpu-gpu/mem_leaks.rs b/tests/tests/wgpu-gpu/mem_leaks.rs index a6fc758a97a..1d223d5d955 100644 --- a/tests/tests/wgpu-gpu/mem_leaks.rs +++ b/tests/tests/wgpu-gpu/mem_leaks.rs @@ -92,7 +92,7 @@ async fn draw_test_with_reports( .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let global_report = ctx.instance.generate_report().unwrap(); diff --git a/tests/tests/wgpu-gpu/mesh_shader/mod.rs b/tests/tests/wgpu-gpu/mesh_shader/mod.rs index 9178b215a09..a76cbcc8061 100644 --- a/tests/tests/wgpu-gpu/mesh_shader/mod.rs +++ b/tests/tests/wgpu-gpu/mesh_shader/mod.rs @@ -211,7 +211,7 @@ fn mesh_pipeline_build(ctx: &TestingContext, info: MeshPipelineTestInfo) { let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = device.create_mesh_pipeline(&wgpu::MeshPipelineDescriptor { label: None, @@ -299,7 +299,7 @@ fn mesh_draw(ctx: &TestingContext, draw_type: DrawType) { let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = device.create_mesh_pipeline(&wgpu::MeshPipelineDescriptor { label: None, diff --git a/tests/tests/wgpu-gpu/oob_indexing.rs b/tests/tests/wgpu-gpu/oob_indexing.rs index 04cd502afa1..9c2fc7d6ec0 100644 --- a/tests/tests/wgpu-gpu/oob_indexing.rs +++ b/tests/tests/wgpu-gpu/oob_indexing.rs @@ -178,7 +178,7 @@ impl TestResources { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = ctx @@ -342,7 +342,7 @@ async fn d3d12_restrict_dynamic_buffers(ctx: TestingContext) { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let pipeline = ctx diff --git a/tests/tests/wgpu-gpu/pipeline_cache.rs b/tests/tests/wgpu-gpu/pipeline_cache.rs index f9103fbe402..04c6beec7ca 100644 --- a/tests/tests/wgpu-gpu/pipeline_cache.rs +++ b/tests/tests/wgpu-gpu/pipeline_cache.rs @@ -98,7 +98,7 @@ async fn pipeline_cache_test(ctx: TestingContext) { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("pipeline_layout"), bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let first_cache_data; diff --git a/tests/tests/wgpu-gpu/regression/issue_3349.rs b/tests/tests/wgpu-gpu/regression/issue_3349.rs index 706db27427a..006d4b51c95 100644 --- a/tests/tests/wgpu-gpu/regression/issue_3349.rs +++ b/tests/tests/wgpu-gpu/regression/issue_3349.rs @@ -93,10 +93,7 @@ async fn multi_stage_data_binding_test(ctx: TestingContext) { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("pll"), bind_group_layouts: &[&bgl], - immediates_ranges: &[wgpu::ImmediateRange { - stages: wgpu::ShaderStages::VERTEX_FRAGMENT, - range: 0..16, - }], + immediate_size: 16, }); let pipeline = ctx @@ -171,11 +168,7 @@ async fn multi_stage_data_binding_test(ctx: TestingContext) { rpass.set_pipeline(&pipeline); rpass.set_bind_group(0, &bg, &[]); - rpass.set_immediates( - wgpu::ShaderStages::VERTEX_FRAGMENT, - 0, - bytemuck::cast_slice(&input), - ); + rpass.set_immediates(0, bytemuck::cast_slice(&input)); rpass.draw(0..3, 0..1); } diff --git a/tests/tests/wgpu-gpu/regression/issue_3457.rs b/tests/tests/wgpu-gpu/regression/issue_3457.rs index d3591763b28..731e1896b36 100644 --- a/tests/tests/wgpu-gpu/regression/issue_3457.rs +++ b/tests/tests/wgpu-gpu/regression/issue_3457.rs @@ -46,7 +46,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration = GpuTestConfiguration::ne .create_pipeline_layout(&PipelineLayoutDescriptor { label: Some("Pipeline Layout"), bind_group_layouts: &[], - immediates_ranges: &[], + immediate_size: 0, }); let double_pipeline = ctx diff --git a/tests/tests/wgpu-gpu/regression/issue_5553.rs b/tests/tests/wgpu-gpu/regression/issue_5553.rs index d608461df1e..68a32b37172 100644 --- a/tests/tests/wgpu-gpu/regression/issue_5553.rs +++ b/tests/tests/wgpu-gpu/regression/issue_5553.rs @@ -26,7 +26,7 @@ static ALLOW_INPUT_NOT_CONSUMED: GpuTestConfiguration = GpuTestConfiguration::ne .create_pipeline_layout(&PipelineLayoutDescriptor { label: Some("Pipeline Layout"), bind_group_layouts: &[], - immediates_ranges: &[], + immediate_size: 0, }); let _ = ctx diff --git a/tests/tests/wgpu-gpu/render_pass_ownership.rs b/tests/tests/wgpu-gpu/render_pass_ownership.rs index 67e93b26a30..140851d6937 100644 --- a/tests/tests/wgpu-gpu/render_pass_ownership.rs +++ b/tests/tests/wgpu-gpu/render_pass_ownership.rs @@ -464,7 +464,7 @@ fn resource_setup(ctx: &TestingContext) -> ResourceSetup { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("pipeline_layout"), bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let target_size = wgpu::Extent3d { diff --git a/tests/tests/wgpu-gpu/samplers.rs b/tests/tests/wgpu-gpu/samplers.rs index 43cab45a001..a2e62262375 100644 --- a/tests/tests/wgpu-gpu/samplers.rs +++ b/tests/tests/wgpu-gpu/samplers.rs @@ -335,7 +335,7 @@ fn sampler_bind_group(ctx: TestingContext, group_type: GroupType) { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("pipeline_layout"), bind_group_layouts: &bgl_references, - immediates_ranges: &[], + immediate_size: 0, }); let input_image = ctx.device.create_texture(&wgpu::TextureDescriptor { diff --git a/tests/tests/wgpu-gpu/shader/mod.rs b/tests/tests/wgpu-gpu/shader/mod.rs index 1b287ed0a1a..21d5a9dab40 100644 --- a/tests/tests/wgpu-gpu/shader/mod.rs +++ b/tests/tests/wgpu-gpu/shader/mod.rs @@ -9,8 +9,8 @@ use std::{borrow::Cow, fmt::Debug}; use wgpu::{ Backends, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, ComputePassDescriptor, - ComputePipelineDescriptor, ImmediateRange, MapMode, PipelineLayoutDescriptor, PollType, - ShaderModuleDescriptor, ShaderSource, ShaderStages, + ComputePipelineDescriptor, MapMode, PipelineLayoutDescriptor, PollType, ShaderModuleDescriptor, + ShaderSource, ShaderStages, }; use wgpu_test::{GpuTestInitializer, TestingContext}; @@ -280,12 +280,9 @@ async fn shader_input_output_test( .create_pipeline_layout(&PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl], - immediates_ranges: match storage_type { - InputStorageType::Immediate => &[ImmediateRange { - stages: ShaderStages::COMPUTE, - range: 0..MAX_BUFFER_SIZE as u32, - }], - _ => &[], + immediate_size: match storage_type { + InputStorageType::Immediate => MAX_BUFFER_SIZE as u32, + _ => 0, }, }); diff --git a/tests/tests/wgpu-gpu/shader/zero_init_workgroup_mem.rs b/tests/tests/wgpu-gpu/shader/zero_init_workgroup_mem.rs index efffa3431d2..2cae287ff7d 100644 --- a/tests/tests/wgpu-gpu/shader/zero_init_workgroup_mem.rs +++ b/tests/tests/wgpu-gpu/shader/zero_init_workgroup_mem.rs @@ -70,7 +70,7 @@ static ZERO_INIT_WORKGROUP_MEMORY: GpuTestConfiguration = GpuTestConfiguration:: .create_pipeline_layout(&PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let sm = ctx diff --git a/tests/tests/wgpu-gpu/subgroup_operations/mod.rs b/tests/tests/wgpu-gpu/subgroup_operations/mod.rs index b6396c799bf..9aaf9446575 100644 --- a/tests/tests/wgpu-gpu/subgroup_operations/mod.rs +++ b/tests/tests/wgpu-gpu/subgroup_operations/mod.rs @@ -69,7 +69,7 @@ static SUBGROUP_OPERATIONS: GpuTestConfiguration = GpuTestConfiguration::new() let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("main"), bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let compute_pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { diff --git a/tests/tests/wgpu-gpu/vertex_formats/mod.rs b/tests/tests/wgpu-gpu/vertex_formats/mod.rs index 114477516f2..65c858c6712 100644 --- a/tests/tests/wgpu-gpu/vertex_formats/mod.rs +++ b/tests/tests/wgpu-gpu/vertex_formats/mod.rs @@ -254,7 +254,7 @@ async fn vertex_formats_common(ctx: TestingContext, tests: &[Test<'_>]) { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let dummy = ctx diff --git a/tests/tests/wgpu-gpu/vertex_indices/mod.rs b/tests/tests/wgpu-gpu/vertex_indices/mod.rs index 8d3f8bfd1e7..38fb47573dc 100644 --- a/tests/tests/wgpu-gpu/vertex_indices/mod.rs +++ b/tests/tests/wgpu-gpu/vertex_indices/mod.rs @@ -234,7 +234,7 @@ async fn vertex_index_common(ctx: TestingContext) { .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }); let mut pipeline_desc = wgpu::RenderPipelineDescriptor { diff --git a/wgpu-core/src/binding_model.rs b/wgpu-core/src/binding_model.rs index 10b17f4d566..e3a58f5116c 100644 --- a/wgpu-core/src/binding_model.rs +++ b/wgpu-core/src/binding_model.rs @@ -18,9 +18,7 @@ use serde::Serialize; use wgt::error::{ErrorType, WebGpuError}; use crate::{ - device::{ - bgl, Device, DeviceError, MissingDownlevelFlags, MissingFeatures, SHADER_STAGE_COUNT, - }, + device::{bgl, Device, DeviceError, MissingDownlevelFlags, MissingFeatures}, id::{BindGroupLayoutId, BufferId, ExternalTextureId, SamplerId, TextureViewId, TlasId}, init_tracker::{BufferInitTrackerAction, TextureInitTrackerAction}, pipeline::{ComputePipeline, RenderPipeline}, @@ -777,24 +775,16 @@ pub enum CreatePipelineLayoutError { #[error(transparent)] Device(#[from] DeviceError), #[error( - "Immediate data at index {index} has range bound {bound} not aligned to {}", - wgt::IMMEDIATES_ALIGNMENT + "Immediate data has range bound {size} which is not aligned to IMMEDIATE_DATA_ALIGNMENT ({})", + wgt::IMMEDIATE_DATA_ALIGNMENT )] - MisalignedImmediateRange { index: usize, bound: u32 }, + MisalignedImmediateSize { size: u32 }, #[error(transparent)] MissingFeatures(#[from] MissingFeatures), - #[error("Immediate data range (index {index}) provides for stage(s) {provided:?} but there exists another range that provides stage(s) {intersected:?}. Each stage may only be provided by one range")] - MoreThanOneImmediateRangePerStage { - index: usize, - provided: wgt::ShaderStages, - intersected: wgt::ShaderStages, - }, - #[error("Immediate data at index {index} has range {}..{} which exceeds device immediate data size limit 0..{max}", range.start, range.end)] - ImmediateRangeTooLarge { - index: usize, - range: Range, - max: u32, - }, + #[error( + "Immediate data has size {size} which exceeds device immediate data size limit 0..{max}" + )] + ImmediateRangeTooLarge { size: u32, max: u32 }, #[error(transparent)] TooManyBindings(BindingTypeMaxCountError), #[error("Bind group layout count {actual} exceeds device bind group limit {max}")] @@ -810,8 +800,7 @@ impl WebGpuError for CreatePipelineLayoutError { Self::MissingFeatures(e) => e, Self::InvalidResource(e) => e, Self::TooManyBindings(e) => e, - Self::MisalignedImmediateRange { .. } - | Self::MoreThanOneImmediateRangePerStage { .. } + Self::MisalignedImmediateSize { .. } | Self::ImmediateRangeTooLarge { .. } | Self::TooManyGroups { .. } => return ErrorType::Validation, }; @@ -822,31 +811,16 @@ impl WebGpuError for CreatePipelineLayoutError { #[derive(Clone, Debug, Error)] #[non_exhaustive] pub enum ImmediateUploadError { - #[error("Provided immediate data with indices {offset}..{end_offset} overruns matching immediate data range at index {idx}, with stage(s) {:?} and indices {:?}", range.stages, range.range)] + #[error("Provided immediate data written to offset {offset}..{end_offset} overruns the immediate data range with a size of {size}")] TooLarge { offset: u32, end_offset: u32, - idx: usize, - range: wgt::ImmediateRange, - }, - #[error("Provided immediate data is for stage(s) {actual:?}, stage with a partial match found at index {idx} with stage(s) {matched:?}, however immediates must be complete matches")] - PartialRangeMatch { - actual: wgt::ShaderStages, - idx: usize, - matched: wgt::ShaderStages, - }, - #[error("Provided immediate data is for stage(s) {actual:?}, but intersects a immediate data range (at index {idx}) with stage(s) {missing:?}. Immediates must provide the stages for all ranges they intersect")] - MissingStages { - actual: wgt::ShaderStages, - idx: usize, - missing: wgt::ShaderStages, - }, - #[error("Provided immediate data is for stage(s) {actual:?}, however the pipeline layout has no immediate data range for the stage(s) {unmatched:?}")] - UnmatchedStages { - actual: wgt::ShaderStages, - unmatched: wgt::ShaderStages, + size: u32, }, - #[error("Provided immediate data offset {0} does not respect `IMMEDIATES_ALIGNMENT`")] + #[error( + "Provided immediate data offset {0} does not respect `IMMEDIATE_DATA_ALIGNMENT` ({ida})", + ida = wgt::IMMEDIATE_DATA_ALIGNMENT + )] Unaligned(u32), } @@ -878,14 +852,12 @@ where serde(bound(deserialize = "<[BGL] as ToOwned>::Owned: Deserialize<'de>")) )] pub bind_group_layouts: Cow<'a, [BGL]>, - /// Set of immediate data ranges this pipeline uses. Each shader stage that - /// uses immediates must define the range in immediate data memory that - /// corresponds to its single `layout(immediates)` uniform block. + /// The number of bytes of immediate data that are allocated for use + /// in the shader. The `var`s in the shader attached to + /// this pipeline must be equal or smaller than this size. /// - /// If this array is non-empty, the - /// [`Features::IMMEDIATES`](wgt::Features::IMMEDIATES) feature must - /// be enabled. - pub immediates_ranges: Cow<'a, [wgt::ImmediateRange]>, + /// If this value is non-zero, [`wgt::Features::IMMEDIATES`] must be enabled. + pub immediate_size: u32, } /// cbindgen:ignore @@ -899,7 +871,7 @@ pub struct PipelineLayout { /// The `label` from the descriptor used to create the resource. pub(crate) label: String, pub(crate) bind_group_layouts: ArrayVec, { hal::MAX_BIND_GROUPS }>, - pub(crate) immediates_ranges: ArrayVec, + pub(crate) immediate_size: u32, } impl Drop for PipelineLayout { @@ -928,7 +900,6 @@ impl PipelineLayout { /// Validate immediates match up with expected ranges. pub(crate) fn validate_immediates_ranges( &self, - stages: wgt::ShaderStages, offset: u32, end_offset: u32, ) -> Result<(), ImmediateUploadError> { @@ -936,68 +907,15 @@ impl PipelineLayout { // as immediate data ranges are already validated to be within bounds, // and we validate that they are within the ranges. - if offset % wgt::IMMEDIATES_ALIGNMENT != 0 { + if offset % wgt::IMMEDIATE_DATA_ALIGNMENT != 0 { return Err(ImmediateUploadError::Unaligned(offset)); } - // Immediate data validation looks very complicated on the surface, but - // the problem can be range-reduced pretty well. - // - // Immediates require (summarized from the vulkan spec): - // 1. For each byte in the range and for each shader stage in stageFlags, - // there must be a immediate data range in the layout that includes that - // byte and that stage. - // 2. For each byte in the range and for each immediate data range that overlaps that byte, - // `stage` must include all stages in that immediate data range’s `stage`. - // - // However there are some additional constraints that help us: - // 3. All immediate data ranges are the only range that can access that stage. - // i.e. if one range has VERTEX, no other range has VERTEX - // - // Therefore we can simplify the checks in the following ways: - // - Because 3 guarantees that the immediate data range has a unique stage, - // when we check for 1, we can simply check that our entire updated range - // is within a immediate data range. i.e. our range for a specific stage cannot - // intersect more than one immediate data range. - let mut used_stages = wgt::ShaderStages::NONE; - for (idx, range) in self.immediates_ranges.iter().enumerate() { - // contains not intersects due to 2 - if stages.contains(range.stages) { - if !(range.range.start <= offset && end_offset <= range.range.end) { - return Err(ImmediateUploadError::TooLarge { - offset, - end_offset, - idx, - range: range.clone(), - }); - } - used_stages |= range.stages; - } else if stages.intersects(range.stages) { - // Will be caught by used stages check below, but we can do this because of 1 - // and is more helpful to the user. - return Err(ImmediateUploadError::PartialRangeMatch { - actual: stages, - idx, - matched: range.stages, - }); - } - - // The immediate data range intersects range we are uploading - if offset < range.range.end && range.range.start < end_offset { - // But requires stages we don't provide - if !stages.contains(range.stages) { - return Err(ImmediateUploadError::MissingStages { - actual: stages, - idx, - missing: stages, - }); - } - } - } - if used_stages != stages { - return Err(ImmediateUploadError::UnmatchedStages { - actual: stages, - unmatched: stages - used_stages, + if end_offset > self.immediate_size { + return Err(ImmediateUploadError::TooLarge { + offset, + end_offset, + size: self.immediate_size, }); } Ok(()) diff --git a/wgpu-core/src/command/bind.rs b/wgpu-core/src/command/bind.rs index 8e9541242da..d17144a2702 100644 --- a/wgpu-core/src/command/bind.rs +++ b/wgpu-core/src/command/bind.rs @@ -2,12 +2,10 @@ use core::{iter::zip, ops::Range}; use alloc::{boxed::Box, sync::Arc, vec::Vec}; -use arrayvec::ArrayVec; use thiserror::Error; use crate::{ binding_model::{BindGroup, LateMinBufferBindingSizeMismatch, PipelineLayout}, - device::SHADER_STAGE_COUNT, pipeline::LateSizedBufferGroup, resource::{Labeled, ResourceErrorIdent}, }; @@ -376,7 +374,7 @@ impl Binder { if let Some(old) = old_id_opt { // root constants are the base compatibility property - if old.immediates_ranges != new.immediates_ranges { + if old.immediate_size != new.immediate_size { self.manager.update_start_index(0); } } @@ -498,54 +496,3 @@ impl Binder { Ok(()) } } - -struct ImmediateChange { - stages: wgt::ShaderStages, - offset: u32, - enable: bool, -} - -/// Break up possibly overlapping immediate data ranges into a set of -/// non-overlapping ranges which contain all the stage flags of the -/// original ranges. This allows us to zero out (or write any value) -/// to every possible value. -pub fn compute_nonoverlapping_ranges( - ranges: &[wgt::ImmediateRange], -) -> ArrayVec { - if ranges.is_empty() { - return ArrayVec::new(); - } - debug_assert!(ranges.len() <= SHADER_STAGE_COUNT); - - let mut breaks: ArrayVec = ArrayVec::new(); - for range in ranges { - breaks.push(ImmediateChange { - stages: range.stages, - offset: range.range.start, - enable: true, - }); - breaks.push(ImmediateChange { - stages: range.stages, - offset: range.range.end, - enable: false, - }); - } - breaks.sort_unstable_by_key(|change| change.offset); - - let mut output_ranges = ArrayVec::new(); - let mut position = 0_u32; - let mut stages = wgt::ShaderStages::NONE; - - for bk in breaks { - if bk.offset - position > 0 && !stages.is_empty() { - output_ranges.push(wgt::ImmediateRange { - stages, - range: position..bk.offset, - }) - } - position = bk.offset; - stages.set(bk.stages, bk.enable); - } - - output_ranges -} diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index 5769e4d8aa4..3e029199ace 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -104,10 +104,7 @@ use crate::{ BasePass, BindGroupStateChange, ColorAttachmentError, DrawError, IdReferences, MapPassErr, PassErrorScope, RenderCommand, RenderCommandError, StateChange, }, - device::{ - AttachmentData, Device, DeviceError, MissingDownlevelFlags, RenderPassContext, - SHADER_STAGE_COUNT, - }, + device::{AttachmentData, Device, DeviceError, MissingDownlevelFlags, RenderPassContext}, hub::Hub, id, init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction}, @@ -355,13 +352,12 @@ impl RenderBundleEncoder { .map_pass_err(scope)?; } &RenderCommand::SetImmediate { - stages, offset, size_bytes, values_offset, } => { let scope = PassErrorScope::SetImmediate; - set_immediates(&mut state, stages, offset, size_bytes, values_offset) + set_immediates(&mut state, offset, size_bytes, values_offset) .map_pass_err(scope)?; } &RenderCommand::Draw { @@ -615,8 +611,8 @@ fn set_pipeline( .push(ArcRenderCommand::SetPipeline(pipeline.clone())); // If this pipeline uses immediates, zero out their values. - if let Some(iter) = pipeline_state.zero_immediates() { - state.commands.extend(iter) + if let Some(cmd) = pipeline_state.zero_immediates() { + state.commands.push(cmd); } state.invalidate_bind_groups(&pipeline_state, &pipeline.layout); @@ -711,7 +707,6 @@ fn set_vertex_buffer( fn set_immediates( state: &mut State, - stages: wgt::ShaderStages, offset: u32, size_bytes: u32, values_offset: Option, @@ -723,10 +718,9 @@ fn set_immediates( pipeline_state .pipeline .layout - .validate_immediates_ranges(stages, offset, end_offset)?; + .validate_immediates_ranges(offset, end_offset)?; state.commands.push(ArcRenderCommand::SetImmediate { - stages, offset, size_bytes, values_offset, @@ -1056,7 +1050,6 @@ impl RenderBundle { unsafe { raw.set_vertex_buffer(*slot, bb) }; } Cmd::SetImmediate { - stages, offset, size_bytes, values_offset, @@ -1065,13 +1058,11 @@ impl RenderBundle { if let Some(values_offset) = *values_offset { let values_end_offset = - (values_offset + size_bytes / wgt::IMMEDIATES_ALIGNMENT) as usize; + (values_offset + size_bytes / wgt::IMMEDIATE_DATA_ALIGNMENT) as usize; let data_slice = &self.base.immediates_data[(values_offset as usize)..values_end_offset]; - unsafe { - raw.set_immediates(pipeline_layout.raw(), *stages, *offset, data_slice) - } + unsafe { raw.set_immediates(pipeline_layout.raw(), *offset, data_slice) } } else { super::immediates_clear( *offset, @@ -1080,7 +1071,6 @@ impl RenderBundle { unsafe { raw.set_immediates( pipeline_layout.raw(), - *stages, clear_offset, clear_data, ) @@ -1333,9 +1323,8 @@ struct PipelineState { /// by vertex buffer slot number. steps: Vec, - /// Ranges of immediates this pipeline uses, copied from the pipeline - /// layout. - immediates_ranges: ArrayVec, + /// Size of the immediate data ranges this pipeline uses. Copied from the pipeline layout. + immediate_size: u32, /// The number of bind groups this pipeline uses. used_bind_groups: usize, @@ -1346,31 +1335,23 @@ impl PipelineState { Self { pipeline: pipeline.clone(), steps: pipeline.vertex_steps.to_vec(), - immediates_ranges: pipeline.layout.immediates_ranges.iter().cloned().collect(), + immediate_size: pipeline.layout.immediate_size, used_bind_groups: pipeline.layout.bind_group_layouts.len(), } } /// Return a sequence of commands to zero the immediate data ranges this /// pipeline uses. If no initialization is necessary, return `None`. - fn zero_immediates(&self) -> Option> { - if !self.immediates_ranges.is_empty() { - let nonoverlapping_ranges = - super::bind::compute_nonoverlapping_ranges(&self.immediates_ranges); - - Some( - nonoverlapping_ranges - .into_iter() - .map(|range| ArcRenderCommand::SetImmediate { - stages: range.stages, - offset: range.range.start, - size_bytes: range.range.end - range.range.start, - values_offset: None, // write zeros - }), - ) - } else { - None + fn zero_immediates(&self) -> Option { + if self.immediate_size == 0 { + return None; } + + Some(ArcRenderCommand::SetImmediate { + offset: 0, + size_bytes: self.immediate_size, + values_offset: None, + }) } } @@ -1487,7 +1468,7 @@ impl State { } // Any immediate data change invalidates all groups. - if old.immediates_ranges != new.immediates_ranges { + if old.immediate_size != new.immediate_size { self.invalidate_bind_group_from(0); } else { let first_changed = self.bind.iter().zip(&layout.bind_group_layouts).position( @@ -1739,18 +1720,17 @@ pub mod bundle_ffi { /// valid for `data` elements. pub unsafe fn wgpu_render_bundle_set_immediates( pass: &mut RenderBundleEncoder, - stages: wgt::ShaderStages, offset: u32, size_bytes: u32, data: *const u8, ) { assert_eq!( - offset & (wgt::IMMEDIATES_ALIGNMENT - 1), + offset & (wgt::IMMEDIATE_DATA_ALIGNMENT - 1), 0, "Immediate data offset must be aligned to 4 bytes." ); assert_eq!( - size_bytes & (wgt::IMMEDIATES_ALIGNMENT - 1), + size_bytes & (wgt::IMMEDIATE_DATA_ALIGNMENT - 1), 0, "Immediate data size must be aligned to 4 bytes." ); @@ -1761,12 +1741,11 @@ pub mod bundle_ffi { pass.base.immediates_data.extend( data_slice - .chunks_exact(wgt::IMMEDIATES_ALIGNMENT as usize) + .chunks_exact(wgt::IMMEDIATE_DATA_ALIGNMENT as usize) .map(|arr| u32::from_ne_bytes([arr[0], arr[1], arr[2], arr[3]])), ); pass.base.commands.push(RenderCommand::SetImmediate { - stages, offset, size_bytes, values_offset: Some(value_offset), diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index 78c612f4798..2b227dda7ff 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -668,13 +668,13 @@ pub(super) fn encode_compute_pass( pass::set_immediates::( &mut state.pass, &base.immediates_data, - wgt::ShaderStages::COMPUTE, offset, size_bytes, Some(values_offset), |data_slice| { - let offset_in_elements = (offset / wgt::IMMEDIATES_ALIGNMENT) as usize; - let size_in_elements = (size_bytes / wgt::IMMEDIATES_ALIGNMENT) as usize; + let offset_in_elements = (offset / wgt::IMMEDIATE_DATA_ALIGNMENT) as usize; + let size_in_elements = + (size_bytes / wgt::IMMEDIATE_DATA_ALIGNMENT) as usize; state.immediates[offset_in_elements..][..size_in_elements] .copy_from_slice(data_slice); }, @@ -828,15 +828,10 @@ fn set_pipeline( // validating indirect draws. state.immediates.clear(); // Note that can only be one range for each stage. See the `MoreThanOneImmediateRangePerStage` error. - if let Some(immediates_range) = - pipeline.layout.immediates_ranges.iter().find_map(|pcr| { - pcr.stages - .contains(wgt::ShaderStages::COMPUTE) - .then_some(pcr.range.clone()) - }) - { + if pipeline.layout.immediate_size != 0 { // Note that non-0 range start doesn't work anyway https://github.com/gfx-rs/wgpu/issues/4502 - let len = immediates_range.len() / wgt::IMMEDIATES_ALIGNMENT as usize; + let len = pipeline.layout.immediate_size as usize + / wgt::IMMEDIATE_DATA_ALIGNMENT as usize; state.immediates.extend(core::iter::repeat_n(0, len)); } }, @@ -937,7 +932,6 @@ fn dispatch_indirect( unsafe { state.pass.base.raw_encoder.set_immediates( params.pipeline_layout, - wgt::ShaderStages::COMPUTE, 0, &[params.offset_remainder as u32 / 4], ); @@ -1015,7 +1009,6 @@ fn dispatch_indirect( unsafe { state.pass.base.raw_encoder.set_immediates( pipeline.layout.raw(), - wgt::ShaderStages::COMPUTE, 0, &state.immediates, ); @@ -1163,7 +1156,7 @@ impl Global { let scope = PassErrorScope::SetImmediate; let base = pass_base!(pass, scope); - if offset & (wgt::IMMEDIATES_ALIGNMENT - 1) != 0 { + if offset & (wgt::IMMEDIATE_DATA_ALIGNMENT - 1) != 0 { pass_try!( base, scope, @@ -1171,7 +1164,7 @@ impl Global { ); } - if data.len() as u32 & (wgt::IMMEDIATES_ALIGNMENT - 1) != 0 { + if data.len() as u32 & (wgt::IMMEDIATE_DATA_ALIGNMENT - 1) != 0 { pass_try!( base, scope, @@ -1188,7 +1181,7 @@ impl Global { ); base.immediates_data.extend( - data.chunks_exact(wgt::IMMEDIATES_ALIGNMENT as usize) + data.chunks_exact(wgt::IMMEDIATE_DATA_ALIGNMENT as usize) .map(|arr| u32::from_ne_bytes([arr[0], arr[1], arr[2], arr[3]])), ); diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index 384e55e8a26..470277c4a1a 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -1776,9 +1776,9 @@ where PushFn: FnMut(u32, &[u32]), { let mut count_words = 0_u32; - let size_words = size_bytes / wgt::IMMEDIATES_ALIGNMENT; + let size_words = size_bytes / wgt::IMMEDIATE_DATA_ALIGNMENT; while count_words < size_words { - let count_bytes = count_words * wgt::IMMEDIATES_ALIGNMENT; + let count_bytes = count_words * wgt::IMMEDIATE_DATA_ALIGNMENT; let size_to_write_words = (size_words - count_words).min(IMMEDIATES_CLEAR_ARRAY.len() as u32); diff --git a/wgpu-core/src/command/pass.rs b/wgpu-core/src/command/pass.rs index 324d811fd3c..0ded4bf1ef3 100644 --- a/wgpu-core/src/command/pass.rs +++ b/wgpu-core/src/command/pass.rs @@ -216,22 +216,17 @@ where f(); - let non_overlapping = - super::bind::compute_nonoverlapping_ranges(&pipeline_layout.immediates_ranges); - - // Clear immediate data ranges - for range in non_overlapping { - let offset = range.range.start; - let size_bytes = range.range.end - offset; - super::immediates_clear(offset, size_bytes, |clear_offset, clear_data| unsafe { + super::immediates_clear( + 0, + pipeline_layout.immediate_size, + |clear_offset, clear_data| unsafe { state.base.raw_encoder.set_immediates( pipeline_layout.raw(), - range.stages, clear_offset, clear_data, ); - }); - } + }, + ); } Ok(()) } @@ -239,7 +234,6 @@ where pub(crate) fn set_immediates( state: &mut PassState, immediates_data: &[u32], - stages: wgt::ShaderStages, offset: u32, size_bytes: u32, values_offset: Option, @@ -253,7 +247,7 @@ where let values_offset = values_offset.ok_or(InvalidValuesOffset)?; let end_offset_bytes = offset + size_bytes; - let values_end_offset = (values_offset + size_bytes / wgt::IMMEDIATES_ALIGNMENT) as usize; + let values_end_offset = (values_offset + size_bytes / wgt::IMMEDIATE_DATA_ALIGNMENT) as usize; let data_slice = &immediates_data[(values_offset as usize)..values_end_offset]; let pipeline_layout = state @@ -262,7 +256,7 @@ where .as_ref() .ok_or(MissingPipeline)?; - pipeline_layout.validate_immediates_ranges(stages, offset, end_offset_bytes)?; + pipeline_layout.validate_immediates_ranges(offset, end_offset_bytes)?; f(data_slice); @@ -270,7 +264,7 @@ where state .base .raw_encoder - .set_immediates(pipeline_layout.raw(), stages, offset, data_slice) + .set_immediates(pipeline_layout.raw(), offset, data_slice) } Ok(()) } diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index ae2ffffb875..b1dc0aaae83 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -6,8 +6,8 @@ use arrayvec::ArrayVec; use thiserror::Error; use wgt::{ error::{ErrorType, WebGpuError}, - BufferAddress, BufferSize, BufferUsages, Color, DynamicOffset, IndexFormat, ShaderStages, - TextureSelector, TextureUsages, TextureViewDimension, VertexStepMode, + BufferAddress, BufferSize, BufferUsages, Color, DynamicOffset, IndexFormat, TextureSelector, + TextureUsages, TextureViewDimension, VertexStepMode, }; use crate::command::{ @@ -2021,7 +2021,6 @@ pub(super) fn encode_render_pass( set_viewport(&mut state, rect, depth_min, depth_max).map_pass_err(scope)?; } ArcRenderCommand::SetImmediate { - stages, offset, size_bytes, values_offset, @@ -2030,7 +2029,6 @@ pub(super) fn encode_render_pass( pass::set_immediates::( &mut state.pass, &base.immediates_data, - stages, offset, size_bytes, values_offset, @@ -3336,21 +3334,20 @@ impl Global { pub fn render_pass_set_immediates( &self, pass: &mut RenderPass, - stages: ShaderStages, offset: u32, data: &[u8], ) -> Result<(), PassStateError> { let scope = PassErrorScope::SetImmediate; let base = pass_base!(pass, scope); - if offset & (wgt::IMMEDIATES_ALIGNMENT - 1) != 0 { + if offset & (wgt::IMMEDIATE_DATA_ALIGNMENT - 1) != 0 { pass_try!( base, scope, Err(RenderPassErrorInner::ImmediateOffsetAlignment) ); } - if data.len() as u32 & (wgt::IMMEDIATES_ALIGNMENT - 1) != 0 { + if data.len() as u32 & (wgt::IMMEDIATE_DATA_ALIGNMENT - 1) != 0 { pass_try!( base, scope, @@ -3368,12 +3365,11 @@ impl Global { ); base.immediates_data.extend( - data.chunks_exact(wgt::IMMEDIATES_ALIGNMENT as usize) + data.chunks_exact(wgt::IMMEDIATE_DATA_ALIGNMENT as usize) .map(|arr| u32::from_ne_bytes([arr[0], arr[1], arr[2], arr[3]])), ); base.commands.push(ArcRenderCommand::SetImmediate { - stages, offset, size_bytes: data.len() as u32, values_offset: Some(value_offset), diff --git a/wgpu-core/src/command/render_command.rs b/wgpu-core/src/command/render_command.rs index 7b8af66844d..aa0068cd573 100644 --- a/wgpu-core/src/command/render_command.rs +++ b/wgpu-core/src/command/render_command.rs @@ -46,9 +46,6 @@ pub enum RenderCommand { /// See [`wgpu::RenderPass::set_immediates`] for a detailed explanation /// of the restrictions these commands must satisfy. SetImmediate { - /// Which stages we are setting immediate data values for. - stages: wgt::ShaderStages, - /// The byte offset within the immediate data storage to write to. This /// must be a multiple of four. offset: u32, diff --git a/wgpu-core/src/device/global.rs b/wgpu-core/src/device/global.rs index 4588e84abda..977f175b4ec 100644 --- a/wgpu-core/src/device/global.rs +++ b/wgpu-core/src/device/global.rs @@ -739,7 +739,7 @@ impl Global { let desc = binding_model::ResolvedPipelineLayoutDescriptor { label: desc.label.clone(), bind_group_layouts: Cow::Owned(bind_group_layouts), - immediates_ranges: desc.immediates_ranges.clone(), + immediate_size: desc.immediate_size, }; let layout = match device.create_pipeline_layout(&desc) { diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 176995a3a06..30d9a7e82d1 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -3570,42 +3570,19 @@ impl Device { }); } - if !desc.immediates_ranges.is_empty() { + if desc.immediate_size != 0 { self.require_features(wgt::Features::IMMEDIATES)?; } - - let mut used_stages = wgt::ShaderStages::empty(); - for (index, pc) in desc.immediates_ranges.iter().enumerate() { - if pc.stages.intersects(used_stages) { - return Err(Error::MoreThanOneImmediateRangePerStage { - index, - provided: pc.stages, - intersected: pc.stages & used_stages, - }); - } - used_stages |= pc.stages; - - let device_max_pc_size = self.limits.max_immediate_size; - if device_max_pc_size < pc.range.end { - return Err(Error::ImmediateRangeTooLarge { - index, - range: pc.range.clone(), - max: device_max_pc_size, - }); - } - - if pc.range.start % wgt::IMMEDIATES_ALIGNMENT != 0 { - return Err(Error::MisalignedImmediateRange { - index, - bound: pc.range.start, - }); - } - if pc.range.end % wgt::IMMEDIATES_ALIGNMENT != 0 { - return Err(Error::MisalignedImmediateRange { - index, - bound: pc.range.end, - }); - } + if self.limits.max_immediate_size < desc.immediate_size { + return Err(Error::ImmediateRangeTooLarge { + size: desc.immediate_size, + max: self.limits.max_immediate_size, + }); + } + if desc.immediate_size % wgt::IMMEDIATE_DATA_ALIGNMENT != 0 { + return Err(Error::MisalignedImmediateSize { + size: desc.immediate_size, + }); } let mut count_validator = binding_model::BindingTypeMaxCountValidator::default(); @@ -3643,7 +3620,7 @@ impl Device { | hal::PipelineLayoutFlags::NUM_WORK_GROUPS | additional_flags, bind_group_layouts: &raw_bind_group_layouts, - immediates_ranges: desc.immediates_ranges.as_ref(), + immediate_size: desc.immediate_size, }; let raw = unsafe { self.raw().create_pipeline_layout(&hal_desc) } @@ -3656,7 +3633,7 @@ impl Device { device: self.clone(), label: desc.label.to_string(), bind_group_layouts, - immediates_ranges: desc.immediates_ranges.iter().cloned().collect(), + immediate_size: desc.immediate_size, }; let layout = Arc::new(layout); @@ -3703,7 +3680,7 @@ impl Device { let layout_desc = binding_model::ResolvedPipelineLayoutDescriptor { label: None, bind_group_layouts: Cow::Owned(bind_group_layouts), - immediates_ranges: Cow::Borrowed(&[]), //TODO? + immediate_size: 0, //TODO? }; let layout = self.create_pipeline_layout(&layout_desc)?; diff --git a/wgpu-core/src/device/trace/record.rs b/wgpu-core/src/device/trace/record.rs index 2a6b3c25bed..89639c9afa1 100644 --- a/wgpu-core/src/device/trace/record.rs +++ b/wgpu-core/src/device/trace/record.rs @@ -469,12 +469,10 @@ impl IntoTrace for ArcRenderCommand { }, C::SetScissor(rect) => C::SetScissor(rect), C::SetImmediate { - stages, offset, size_bytes, values_offset, } => C::SetImmediate { - stages, offset, size_bytes, values_offset, @@ -578,7 +576,7 @@ impl<'a> IntoTrace for crate::binding_model::ResolvedPipelineLayoutDescriptor<'a .iter() .map(|bgl| bgl.to_trace()) .collect(), - immediates_ranges: self.immediates_ranges.clone(), + immediate_size: self.immediate_size, } } } diff --git a/wgpu-core/src/indirect_validation/dispatch.rs b/wgpu-core/src/indirect_validation/dispatch.rs index 42cdfd89394..52046511a41 100644 --- a/wgpu-core/src/indirect_validation/dispatch.rs +++ b/wgpu-core/src/indirect_validation/dispatch.rs @@ -177,10 +177,7 @@ impl Dispatch { dst_bind_group_layout.as_ref(), src_bind_group_layout.as_ref(), ], - immediates_ranges: &[wgt::ImmediateRange { - stages: wgt::ShaderStages::COMPUTE, - range: 0..4, - }], + immediate_size: 4, }; let pipeline_layout = unsafe { device diff --git a/wgpu-core/src/indirect_validation/draw.rs b/wgpu-core/src/indirect_validation/draw.rs index 1d28da4692c..50343a2d83d 100644 --- a/wgpu-core/src/indirect_validation/draw.rs +++ b/wgpu-core/src/indirect_validation/draw.rs @@ -81,10 +81,7 @@ impl Draw { src_bind_group_layout.as_ref(), dst_bind_group_layout.as_ref(), ], - immediates_ranges: &[wgt::ImmediateRange { - stages: wgt::ShaderStages::COMPUTE, - range: 0..8, - }], + immediate_size: 8, }; let pipeline_layout = unsafe { device @@ -365,12 +362,7 @@ impl Draw { (batch.metadata_buffer_offset / size_of::() as u64) as u32; let metadata_count = batch.entries.len() as u32; unsafe { - encoder.set_immediates( - pipeline_layout, - wgt::ShaderStages::COMPUTE, - 0, - &[metadata_start, metadata_count], - ); + encoder.set_immediates(pipeline_layout, 0, &[metadata_start, metadata_count]); } let metadata_bind_group = diff --git a/wgpu-core/src/timestamp_normalization/mod.rs b/wgpu-core/src/timestamp_normalization/mod.rs index a3afe9becd3..3cb5cd7e696 100644 --- a/wgpu-core/src/timestamp_normalization/mod.rs +++ b/wgpu-core/src/timestamp_normalization/mod.rs @@ -32,7 +32,6 @@ use core::num::NonZeroU64; use alloc::{boxed::Box, string::String, string::ToString, sync::Arc}; use hashbrown::HashMap; -use wgt::ImmediateRange; use crate::{ device::{Device, DeviceError}, @@ -191,10 +190,7 @@ impl TimestampNormalizer { .create_pipeline_layout(&hal::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[temporary_bind_group_layout.as_ref()], - immediates_ranges: &[ImmediateRange { - stages: wgt::ShaderStages::COMPUTE, - range: 0..8, - }], + immediate_size: 8, flags: hal::PipelineLayoutFlags::empty(), }) .map_err(|e| { @@ -345,7 +341,6 @@ impl TimestampNormalizer { encoder.set_bind_group(&*state.pipeline_layout, 0, Some(bind_group), &[]); encoder.set_immediates( &*state.pipeline_layout, - wgt::ShaderStages::COMPUTE, 0, &[buffer_offset_timestamps, total_timestamps], ); diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index ea43a059b59..20544860766 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -242,7 +242,7 @@ impl Example { label: None, flags: hal::PipelineLayoutFlags::empty(), bind_group_layouts: &[&global_group_layout, &local_group_layout], - immediates_ranges: &[], + immediate_size: 0, }; let pipeline_layout = unsafe { device diff --git a/wgpu-hal/examples/ray-traced-triangle/main.rs b/wgpu-hal/examples/ray-traced-triangle/main.rs index 01aaf57117e..f3d7f61754f 100644 --- a/wgpu-hal/examples/ray-traced-triangle/main.rs +++ b/wgpu-hal/examples/ray-traced-triangle/main.rs @@ -387,7 +387,7 @@ impl Example { label: None, flags: hal::PipelineLayoutFlags::empty(), bind_group_layouts: &[&bgl], - immediates_ranges: &[], + immediate_size: 0, }; let pipeline_layout = unsafe { device diff --git a/wgpu-hal/src/dx12/command.rs b/wgpu-hal/src/dx12/command.rs index 7a738931bbe..62d2e05d74a 100644 --- a/wgpu-hal/src/dx12/command.rs +++ b/wgpu-hal/src/dx12/command.rs @@ -1195,7 +1195,6 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn set_immediates( &mut self, layout: &super::PipelineLayout, - _stages: wgt::ShaderStages, offset_bytes: u32, data: &[u32], ) { diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 204d27e7c40..32145493e00 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -911,17 +911,9 @@ impl crate::Device for super::Device { let mut immediates_target = None; let mut root_constant_info = None; - let mut pc_start = u32::MAX; - let mut pc_end = u32::MIN; - - for pc in desc.immediates_ranges.iter() { - pc_start = pc_start.min(pc.range.start); - pc_end = pc_end.max(pc.range.end); - } - - if pc_start != u32::MAX && pc_end != u32::MIN { + if desc.immediate_size != 0 { let parameter_index = parameters.len(); - let size = (pc_end - pc_start) / 4; + let size = desc.immediate_size / 4; parameters.push(Direct3D12::D3D12_ROOT_PARAMETER { ParameterType: Direct3D12::D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS, Anonymous: Direct3D12::D3D12_ROOT_PARAMETER_0 { @@ -937,7 +929,7 @@ impl crate::Device for super::Device { bind_cbv.register += 1; root_constant_info = Some(super::RootConstantInfo { root_index: parameter_index as u32, - range: (pc_start / 4)..(pc_end / 4), + range: 0..size, }); immediates_target = Some(binding); diff --git a/wgpu-hal/src/dynamic/command.rs b/wgpu-hal/src/dynamic/command.rs index 160c4b25640..d3f812263d0 100644 --- a/wgpu-hal/src/dynamic/command.rs +++ b/wgpu-hal/src/dynamic/command.rs @@ -69,7 +69,6 @@ pub trait DynCommandEncoder: DynResource + core::fmt::Debug { unsafe fn set_immediates( &mut self, layout: &dyn DynPipelineLayout, - stages: wgt::ShaderStages, offset_bytes: u32, data: &[u32], ); @@ -332,12 +331,11 @@ impl DynCommandEncoder for C { unsafe fn set_immediates( &mut self, layout: &dyn DynPipelineLayout, - stages: wgt::ShaderStages, offset_bytes: u32, data: &[u32], ) { let layout = layout.expect_downcast_ref(); - unsafe { C::set_immediates(self, layout, stages, offset_bytes, data) }; + unsafe { C::set_immediates(self, layout, offset_bytes, data) }; } unsafe fn insert_debug_marker(&mut self, label: &str) { diff --git a/wgpu-hal/src/dynamic/device.rs b/wgpu-hal/src/dynamic/device.rs index b0088b6d7ba..9d3de023249 100644 --- a/wgpu-hal/src/dynamic/device.rs +++ b/wgpu-hal/src/dynamic/device.rs @@ -295,7 +295,7 @@ impl DynDevice for D { let desc = PipelineLayoutDescriptor { label: desc.label, bind_group_layouts: &bind_group_layouts, - immediates_ranges: desc.immediates_ranges, + immediate_size: desc.immediate_size, flags: desc.flags, }; diff --git a/wgpu-hal/src/gles/command.rs b/wgpu-hal/src/gles/command.rs index ff77a626efa..41cf14b85ea 100644 --- a/wgpu-hal/src/gles/command.rs +++ b/wgpu-hal/src/gles/command.rs @@ -34,7 +34,7 @@ pub(super) struct State { active_first_instance: u32, first_instance_location: Option, immediates_descs: ArrayVec, - // The current state of the immediate data data block. + // The current state of the immediate data block. current_immediates_data: [u32; super::MAX_IMMEDIATES], end_of_pass_timestamp: Option, clip_distance_count: u32, @@ -792,7 +792,6 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn set_immediates( &mut self, _layout: &super::PipelineLayout, - _stages: wgt::ShaderStages, offset_bytes: u32, data: &[u32], ) { diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index a4bf4169d17..dfd528f9e20 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -1467,7 +1467,7 @@ pub trait CommandEncoder: WasmNotSendSync + fmt::Debug { dynamic_offsets: &[wgt::DynamicOffset], ); - /// Sets a range in immediate data data. + /// Sets a range in immediate data. /// /// IMPORTANT: while the data is passed as words, the offset is in bytes! /// @@ -1478,7 +1478,6 @@ pub trait CommandEncoder: WasmNotSendSync + fmt::Debug { unsafe fn set_immediates( &mut self, layout: &::PipelineLayout, - stages: wgt::ShaderStages, offset_bytes: u32, data: &[u32], ); @@ -2084,7 +2083,7 @@ pub struct PipelineLayoutDescriptor<'a, B: DynBindGroupLayout + ?Sized> { pub label: Label<'a>, pub flags: PipelineLayoutFlags, pub bind_group_layouts: &'a [&'a B], - pub immediates_ranges: &'a [wgt::ImmediateRange], + pub immediate_size: u32, } /// A region of a buffer made visible to shaders via a [`BindGroup`]. diff --git a/wgpu-hal/src/metal/command.rs b/wgpu-hal/src/metal/command.rs index 9826ee4d306..276ac72c356 100644 --- a/wgpu-hal/src/metal/command.rs +++ b/wgpu-hal/src/metal/command.rs @@ -956,7 +956,6 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn set_immediates( &mut self, layout: &super::PipelineLayout, - stages: wgt::ShaderStages, offset_bytes: u32, data: &[u32], ) { @@ -969,40 +968,46 @@ impl crate::CommandEncoder for super::CommandEncoder { let offset_words = offset_bytes as usize / WORD_SIZE; state_pc[offset_words..offset_words + data.len()].copy_from_slice(data); - if stages.contains(wgt::ShaderStages::COMPUTE) { - self.state.compute.as_ref().unwrap().set_bytes( + if let Some(ref compute) = self.state.compute { + compute.set_bytes( layout.immediates_infos.cs.unwrap().buffer_index as _, (layout.total_immediates as usize * WORD_SIZE) as _, state_pc.as_ptr().cast(), ) } - if stages.contains(wgt::ShaderStages::VERTEX) { - self.state.render.as_ref().unwrap().set_vertex_bytes( - layout.immediates_infos.vs.unwrap().buffer_index as _, - (layout.total_immediates as usize * WORD_SIZE) as _, - state_pc.as_ptr().cast(), - ) - } - if stages.contains(wgt::ShaderStages::FRAGMENT) { - self.state.render.as_ref().unwrap().set_fragment_bytes( - layout.immediates_infos.fs.unwrap().buffer_index as _, - (layout.total_immediates as usize * WORD_SIZE) as _, - state_pc.as_ptr().cast(), - ) - } - if stages.contains(wgt::ShaderStages::TASK) { - self.state.render.as_ref().unwrap().set_object_bytes( - layout.immediates_infos.ts.unwrap().buffer_index as _, - (layout.total_immediates as usize * WORD_SIZE) as _, - state_pc.as_ptr().cast(), - ) - } - if stages.contains(wgt::ShaderStages::MESH) { - self.state.render.as_ref().unwrap().set_object_bytes( - layout.immediates_infos.ms.unwrap().buffer_index as _, - (layout.total_immediates as usize * WORD_SIZE) as _, - state_pc.as_ptr().cast(), - ) + if let Some(ref render) = self.state.render { + if let Some(vs) = layout.immediates_infos.vs { + render.set_vertex_bytes( + vs.buffer_index as _, + (layout.total_immediates as usize * WORD_SIZE) as _, + state_pc.as_ptr().cast(), + ) + } + if let Some(fs) = layout.immediates_infos.fs { + render.set_fragment_bytes( + fs.buffer_index as _, + (layout.total_immediates as usize * WORD_SIZE) as _, + state_pc.as_ptr().cast(), + ) + } + if let Some(ts) = layout.immediates_infos.ts { + if self.shared.private_caps.mesh_shaders { + render.set_object_bytes( + ts.buffer_index as _, + (layout.total_immediates as usize * WORD_SIZE) as _, + state_pc.as_ptr().cast(), + ) + } + } + if let Some(ms) = layout.immediates_infos.ms { + if self.shared.private_caps.mesh_shaders { + render.set_object_bytes( + ms.buffer_index as _, + (layout.total_immediates as usize * WORD_SIZE) as _, + state_pc.as_ptr().cast(), + ) + } + } } } diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index 917c8062254..d657db6d747 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -688,30 +688,14 @@ impl crate::Device for super::Device { let mut bind_group_infos = arrayvec::ArrayVec::new(); // First, place the immediates - let mut total_immediates = 0; for info in stage_data.iter_mut() { - for pcr in desc.immediates_ranges { - if pcr.stages.contains(map_naga_stage(info.stage)) { - debug_assert_eq!(pcr.range.end % 4, 0); - info.pc_limit = (pcr.range.end / 4).max(info.pc_limit); - } - } - - // round up the limits alignment to 4, so that it matches MTL compiler logic - const LIMIT_MASK: u32 = 3; - //TODO: figure out what and how exactly does the alignment. Clearly, it's not - // straightforward, given that value of 2 stays non-aligned. - if info.pc_limit > LIMIT_MASK { - info.pc_limit = (info.pc_limit + LIMIT_MASK) & !LIMIT_MASK; - } + info.pc_limit = desc.immediate_size; // handle the immediate data buffer assignment and shader overrides if info.pc_limit != 0 { info.pc_buffer = Some(info.counters.buffers); info.counters.buffers += 1; } - - total_immediates = total_immediates.max(info.pc_limit); } // Second, place the described resources @@ -845,7 +829,7 @@ impl crate::Device for super::Device { bind_group_infos, immediates_infos, total_counters, - total_immediates, + total_immediates: desc.immediate_size, per_stage_map, }) } diff --git a/wgpu-hal/src/noop/command.rs b/wgpu-hal/src/noop/command.rs index 5269ab3e51f..52f359f673d 100644 --- a/wgpu-hal/src/noop/command.rs +++ b/wgpu-hal/src/noop/command.rs @@ -162,14 +162,7 @@ impl crate::CommandEncoder for CommandBuffer { dynamic_offsets: &[wgt::DynamicOffset], ) { } - unsafe fn set_immediates( - &mut self, - layout: &Resource, - stages: wgt::ShaderStages, - offset_bytes: u32, - data: &[u32], - ) { - } + unsafe fn set_immediates(&mut self, layout: &Resource, offset_bytes: u32, data: &[u32]) {} unsafe fn insert_debug_marker(&mut self, label: &str) {} unsafe fn begin_debug_marker(&mut self, group_label: &str) {} diff --git a/wgpu-hal/src/vulkan/command.rs b/wgpu-hal/src/vulkan/command.rs index 26258b0a7f3..bc2e5c7a846 100644 --- a/wgpu-hal/src/vulkan/command.rs +++ b/wgpu-hal/src/vulkan/command.rs @@ -943,7 +943,6 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn set_immediates( &mut self, layout: &super::PipelineLayout, - stages: wgt::ShaderStages, offset_bytes: u32, data: &[u32], ) { @@ -951,7 +950,7 @@ impl crate::CommandEncoder for super::CommandEncoder { self.device.raw.cmd_push_constants( self.active, layout.raw, - conv::map_shader_stage(stages), + vk::ShaderStageFlags::ALL, offset_bytes, bytemuck::cast_slice(data), ) diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 606db48475c..dee39340a74 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -1404,20 +1404,20 @@ impl crate::Device for super::Device { .iter() .map(|bgl| bgl.raw) .collect::>(); - let vk_immediates_ranges = desc - .immediates_ranges - .iter() - .map(|pcr| vk::PushConstantRange { - stage_flags: conv::map_shader_stage(pcr.stages), - offset: pcr.range.start, - size: pcr.range.end - pcr.range.start, + let vk_immediates_ranges: Option = if desc.immediate_size != 0 { + Some(vk::PushConstantRange { + stage_flags: vk::ShaderStageFlags::ALL, + offset: 0, + size: desc.immediate_size, }) - .collect::>(); + } else { + None + }; let vk_info = vk::PipelineLayoutCreateInfo::default() .flags(vk::PipelineLayoutCreateFlags::empty()) .set_layouts(&vk_set_layouts) - .push_constant_ranges(&vk_immediates_ranges); + .push_constant_ranges(vk_immediates_ranges.as_slice()); let raw = { profiling::scope!("vkCreatePipelineLayout"); diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 980013ff1b9..b1c0fe0a096 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -19,7 +19,7 @@ extern crate std; extern crate alloc; -use core::{fmt, hash::Hash, ops::Range, time::Duration}; +use core::{fmt, hash::Hash, time::Duration}; #[cfg(any(feature = "serde", test))] use serde::{Deserialize, Serialize}; @@ -197,7 +197,7 @@ pub const VERTEX_STRIDE_ALIGNMENT: BufferAddress = 4; /// Ranges of [writes to immediate data] must be at least this aligned. /// #[doc = link_to_wgpu_docs!(["writes to immediate data"]: "struct.RenderPass.html#method.set_immediates")] -pub const IMMEDIATES_ALIGNMENT: u32 = 4; +pub const IMMEDIATE_DATA_ALIGNMENT: u32 = 4; /// Maximum queries in a [`QuerySetDescriptor`]. pub const QUERY_SET_MAX_QUERIES: u32 = 4096; @@ -430,18 +430,6 @@ impl Color { }; } -/// A range of immediate data memory to pass to a shader stage. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct ImmediateRange { - /// Stage immediate data range is visible from. Each stage can only be served by at most one range. - /// One range can serve multiple stages however. - pub stages: ShaderStages, - /// Range in immediate data memory to use for the stage. Must be less than [`Limits::max_immediate_size`]. - /// Start and end must be aligned to the 4s. - pub range: Range, -} - /// Describes a [`CommandBuffer`](../wgpu/struct.CommandBuffer.html). /// /// Corresponds to [WebGPU `GPUCommandBufferDescriptor`]( diff --git a/wgpu/src/api/compute_pass.rs b/wgpu/src/api/compute_pass.rs index c89c1a222e6..0d1dcf58517 100644 --- a/wgpu/src/api/compute_pass.rs +++ b/wgpu/src/api/compute_pass.rs @@ -113,11 +113,11 @@ impl ComputePass<'_> { /// [`Features::IMMEDIATES`] must be enabled on the device in order to call these functions. impl ComputePass<'_> { - /// Set immediate data data for subsequent dispatch calls. + /// Set immediate data for subsequent dispatch calls. /// /// Write the bytes in `data` at offset `offset` within immediate data /// storage. Both `offset` and the length of `data` must be - /// multiples of [`IMMEDIATES_ALIGNMENT`], which is always 4. + /// multiples of [`crate::IMMEDIATE_DATA_ALIGNMENT`], which is always 4. /// /// For example, if `offset` is `4` and `data` is eight bytes long, this /// call will write `data` to bytes `4..12` of immediate data storage. diff --git a/wgpu/src/api/pipeline_layout.rs b/wgpu/src/api/pipeline_layout.rs index e4e0110c87d..fc7948df676 100644 --- a/wgpu/src/api/pipeline_layout.rs +++ b/wgpu/src/api/pipeline_layout.rs @@ -36,12 +36,12 @@ pub struct PipelineLayoutDescriptor<'a> { /// Bind groups that this pipeline uses. The first entry will provide all the bindings for /// "set = 0", second entry will provide all the bindings for "set = 1" etc. pub bind_group_layouts: &'a [&'a BindGroupLayout], - /// Set of immediate data ranges this pipeline uses. Each shader stage that uses immediates - /// must define the range in immediate data memory that corresponds to its single `var` - /// buffer. + /// The number of bytes of immediate data that are allocated for use + /// in the shader. The `var`s in the shader attached to + /// this pipeline must be equal or smaller than this size. /// - /// If this array is non-empty, the [`Features::IMMEDIATES`] must be enabled. - pub immediates_ranges: &'a [ImmediateRange], + /// If this value is non-zero, [`Features::IMMEDIATES`] must be enabled. + pub immediate_size: u32, } #[cfg(send_sync)] static_assertions::assert_impl_all!(PipelineLayoutDescriptor<'_>: Send, Sync); diff --git a/wgpu/src/api/render_bundle_encoder.rs b/wgpu/src/api/render_bundle_encoder.rs index aebae7b040b..cea7aa330c5 100644 --- a/wgpu/src/api/render_bundle_encoder.rs +++ b/wgpu/src/api/render_bundle_encoder.rs @@ -198,35 +198,15 @@ impl<'a> RenderBundleEncoder<'a> { /// [`Features::IMMEDIATES`] must be enabled on the device in order to call these functions. impl RenderBundleEncoder<'_> { - /// Set immediate data data. + /// Set immediate data for subsequent draw calls within the render bundle. /// - /// Offset is measured in bytes, but must be a multiple of [`IMMEDIATES_ALIGNMENT`]. + /// Write the bytes in `data` at offset `offset` within immediate data + /// storage. Both `offset` and the length of `data` must be + /// multiples of [`crate::IMMEDIATE_DATA_ALIGNMENT`], which is always 4. /// - /// Data size must be a multiple of 4 and must have an alignment of 4. - /// For example, with an offset of 4 and an array of `[u8; 8]`, that will write to the range - /// of 4..12. - /// - /// For each byte in the range of immediate data data written, the union of the stages of all immediate data - /// ranges that covers that byte must be exactly `stages`. There's no good way of explaining this simply, - /// so here are some examples: - /// - /// ```text - /// For the given ranges: - /// - 0..4 Vertex - /// - 4..8 Fragment - /// ``` - /// - /// You would need to upload this in two set_immediates calls. First for the `Vertex` range, second for the `Fragment` range. - /// - /// ```text - /// For the given ranges: - /// - 0..8 Vertex - /// - 4..12 Fragment - /// ``` - /// - /// You would need to upload this in three set_immediates calls. First for the `Vertex` only range 0..4, second - /// for the `Vertex | Fragment` range 4..8, third for the `Fragment` range 8..12. - pub fn set_immediates(&mut self, stages: ShaderStages, offset: u32, data: &[u8]) { - self.inner.set_immediates(stages, offset, data); + /// For example, if `offset` is `4` and `data` is eight bytes long, this + /// call will write `data` to bytes `4..12` of immediate data storage. + pub fn set_immediates(&mut self, offset: u32, data: &[u8]) { + self.inner.set_immediates(offset, data); } } diff --git a/wgpu/src/api/render_pass.rs b/wgpu/src/api/render_pass.rs index 2fdc85cd3f2..63416802186 100644 --- a/wgpu/src/api/render_pass.rs +++ b/wgpu/src/api/render_pass.rs @@ -507,48 +507,16 @@ impl RenderPass<'_> { /// [`Features::IMMEDIATES`] must be enabled on the device in order to call these functions. impl RenderPass<'_> { - /// Set immediate data data for subsequent draw calls. + /// Set immediate data for subsequent draw calls. /// /// Write the bytes in `data` at offset `offset` within immediate data - /// storage, all of which are accessible by all the pipeline stages in - /// `stages`, and no others. Both `offset` and the length of `data` must be - /// multiples of [`IMMEDIATES_ALIGNMENT`], which is always 4. + /// storage. Both `offset` and the length of `data` must be + /// multiples of [`crate::IMMEDIATE_DATA_ALIGNMENT`], which is always 4. /// /// For example, if `offset` is `4` and `data` is eight bytes long, this /// call will write `data` to bytes `4..12` of immediate data storage. - /// - /// # Stage matching - /// - /// Every byte in the affected range of immediate data storage must be - /// accessible to exactly the same set of pipeline stages, which must match - /// `stages`. If there are two bytes of storage that are accessible by - /// different sets of pipeline stages - say, one is accessible by fragment - /// shaders, and the other is accessible by both fragment shaders and vertex - /// shaders - then no single `set_immediates` call may affect both of - /// them; to write both, you must make multiple calls, each with the - /// appropriate `stages` value. - /// - /// Which pipeline stages may access a given byte is determined by the - /// pipeline's [`Immediate`] global variable and (if it is a struct) its - /// members' offsets. - /// - /// For example, suppose you have twelve bytes of immediate data storage, - /// where bytes `0..8` are accessed by the vertex shader, and bytes `4..12` - /// are accessed by the fragment shader. This means there are three byte - /// ranges each accessed by a different set of stages: - /// - /// - Bytes `0..4` are accessed only by the fragment shader. - /// - /// - Bytes `4..8` are accessed by both the fragment shader and the vertex shader. - /// - /// - Bytes `8..12` are accessed only by the vertex shader. - /// - /// To write all twelve bytes requires three `set_immediates` calls, one - /// for each range, each passing the matching `stages` mask. - /// - /// [`Immediate`]: https://docs.rs/naga/latest/naga/enum.StorageClass.html#variant.Immediate - pub fn set_immediates(&mut self, stages: ShaderStages, offset: u32, data: &[u8]) { - self.inner.set_immediates(stages, offset, data); + pub fn set_immediates(&mut self, offset: u32, data: &[u8]) { + self.inner.set_immediates(offset, data); } } diff --git a/wgpu/src/backend/webgpu.rs b/wgpu/src/backend/webgpu.rs index 208484b8c3e..dd44120c1bd 100644 --- a/wgpu/src/backend/webgpu.rs +++ b/wgpu/src/backend/webgpu.rs @@ -3474,8 +3474,8 @@ impl dispatch::RenderPassInterface for WebRenderPassEncoder { } } - fn set_immediates(&mut self, _stages: crate::ShaderStages, _offset: u32, _data: &[u8]) { - panic!("IMMEDIATES feature must be enabled to call multi_draw_indexed_indirect") + fn set_immediates(&mut self, _offset: u32, _data: &[u8]) { + panic!("IMMEDIATES feature must be enabled to call set_immediates") } fn set_blend_constant(&mut self, color: crate::Color) { @@ -3780,8 +3780,8 @@ impl dispatch::RenderBundleEncoderInterface for WebRenderBundleEncoder { } } - fn set_immediates(&mut self, _stages: crate::ShaderStages, _offset: u32, _data: &[u8]) { - panic!("IMMEDIATES feature must be enabled to call multi_draw_indexed_indirect") + fn set_immediates(&mut self, _offset: u32, _data: &[u8]) { + panic!("IMMEDIATES feature must be enabled to call set_immediates") } fn draw(&mut self, vertices: Range, instances: Range) { diff --git a/wgpu/src/backend/wgpu_core.rs b/wgpu/src/backend/wgpu_core.rs index e85d4b747b8..00a3a5e8933 100644 --- a/wgpu/src/backend/wgpu_core.rs +++ b/wgpu/src/backend/wgpu_core.rs @@ -1286,7 +1286,7 @@ impl dispatch::DeviceInterface for CoreDevice { let descriptor = wgc::binding_model::PipelineLayoutDescriptor { label: desc.label.map(Borrowed), bind_group_layouts: Borrowed(&temp_layouts), - immediates_ranges: Borrowed(desc.immediates_ranges), + immediate_size: desc.immediate_size, }; let (id, error) = self @@ -3185,11 +3185,11 @@ impl dispatch::RenderPassInterface for CoreRenderPass { } } - fn set_immediates(&mut self, stages: crate::ShaderStages, offset: u32, data: &[u8]) { - if let Err(cause) = - self.context - .0 - .render_pass_set_immediates(&mut self.pass, stages, offset, data) + fn set_immediates(&mut self, offset: u32, data: &[u8]) { + if let Err(cause) = self + .context + .0 + .render_pass_set_immediates(&mut self.pass, offset, data) { self.context.handle_error( &self.error_sink, @@ -3761,11 +3761,10 @@ impl dispatch::RenderBundleEncoderInterface for CoreRenderBundleEncoder { wgpu_render_bundle_set_vertex_buffer(&mut self.encoder, slot, buffer.id, offset, size) } - fn set_immediates(&mut self, stages: crate::ShaderStages, offset: u32, data: &[u8]) { + fn set_immediates(&mut self, offset: u32, data: &[u8]) { unsafe { wgpu_render_bundle_set_immediates( &mut self.encoder, - stages, offset, data.len().try_into().unwrap(), data.as_ptr(), diff --git a/wgpu/src/dispatch.rs b/wgpu/src/dispatch.rs index b4d0a599310..233dc20759d 100644 --- a/wgpu/src/dispatch.rs +++ b/wgpu/src/dispatch.rs @@ -417,7 +417,7 @@ pub trait RenderPassInterface: CommonTraits { offset: crate::BufferAddress, size: Option, ); - fn set_immediates(&mut self, stages: crate::ShaderStages, offset: u32, data: &[u8]); + fn set_immediates(&mut self, offset: u32, data: &[u8]); fn set_blend_constant(&mut self, color: crate::Color); fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32); fn set_viewport( @@ -530,7 +530,7 @@ pub trait RenderBundleEncoderInterface: CommonTraits { offset: crate::BufferAddress, size: Option, ); - fn set_immediates(&mut self, stages: crate::ShaderStages, offset: u32, data: &[u8]); + fn set_immediates(&mut self, offset: u32, data: &[u8]); fn draw(&mut self, vertices: Range, instances: Range); fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range); diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 3dfe6ad1b28..4403222e93b 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -138,8 +138,8 @@ pub use wgt::{ Dx12SwapchainKind, Dx12UseFrameLatencyWaitableObject, DxcShaderModel, DynamicOffset, ExperimentalFeatures, Extent3d, ExternalTextureFormat, ExternalTextureTransferFunction, Face, Features, FeaturesWGPU, FeaturesWebGPU, FilterMode, FrontFace, GlBackendOptions, - GlFenceBehavior, Gles3MinorVersion, HalCounters, ImageSubresourceRange, ImmediateRange, - IndexFormat, InstanceDescriptor, InstanceFlags, InternalCounters, Limits, LoadOpDontCare, + GlFenceBehavior, Gles3MinorVersion, HalCounters, ImageSubresourceRange, IndexFormat, + InstanceDescriptor, InstanceFlags, InternalCounters, Limits, LoadOpDontCare, MemoryBudgetThresholds, MemoryHints, MipmapFilterMode, MultisampleState, NoopBackendOptions, Origin2d, Origin3d, PipelineStatisticsTypes, PollError, PollStatus, PolygonMode, PowerPreference, PredefinedColorSpace, PresentMode, PresentationTimestamp, PrimitiveState, @@ -150,9 +150,9 @@ pub use wgt::{ TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures, TextureSampleType, TextureTransition, TextureUsages, TextureUses, TextureViewDimension, Trace, VertexAttribute, VertexFormat, VertexStepMode, WasmNotSend, WasmNotSendSync, WasmNotSync, COPY_BUFFER_ALIGNMENT, - COPY_BYTES_PER_ROW_ALIGNMENT, IMMEDIATES_ALIGNMENT, MAP_ALIGNMENT, MAXIMUM_SUBGROUP_MAX_SIZE, - MINIMUM_SUBGROUP_MIN_SIZE, QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE, - VERTEX_ALIGNMENT, + COPY_BYTES_PER_ROW_ALIGNMENT, IMMEDIATE_DATA_ALIGNMENT, MAP_ALIGNMENT, + MAXIMUM_SUBGROUP_MAX_SIZE, MINIMUM_SUBGROUP_MIN_SIZE, QUERY_RESOLVE_BUFFER_ALIGNMENT, + QUERY_SET_MAX_QUERIES, QUERY_SIZE, VERTEX_ALIGNMENT, }; #[expect(deprecated)] diff --git a/wgpu/src/util/encoder.rs b/wgpu/src/util/encoder.rs index 489371cf016..64d9b6c3a6e 100644 --- a/wgpu/src/util/encoder.rs +++ b/wgpu/src/util/encoder.rs @@ -73,35 +73,15 @@ pub trait RenderEncoder<'a> { /// [`wgt::Features::IMMEDIATES`] must be enabled on the device in order to call this function. /// - /// Set immediate data data. + /// Set immediate data for subsequent draw calls. /// - /// Offset is measured in bytes, but must be a multiple of [`wgt::IMMEDIATES_ALIGNMENT`]. + /// Write the bytes in `data` at offset `offset` within immediate data + /// storage. Both `offset` and the length of `data` must be + /// multiples of [`crate::IMMEDIATE_DATA_ALIGNMENT`], which is always 4. /// - /// Data size must be a multiple of 4 and must be aligned to the 4s, so we take an array of u32. - /// For example, with an offset of 4 and an array of `[u32; 3]`, that will write to the range - /// of 4..16. - /// - /// For each byte in the range of immediate data data written, the union of the stages of all immediate data - /// ranges that covers that byte must be exactly `stages`. There's no good way of explaining this simply, - /// so here are some examples: - /// - /// ```text - /// For the given ranges: - /// - 0..4 Vertex - /// - 4..8 Fragment - /// ``` - /// - /// You would need to upload this in two `set_immediates` calls. First for the `Vertex` range, second for the `Fragment` range. - /// - /// ```text - /// For the given ranges: - /// - 0..8 Vertex - /// - 4..12 Fragment - /// ``` - /// - /// You would need to upload this in three `set_immediates` calls. First for the `Vertex` only range 0..4, second - /// for the `Vertex | Fragment` range 4..8, third for the `Fragment` range 8..12. - fn set_immediates(&mut self, stages: wgt::ShaderStages, offset: u32, data: &[u8]); + /// For example, if `offset` is `4` and `data` is eight bytes long, this + /// call will write `data` to bytes `4..12` of immediate data storage. + fn set_immediates(&mut self, offset: u32, data: &[u8]); } impl<'a> RenderEncoder<'a> for RenderPass<'a> { @@ -155,8 +135,8 @@ impl<'a> RenderEncoder<'a> for RenderPass<'a> { } #[inline(always)] - fn set_immediates(&mut self, stages: wgt::ShaderStages, offset: u32, data: &[u8]) { - Self::set_immediates(self, stages, offset, data); + fn set_immediates(&mut self, offset: u32, data: &[u8]) { + Self::set_immediates(self, offset, data); } } @@ -211,7 +191,7 @@ impl<'a> RenderEncoder<'a> for RenderBundleEncoder<'a> { } #[inline(always)] - fn set_immediates(&mut self, stages: wgt::ShaderStages, offset: u32, data: &[u8]) { - Self::set_immediates(self, stages, offset, data); + fn set_immediates(&mut self, offset: u32, data: &[u8]) { + Self::set_immediates(self, offset, data); } } diff --git a/wgpu/src/util/texture_blitter.rs b/wgpu/src/util/texture_blitter.rs index 2b7c6bdbb78..c0704fe0af6 100644 --- a/wgpu/src/util/texture_blitter.rs +++ b/wgpu/src/util/texture_blitter.rs @@ -94,7 +94,7 @@ impl<'a> TextureBlitterBuilder<'a> { .create_pipeline_layout(&PipelineLayoutDescriptor { label: Some("wgpu::util::TextureBlitter::pipeline_layout"), bind_group_layouts: &[&bind_group_layout], - immediates_ranges: &[], + immediate_size: 0, }); let shader = self.device.create_shader_module(include_wgsl!("blit.wgsl"));