From 3bda38181293a247c00de60c1ff86b984b559497 Mon Sep 17 00:00:00 2001 From: teoxoy <28601907+teoxoy@users.noreply.github.com> Date: Mon, 13 Nov 2023 17:48:24 +0100 Subject: [PATCH] add pipeline constants plumbing --- deno_webgpu/pipeline.rs | 12 ++++++--- examples/src/boids/mod.rs | 3 +++ examples/src/bunnymark/mod.rs | 2 ++ examples/src/conservative_raster/mod.rs | 8 ++++++ examples/src/cube/mod.rs | 4 +++ examples/src/hello_compute/mod.rs | 1 + examples/src/hello_synchronization/mod.rs | 2 ++ examples/src/hello_triangle/mod.rs | 2 ++ examples/src/hello_workgroups/mod.rs | 1 + examples/src/mipmap/mod.rs | 4 +++ examples/src/msaa_line/mod.rs | 2 ++ examples/src/render_to_texture/mod.rs | 2 ++ examples/src/repeated_compute/mod.rs | 1 + examples/src/shadow/mod.rs | 3 +++ examples/src/skybox/mod.rs | 4 +++ examples/src/srgb_blend/mod.rs | 2 ++ examples/src/stencil_triangles/mod.rs | 4 +++ examples/src/storage_texture/mod.rs | 1 + examples/src/texture_arrays/mod.rs | 2 ++ examples/src/timestamp_queries/mod.rs | 3 +++ examples/src/uniform_values/mod.rs | 2 ++ examples/src/water/mod.rs | 4 +++ naga-cli/src/bin/naga.rs | 3 +++ naga/benches/criterion.rs | 5 +++- naga/src/back/glsl/mod.rs | 4 ++- naga/src/back/hlsl/mod.rs | 8 ++++++ naga/src/back/hlsl/writer.rs | 3 ++- naga/src/back/mod.rs | 9 +++++++ naga/src/back/msl/mod.rs | 4 ++- naga/src/back/spv/mod.rs | 4 ++- naga/tests/in/interface.param.ron | 1 + naga/tests/snapshots.rs | 6 ++++- player/tests/data/bind-group.ron | 1 + .../tests/data/pipeline-statistics-query.ron | 1 + player/tests/data/quad.ron | 2 ++ player/tests/data/zero-init-buffer.ron | 1 + .../tests/data/zero-init-texture-binding.ron | 1 + tests/src/image.rs | 1 + tests/tests/bgra8unorm_storage.rs | 1 + tests/tests/bind_group_layout_dedup.rs | 5 ++++ tests/tests/buffer.rs | 2 ++ tests/tests/device.rs | 4 +++ tests/tests/mem_leaks.rs | 6 +++-- tests/tests/nv12_texture/mod.rs | 2 ++ tests/tests/occlusion_query/mod.rs | 1 + tests/tests/partially_bounded_arrays/mod.rs | 1 + tests/tests/pipeline.rs | 1 + tests/tests/push_constants.rs | 1 + tests/tests/regression/issue_3349.rs | 2 ++ tests/tests/regression/issue_3457.rs | 4 +++ tests/tests/scissor_tests/mod.rs | 6 +++-- tests/tests/shader/mod.rs | 1 + tests/tests/shader/zero_init_workgroup_mem.rs | 2 ++ tests/tests/shader_primitive_index/mod.rs | 8 +++--- tests/tests/shader_view_format/mod.rs | 2 ++ tests/tests/vertex_indices/mod.rs | 7 ++++-- wgpu-core/src/device/resource.rs | 5 +++- wgpu-core/src/pipeline.rs | 8 ++++++ wgpu-hal/examples/halmark/main.rs | 3 +++ wgpu-hal/examples/ray-traced-triangle/main.rs | 1 + wgpu-hal/src/dx12/device.rs | 5 +++- wgpu-hal/src/gles/device.rs | 1 + wgpu-hal/src/lib.rs | 3 +++ wgpu-hal/src/metal/device.rs | 1 + wgpu-hal/src/vulkan/device.rs | 1 + wgpu/src/backend/wgpu_core.rs | 3 +++ wgpu/src/lib.rs | 25 +++++++++++++++++++ 67 files changed, 214 insertions(+), 21 deletions(-) diff --git a/deno_webgpu/pipeline.rs b/deno_webgpu/pipeline.rs index ab7cf42e7..303128760 100644 --- a/deno_webgpu/pipeline.rs +++ b/deno_webgpu/pipeline.rs @@ -8,6 +8,7 @@ use deno_core::ResourceId; use serde::Deserialize; use serde::Serialize; use std::borrow::Cow; +use std::collections::HashMap; use std::rc::Rc; use super::error::WebGpuError; @@ -75,7 +76,7 @@ pub enum GPUPipelineLayoutOrGPUAutoLayoutMode { pub struct GpuProgrammableStage { module: ResourceId, entry_point: Option, - // constants: HashMap + constants: HashMap, } #[op2] @@ -111,7 +112,7 @@ pub fn op_webgpu_create_compute_pipeline( stage: wgpu_core::pipeline::ProgrammableStageDescriptor { module: compute_shader_module_resource.1, entry_point: compute.entry_point.map(Cow::from), - // TODO(lucacasonato): support args.compute.constants + constants: Cow::Owned(compute.constants), }, }; let implicit_pipelines = match layout { @@ -279,6 +280,7 @@ impl<'a> From for wgpu_core::pipeline::VertexBufferLayout struct GpuVertexState { module: ResourceId, entry_point: String, + constants: HashMap, buffers: Vec>, } @@ -306,7 +308,7 @@ struct GpuFragmentState { targets: Vec>, module: u32, entry_point: String, - // TODO(lucacasonato): constants + constants: HashMap, } #[derive(Deserialize)] @@ -356,8 +358,9 @@ pub fn op_webgpu_create_render_pipeline( stage: wgpu_core::pipeline::ProgrammableStageDescriptor { module: fragment_shader_module_resource.1, entry_point: Some(Cow::from(fragment.entry_point)), + constants: Cow::Owned(fragment.constants), }, - targets: Cow::from(fragment.targets), + targets: Cow::Owned(fragment.targets), }) } else { None @@ -378,6 +381,7 @@ pub fn op_webgpu_create_render_pipeline( stage: wgpu_core::pipeline::ProgrammableStageDescriptor { module: vertex_shader_module_resource.1, entry_point: Some(Cow::Owned(args.vertex.entry_point)), + constants: Cow::Owned(args.vertex.constants), }, buffers: Cow::Owned(vertex_buffers), }, diff --git a/examples/src/boids/mod.rs b/examples/src/boids/mod.rs index b60839413..02846beea 100644 --- a/examples/src/boids/mod.rs +++ b/examples/src/boids/mod.rs @@ -132,6 +132,7 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &draw_shader, entry_point: "main_vs", + constants: &Default::default(), buffers: &[ wgpu::VertexBufferLayout { array_stride: 4 * 4, @@ -148,6 +149,7 @@ impl crate::framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &draw_shader, entry_point: "main_fs", + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: wgpu::PrimitiveState::default(), @@ -163,6 +165,7 @@ impl crate::framework::Example for Example { layout: Some(&compute_pipeline_layout), module: &compute_shader, entry_point: "main", + constants: &Default::default(), }); // buffer for the three 2d triangle vertices of each instance diff --git a/examples/src/bunnymark/mod.rs b/examples/src/bunnymark/mod.rs index c29da351e..be0947807 100644 --- a/examples/src/bunnymark/mod.rs +++ b/examples/src/bunnymark/mod.rs @@ -203,11 +203,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(wgpu::ColorTargetState { format: config.view_formats[0], blend: Some(wgpu::BlendState::ALPHA_BLENDING), diff --git a/examples/src/conservative_raster/mod.rs b/examples/src/conservative_raster/mod.rs index ce2054caa..12cdaa399 100644 --- a/examples/src/conservative_raster/mod.rs +++ b/examples/src/conservative_raster/mod.rs @@ -97,11 +97,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader_triangle_and_lines, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &shader_triangle_and_lines, entry_point: "fs_main_red", + constants: &Default::default(), targets: &[Some(RENDER_TARGET_FORMAT.into())], }), primitive: wgpu::PrimitiveState { @@ -120,11 +122,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader_triangle_and_lines, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &shader_triangle_and_lines, entry_point: "fs_main_blue", + constants: &Default::default(), targets: &[Some(RENDER_TARGET_FORMAT.into())], }), primitive: wgpu::PrimitiveState::default(), @@ -144,11 +148,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader_triangle_and_lines, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &shader_triangle_and_lines, entry_point: "fs_main_white", + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: wgpu::PrimitiveState { @@ -205,11 +211,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: wgpu::PrimitiveState::default(), diff --git a/examples/src/cube/mod.rs b/examples/src/cube/mod.rs index d21aafe5d..d87193fcf 100644 --- a/examples/src/cube/mod.rs +++ b/examples/src/cube/mod.rs @@ -244,11 +244,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &vertex_buffers, }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: wgpu::PrimitiveState { @@ -270,11 +272,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &vertex_buffers, }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_wire", + constants: &Default::default(), targets: &[Some(wgpu::ColorTargetState { format: config.view_formats[0], blend: Some(wgpu::BlendState { diff --git a/examples/src/hello_compute/mod.rs b/examples/src/hello_compute/mod.rs index ef452bf02..63169662e 100644 --- a/examples/src/hello_compute/mod.rs +++ b/examples/src/hello_compute/mod.rs @@ -109,6 +109,7 @@ async fn execute_gpu_inner( layout: None, module: &cs_module, entry_point: "main", + constants: &Default::default(), }); // Instantiates the bind group, once again specifying the binding of buffers. diff --git a/examples/src/hello_synchronization/mod.rs b/examples/src/hello_synchronization/mod.rs index c2a6fe8b2..7dc2e6c9c 100644 --- a/examples/src/hello_synchronization/mod.rs +++ b/examples/src/hello_synchronization/mod.rs @@ -103,12 +103,14 @@ async fn execute( layout: Some(&pipeline_layout), module: &shaders_module, entry_point: "patient_main", + constants: &Default::default(), }); let hasty_pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { label: None, layout: Some(&pipeline_layout), module: &shaders_module, entry_point: "hasty_main", + constants: &Default::default(), }); //---------------------------------------------------------- diff --git a/examples/src/hello_triangle/mod.rs b/examples/src/hello_triangle/mod.rs index faa1db8f8..76b7a5a73 100644 --- a/examples/src/hello_triangle/mod.rs +++ b/examples/src/hello_triangle/mod.rs @@ -60,10 +60,12 @@ async fn run(event_loop: EventLoop<()>, window: Window) { module: &shader, entry_point: "vs_main", buffers: &[], + constants: &Default::default(), }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(swapchain_format.into())], }), primitive: wgpu::PrimitiveState::default(), diff --git a/examples/src/hello_workgroups/mod.rs b/examples/src/hello_workgroups/mod.rs index 3e5795048..5fb0eff6b 100644 --- a/examples/src/hello_workgroups/mod.rs +++ b/examples/src/hello_workgroups/mod.rs @@ -110,6 +110,7 @@ async fn run() { layout: Some(&pipeline_layout), module: &shader, entry_point: "main", + constants: &Default::default(), }); //---------------------------------------------------------- diff --git a/examples/src/mipmap/mod.rs b/examples/src/mipmap/mod.rs index 755102102..fc40d5d88 100644 --- a/examples/src/mipmap/mod.rs +++ b/examples/src/mipmap/mod.rs @@ -93,11 +93,13 @@ impl Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(TEXTURE_FORMAT.into())], }), primitive: wgpu::PrimitiveState { @@ -290,11 +292,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: wgpu::PrimitiveState { diff --git a/examples/src/msaa_line/mod.rs b/examples/src/msaa_line/mod.rs index 595bcbf17..178968f47 100644 --- a/examples/src/msaa_line/mod.rs +++ b/examples/src/msaa_line/mod.rs @@ -54,6 +54,7 @@ impl Example { vertex: wgpu::VertexState { module: shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &[wgpu::VertexBufferLayout { array_stride: std::mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::VertexStepMode::Vertex, @@ -63,6 +64,7 @@ impl Example { fragment: Some(wgpu::FragmentState { module: shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: wgpu::PrimitiveState { diff --git a/examples/src/render_to_texture/mod.rs b/examples/src/render_to_texture/mod.rs index 96be26b0f..0cb2cdea7 100644 --- a/examples/src/render_to_texture/mod.rs +++ b/examples/src/render_to_texture/mod.rs @@ -59,11 +59,13 @@ async fn run(_path: Option) { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(wgpu::TextureFormat::Rgba8UnormSrgb.into())], }), primitive: wgpu::PrimitiveState::default(), diff --git a/examples/src/repeated_compute/mod.rs b/examples/src/repeated_compute/mod.rs index faed2467b..0c4705519 100644 --- a/examples/src/repeated_compute/mod.rs +++ b/examples/src/repeated_compute/mod.rs @@ -245,6 +245,7 @@ impl WgpuContext { layout: Some(&pipeline_layout), module: &shader, entry_point: "main", + constants: &Default::default(), }); WgpuContext { diff --git a/examples/src/shadow/mod.rs b/examples/src/shadow/mod.rs index 485d0d78d..d0a29cc8b 100644 --- a/examples/src/shadow/mod.rs +++ b/examples/src/shadow/mod.rs @@ -500,6 +500,7 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_bake", + constants: &Default::default(), buffers: &[vb_desc.clone()], }, fragment: None, @@ -632,6 +633,7 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &[vb_desc], }, fragment: Some(wgpu::FragmentState { @@ -641,6 +643,7 @@ impl crate::framework::Example for Example { } else { "fs_main_without_storage" }, + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: wgpu::PrimitiveState { diff --git a/examples/src/skybox/mod.rs b/examples/src/skybox/mod.rs index bdb5e6614..443c9d41e 100644 --- a/examples/src/skybox/mod.rs +++ b/examples/src/skybox/mod.rs @@ -199,11 +199,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_sky", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_sky", + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: wgpu::PrimitiveState { @@ -226,6 +228,7 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_entity", + constants: &Default::default(), buffers: &[wgpu::VertexBufferLayout { array_stride: std::mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::VertexStepMode::Vertex, @@ -235,6 +238,7 @@ impl crate::framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_entity", + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: wgpu::PrimitiveState { diff --git a/examples/src/srgb_blend/mod.rs b/examples/src/srgb_blend/mod.rs index d4021e6c5..fdff310c3 100644 --- a/examples/src/srgb_blend/mod.rs +++ b/examples/src/srgb_blend/mod.rs @@ -131,11 +131,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &vertex_buffers, }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(wgpu::ColorTargetState { format: config.view_formats[0], blend: Some(wgpu::BlendState::ALPHA_BLENDING), diff --git a/examples/src/stencil_triangles/mod.rs b/examples/src/stencil_triangles/mod.rs index bf645d3a3..07b8e3ec5 100644 --- a/examples/src/stencil_triangles/mod.rs +++ b/examples/src/stencil_triangles/mod.rs @@ -74,11 +74,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &vertex_buffers, }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(wgpu::ColorTargetState { format: config.view_formats[0], blend: None, @@ -112,11 +114,13 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &vertex_buffers, }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: Default::default(), diff --git a/examples/src/storage_texture/mod.rs b/examples/src/storage_texture/mod.rs index d4e207f3b..f83f61967 100644 --- a/examples/src/storage_texture/mod.rs +++ b/examples/src/storage_texture/mod.rs @@ -100,6 +100,7 @@ async fn run(_path: Option) { layout: Some(&pipeline_layout), module: &shader, entry_point: "main", + constants: &Default::default(), }); log::info!("Wgpu context set up."); diff --git a/examples/src/texture_arrays/mod.rs b/examples/src/texture_arrays/mod.rs index ccad75999..c786b0efe 100644 --- a/examples/src/texture_arrays/mod.rs +++ b/examples/src/texture_arrays/mod.rs @@ -321,6 +321,7 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &base_shader_module, entry_point: "vert_main", + constants: &Default::default(), buffers: &[wgpu::VertexBufferLayout { array_stride: vertex_size as wgpu::BufferAddress, step_mode: wgpu::VertexStepMode::Vertex, @@ -330,6 +331,7 @@ impl crate::framework::Example for Example { fragment: Some(wgpu::FragmentState { module: fragment_shader_module, entry_point: fragment_entry_point, + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: wgpu::PrimitiveState { diff --git a/examples/src/timestamp_queries/mod.rs b/examples/src/timestamp_queries/mod.rs index 4911af413..58952c76c 100644 --- a/examples/src/timestamp_queries/mod.rs +++ b/examples/src/timestamp_queries/mod.rs @@ -298,6 +298,7 @@ fn compute_pass( layout: None, module, entry_point: "main_cs", + constants: &Default::default(), }); let bind_group_layout = compute_pipeline.get_bind_group_layout(0); let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { @@ -352,11 +353,13 @@ fn render_pass( vertex: wgpu::VertexState { module, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(format.into())], }), primitive: wgpu::PrimitiveState::default(), diff --git a/examples/src/uniform_values/mod.rs b/examples/src/uniform_values/mod.rs index 4a31ddc06..1ddee03e9 100644 --- a/examples/src/uniform_values/mod.rs +++ b/examples/src/uniform_values/mod.rs @@ -179,11 +179,13 @@ impl WgpuContext { vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(swapchain_format.into())], }), primitive: wgpu::PrimitiveState::default(), diff --git a/examples/src/water/mod.rs b/examples/src/water/mod.rs index 7371e9615..0cd00aac5 100644 --- a/examples/src/water/mod.rs +++ b/examples/src/water/mod.rs @@ -512,6 +512,7 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &water_module, entry_point: "vs_main", + constants: &Default::default(), // Layout of our vertices. This should match the structs // which are uploaded to the GPU. This should also be // ensured by tagging on either a `#[repr(C)]` onto a @@ -527,6 +528,7 @@ impl crate::framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &water_module, entry_point: "fs_main", + constants: &Default::default(), // Describes how the colour will be interpolated // and assigned to the output attachment. targets: &[Some(wgpu::ColorTargetState { @@ -581,6 +583,7 @@ impl crate::framework::Example for Example { vertex: wgpu::VertexState { module: &terrain_module, entry_point: "vs_main", + constants: &Default::default(), buffers: &[wgpu::VertexBufferLayout { array_stride: terrain_vertex_size as wgpu::BufferAddress, step_mode: wgpu::VertexStepMode::Vertex, @@ -590,6 +593,7 @@ impl crate::framework::Example for Example { fragment: Some(wgpu::FragmentState { module: &terrain_module, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(config.view_formats[0].into())], }), primitive: wgpu::PrimitiveState { diff --git a/naga-cli/src/bin/naga.rs b/naga-cli/src/bin/naga.rs index 29e5a5044..a20611114 100644 --- a/naga-cli/src/bin/naga.rs +++ b/naga-cli/src/bin/naga.rs @@ -593,6 +593,7 @@ fn write_output( pipeline_options_owned = spv::PipelineOptions { entry_point: name.clone(), shader_stage: module.entry_points[ep_index].stage, + constants: naga::back::PipelineConstants::default(), }; Some(&pipeline_options_owned) } @@ -633,6 +634,7 @@ fn write_output( _ => unreachable!(), }, multiview: None, + constants: naga::back::PipelineConstants::default(), }; let mut buffer = String::new(); @@ -668,6 +670,7 @@ fn write_output( "Generating hlsl output requires validation to \ succeed, and it failed in a previous step", ))?, + &hlsl::PipelineOptions::default(), ) .unwrap_pretty(); fs::write(output_path, buffer)?; diff --git a/naga/benches/criterion.rs b/naga/benches/criterion.rs index e57c58a84..420c9ee33 100644 --- a/naga/benches/criterion.rs +++ b/naga/benches/criterion.rs @@ -193,6 +193,7 @@ fn backends(c: &mut Criterion) { let pipeline_options = naga::back::spv::PipelineOptions { shader_stage: ep.stage, entry_point: ep.name.clone(), + constants: naga::back::PipelineConstants::default(), }; writer .write(module, info, Some(&pipeline_options), &None, &mut data) @@ -223,10 +224,11 @@ fn backends(c: &mut Criterion) { group.bench_function("hlsl", |b| { b.iter(|| { let options = naga::back::hlsl::Options::default(); + let pipeline_options = naga::back::hlsl::PipelineOptions::default(); let mut string = String::new(); for &(ref module, ref info) in inputs.iter() { let mut writer = naga::back::hlsl::Writer::new(&mut string, &options); - let _ = writer.write(module, info); // may fail on unimplemented things + let _ = writer.write(module, info, &pipeline_options); // may fail on unimplemented things string.clear(); } }); @@ -248,6 +250,7 @@ fn backends(c: &mut Criterion) { shader_stage: ep.stage, entry_point: ep.name.clone(), multiview: None, + constants: naga::back::PipelineConstants::default(), }; // might be `Err` if missing features diff --git a/naga/src/back/glsl/mod.rs b/naga/src/back/glsl/mod.rs index 9bda59461..410b69eaf 100644 --- a/naga/src/back/glsl/mod.rs +++ b/naga/src/back/glsl/mod.rs @@ -282,7 +282,7 @@ impl Default for Options { } /// A subset of options meant to be changed per pipeline. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] pub struct PipelineOptions { @@ -294,6 +294,8 @@ pub struct PipelineOptions { pub entry_point: String, /// How many views to render to, if doing multiview rendering. pub multiview: Option, + /// Pipeline constants. + pub constants: back::PipelineConstants, } #[derive(Debug)] diff --git a/naga/src/back/hlsl/mod.rs b/naga/src/back/hlsl/mod.rs index f37a223f4..37d26bf3b 100644 --- a/naga/src/back/hlsl/mod.rs +++ b/naga/src/back/hlsl/mod.rs @@ -195,6 +195,14 @@ pub struct Options { pub zero_initialize_workgroup_memory: bool, } +#[derive(Clone, Debug, Default)] +#[cfg_attr(feature = "serialize", derive(serde::Serialize))] +#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] +pub struct PipelineOptions { + /// Pipeline constants. + pub constants: back::PipelineConstants, +} + impl Default for Options { fn default() -> Self { Options { diff --git a/naga/src/back/hlsl/writer.rs b/naga/src/back/hlsl/writer.rs index 4ba856946..b442637c4 100644 --- a/naga/src/back/hlsl/writer.rs +++ b/naga/src/back/hlsl/writer.rs @@ -1,7 +1,7 @@ use super::{ help::{WrappedArrayLength, WrappedConstructor, WrappedImageQuery, WrappedStructMatrixAccess}, storage::StoreValue, - BackendResult, Error, Options, + BackendResult, Error, Options, PipelineOptions, }; use crate::{ back, @@ -167,6 +167,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { &mut self, module: &Module, module_info: &valid::ModuleInfo, + _pipeline_options: &PipelineOptions, ) -> Result { self.reset(module); diff --git a/naga/src/back/mod.rs b/naga/src/back/mod.rs index c8f091dec..61dc4a060 100644 --- a/naga/src/back/mod.rs +++ b/naga/src/back/mod.rs @@ -26,6 +26,15 @@ pub const BAKE_PREFIX: &str = "_e"; /// Expressions that need baking. pub type NeedBakeExpressions = crate::FastHashSet>; +/// Specifies the values of pipeline-overridable constants in the shader module. +/// +/// If an `@id` attribute was specified on the declaration, +/// the key must be the pipeline constant ID as a decimal ASCII number; if not, +/// the key must be the constant's identifier name. +/// +/// The value may represent any of WGSL's concrete scalar types. +pub type PipelineConstants = std::collections::HashMap; + /// Indentation level. #[derive(Clone, Copy)] pub struct Level(pub usize); diff --git a/naga/src/back/msl/mod.rs b/naga/src/back/msl/mod.rs index 68e5b7990..7e05be29b 100644 --- a/naga/src/back/msl/mod.rs +++ b/naga/src/back/msl/mod.rs @@ -221,7 +221,7 @@ impl Default for Options { } /// A subset of options that are meant to be changed per pipeline. -#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Default, Clone)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] pub struct PipelineOptions { @@ -232,6 +232,8 @@ pub struct PipelineOptions { /// /// Enable this for vertex shaders with point primitive topologies. pub allow_and_force_point_size: bool, + /// Pipeline constants. + pub constants: crate::back::PipelineConstants, } impl Options { diff --git a/naga/src/back/spv/mod.rs b/naga/src/back/spv/mod.rs index eb29e3cd8..087c49bcc 100644 --- a/naga/src/back/spv/mod.rs +++ b/naga/src/back/spv/mod.rs @@ -725,7 +725,7 @@ impl<'a> Default for Options<'a> { } // A subset of options meant to be changed per pipeline. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] pub struct PipelineOptions { @@ -735,6 +735,8 @@ pub struct PipelineOptions { /// /// If no entry point that matches is found while creating a [`Writer`], a error will be thrown. pub entry_point: String, + /// Pipeline constants. + pub constants: crate::back::PipelineConstants, } pub fn write_vec( diff --git a/naga/tests/in/interface.param.ron b/naga/tests/in/interface.param.ron index 4d8566176..19ed5e464 100644 --- a/naga/tests/in/interface.param.ron +++ b/naga/tests/in/interface.param.ron @@ -27,5 +27,6 @@ ), msl_pipeline: ( allow_and_force_point_size: true, + constants: {}, ), ) diff --git a/naga/tests/snapshots.rs b/naga/tests/snapshots.rs index 198a4aa2d..f19077869 100644 --- a/naga/tests/snapshots.rs +++ b/naga/tests/snapshots.rs @@ -428,6 +428,7 @@ fn write_output_spv( let pipeline_options = spv::PipelineOptions { entry_point: ep.name.clone(), shader_stage: ep.stage, + constants: naga::back::PipelineConstants::default(), }; write_output_spv_inner( input, @@ -516,6 +517,7 @@ fn write_output_glsl( shader_stage: stage, entry_point: ep_name.to_string(), multiview, + constants: naga::back::PipelineConstants::default(), }; let mut buffer = String::new(); @@ -548,7 +550,9 @@ fn write_output_hlsl( let mut buffer = String::new(); let mut writer = hlsl::Writer::new(&mut buffer, options); - let reflection_info = writer.write(module, info).expect("HLSL write failed"); + let reflection_info = writer + .write(module, info, &hlsl::PipelineOptions::default()) + .expect("HLSL write failed"); input.write_output_file("hlsl", "hlsl", buffer); diff --git a/player/tests/data/bind-group.ron b/player/tests/data/bind-group.ron index 471f921fe..92415e4ff 100644 --- a/player/tests/data/bind-group.ron +++ b/player/tests/data/bind-group.ron @@ -57,6 +57,7 @@ stage: ( module: Id(0, 1, Empty), entry_point: None, + constants: {}, ), ), ), diff --git a/player/tests/data/pipeline-statistics-query.ron b/player/tests/data/pipeline-statistics-query.ron index 8274e341f..3c672f4e5 100644 --- a/player/tests/data/pipeline-statistics-query.ron +++ b/player/tests/data/pipeline-statistics-query.ron @@ -30,6 +30,7 @@ stage: ( module: Id(0, 1, Empty), entry_point: None, + constants: {}, ), ), ), diff --git a/player/tests/data/quad.ron b/player/tests/data/quad.ron index b7db1f8c2..9d6b4a25f 100644 --- a/player/tests/data/quad.ron +++ b/player/tests/data/quad.ron @@ -58,6 +58,7 @@ stage: ( module: Id(0, 1, Empty), entry_point: None, + constants: {}, ), buffers: [], ), @@ -65,6 +66,7 @@ stage: ( module: Id(0, 1, Empty), entry_point: None, + constants: {}, ), targets: [ Some(( diff --git a/player/tests/data/zero-init-buffer.ron b/player/tests/data/zero-init-buffer.ron index be9a20d89..5697a2555 100644 --- a/player/tests/data/zero-init-buffer.ron +++ b/player/tests/data/zero-init-buffer.ron @@ -134,6 +134,7 @@ stage: ( module: Id(0, 1, Empty), entry_point: None, + constants: {}, ), ), ), diff --git a/player/tests/data/zero-init-texture-binding.ron b/player/tests/data/zero-init-texture-binding.ron index 41a513f60..340cb0cfa 100644 --- a/player/tests/data/zero-init-texture-binding.ron +++ b/player/tests/data/zero-init-texture-binding.ron @@ -135,6 +135,7 @@ stage: ( module: Id(0, 1, Empty), entry_point: None, + constants: {}, ), ), ), diff --git a/tests/src/image.rs b/tests/src/image.rs index e1b9b0720..98310233c 100644 --- a/tests/src/image.rs +++ b/tests/src/image.rs @@ -369,6 +369,7 @@ fn copy_via_compute( layout: Some(&pll), module: &sm, entry_point: "copy_texture_to_buffer", + constants: &Default::default(), }); { diff --git a/tests/tests/bgra8unorm_storage.rs b/tests/tests/bgra8unorm_storage.rs index b1ca3b836..c3913e5df 100644 --- a/tests/tests/bgra8unorm_storage.rs +++ b/tests/tests/bgra8unorm_storage.rs @@ -96,6 +96,7 @@ static BGRA8_UNORM_STORAGE: GpuTestConfiguration = GpuTestConfiguration::new() label: None, layout: Some(&pl), entry_point: "main", + constants: &Default::default(), module: &module, }); diff --git a/tests/tests/bind_group_layout_dedup.rs b/tests/tests/bind_group_layout_dedup.rs index 7ac30fb8f..519cfbda2 100644 --- a/tests/tests/bind_group_layout_dedup.rs +++ b/tests/tests/bind_group_layout_dedup.rs @@ -90,6 +90,7 @@ async fn bgl_dedupe(ctx: TestingContext) { layout: Some(&pipeline_layout), module: &module, entry_point: "no_resources", + constants: &Default::default(), }; let pipeline = ctx.device.create_compute_pipeline(&desc); @@ -218,6 +219,7 @@ fn bgl_dedupe_with_dropped_user_handle(ctx: TestingContext) { layout: Some(&pipeline_layout), module: &module, entry_point: "no_resources", + constants: &Default::default(), }); let mut encoder = ctx.device.create_command_encoder(&Default::default()); @@ -263,6 +265,7 @@ fn bgl_dedupe_derived(ctx: TestingContext) { layout: None, module: &module, entry_point: "resources", + constants: &Default::default(), }); // We create two bind groups, pulling the bind_group_layout from the pipeline each time. @@ -333,6 +336,7 @@ fn separate_programs_have_incompatible_derived_bgls(ctx: TestingContext) { layout: None, module: &module, entry_point: "resources", + constants: &Default::default(), }; // Create two pipelines, creating a BG from the second. let pipeline1 = ctx.device.create_compute_pipeline(&desc); @@ -394,6 +398,7 @@ fn derived_bgls_incompatible_with_regular_bgls(ctx: TestingContext) { layout: None, module: &module, entry_point: "resources", + constants: &Default::default(), }); // Create a matching BGL diff --git a/tests/tests/buffer.rs b/tests/tests/buffer.rs index a5fcf3e59..1622995c3 100644 --- a/tests/tests/buffer.rs +++ b/tests/tests/buffer.rs @@ -224,6 +224,7 @@ static MINIMUM_BUFFER_BINDING_SIZE_LAYOUT: GpuTestConfiguration = GpuTestConfigu layout: Some(&pipeline_layout), module: &shader_module, entry_point: "main", + constants: &Default::default(), }); }); }); @@ -292,6 +293,7 @@ static MINIMUM_BUFFER_BINDING_SIZE_DISPATCH: GpuTestConfiguration = GpuTestConfi layout: Some(&pipeline_layout), module: &shader_module, entry_point: "main", + constants: &Default::default(), }); let buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor { diff --git a/tests/tests/device.rs b/tests/tests/device.rs index ff596d091..82e3f71a1 100644 --- a/tests/tests/device.rs +++ b/tests/tests/device.rs @@ -480,6 +480,7 @@ static DEVICE_DESTROY_THEN_MORE: GpuTestConfiguration = GpuTestConfiguration::ne vertex: wgpu::VertexState { module: &shader_module, entry_point: "", + constants: &Default::default(), buffers: &[], }, primitive: wgpu::PrimitiveState::default(), @@ -498,6 +499,7 @@ static DEVICE_DESTROY_THEN_MORE: GpuTestConfiguration = GpuTestConfiguration::ne layout: None, module: &shader_module, entry_point: "", + constants: &Default::default(), }); }); @@ -734,6 +736,7 @@ fn vs_main() -> @builtin(position) vec4 { fragment: Some(wgpu::FragmentState { module: &trivial_shaders_with_some_reversed_bindings, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(wgt::ColorTargetState { format: wgt::TextureFormat::Bgra8Unorm, blend: None, @@ -747,6 +750,7 @@ fn vs_main() -> @builtin(position) vec4 { vertex: wgpu::VertexState { module: &trivial_shaders_with_some_reversed_bindings, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, primitive: wgt::PrimitiveState::default(), diff --git a/tests/tests/mem_leaks.rs b/tests/tests/mem_leaks.rs index 83fa2bbc1..949b4d96c 100644 --- a/tests/tests/mem_leaks.rs +++ b/tests/tests/mem_leaks.rs @@ -95,15 +95,17 @@ async fn draw_test_with_reports( layout: Some(&ppl), vertex: wgpu::VertexState { buffers: &[], - entry_point: "vs_main_builtin", module: &shader, + entry_point: "vs_main_builtin", + constants: &Default::default(), }, primitive: wgpu::PrimitiveState::default(), depth_stencil: None, multisample: wgpu::MultisampleState::default(), fragment: Some(wgpu::FragmentState { - entry_point: "fs_main", module: &shader, + entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(wgpu::ColorTargetState { format: wgpu::TextureFormat::Rgba8Unorm, blend: None, diff --git a/tests/tests/nv12_texture/mod.rs b/tests/tests/nv12_texture/mod.rs index aba12e02b..0f4ba16f2 100644 --- a/tests/tests/nv12_texture/mod.rs +++ b/tests/tests/nv12_texture/mod.rs @@ -24,11 +24,13 @@ static NV12_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfigurati vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(target_format.into())], }), primitive: wgpu::PrimitiveState { diff --git a/tests/tests/occlusion_query/mod.rs b/tests/tests/occlusion_query/mod.rs index 0c3f3072a..2db035bfb 100644 --- a/tests/tests/occlusion_query/mod.rs +++ b/tests/tests/occlusion_query/mod.rs @@ -37,6 +37,7 @@ static OCCLUSION_QUERY: GpuTestConfiguration = GpuTestConfiguration::new() vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: None, diff --git a/tests/tests/partially_bounded_arrays/mod.rs b/tests/tests/partially_bounded_arrays/mod.rs index a1350718f..b93e900a9 100644 --- a/tests/tests/partially_bounded_arrays/mod.rs +++ b/tests/tests/partially_bounded_arrays/mod.rs @@ -69,6 +69,7 @@ static PARTIALLY_BOUNDED_ARRAY: GpuTestConfiguration = GpuTestConfiguration::new layout: Some(&pipeline_layout), module: &cs_module, entry_point: "main", + constants: &Default::default(), }); let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { diff --git a/tests/tests/pipeline.rs b/tests/tests/pipeline.rs index 2350f1066..c8814e25f 100644 --- a/tests/tests/pipeline.rs +++ b/tests/tests/pipeline.rs @@ -28,6 +28,7 @@ static PIPELINE_DEFAULT_LAYOUT_BAD_MODULE: GpuTestConfiguration = GpuTestConfigu layout: None, module: &module, entry_point: "doesn't exist", + constants: &Default::default(), }); pipeline.get_bind_group_layout(0); diff --git a/tests/tests/push_constants.rs b/tests/tests/push_constants.rs index 0e16b3df6..d1119476c 100644 --- a/tests/tests/push_constants.rs +++ b/tests/tests/push_constants.rs @@ -103,6 +103,7 @@ async fn partial_update_test(ctx: TestingContext) { layout: Some(&pipeline_layout), module: &sm, entry_point: "main", + constants: &Default::default(), }); let mut encoder = ctx diff --git a/tests/tests/regression/issue_3349.rs b/tests/tests/regression/issue_3349.rs index 2d94d5692..93b91b9d7 100644 --- a/tests/tests/regression/issue_3349.rs +++ b/tests/tests/regression/issue_3349.rs @@ -102,11 +102,13 @@ async fn multi_stage_data_binding_test(ctx: TestingContext) { vertex: wgpu::VertexState { module: &vs_sm, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: &fs_sm, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(wgpu::ColorTargetState { format: wgpu::TextureFormat::Rgba8Unorm, blend: None, diff --git a/tests/tests/regression/issue_3457.rs b/tests/tests/regression/issue_3457.rs index 12ace62e8..0fca44b0c 100644 --- a/tests/tests/regression/issue_3457.rs +++ b/tests/tests/regression/issue_3457.rs @@ -52,6 +52,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration = vertex: VertexState { module: &module, entry_point: "double_buffer_vert", + constants: &Default::default(), buffers: &[ VertexBufferLayout { array_stride: 16, @@ -71,6 +72,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration = fragment: Some(FragmentState { module: &module, entry_point: "double_buffer_frag", + constants: &Default::default(), targets: &[Some(ColorTargetState { format: TextureFormat::Rgba8Unorm, blend: None, @@ -88,6 +90,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration = vertex: VertexState { module: &module, entry_point: "single_buffer_vert", + constants: &Default::default(), buffers: &[VertexBufferLayout { array_stride: 16, step_mode: VertexStepMode::Vertex, @@ -100,6 +103,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration = fragment: Some(FragmentState { module: &module, entry_point: "single_buffer_frag", + constants: &Default::default(), targets: &[Some(ColorTargetState { format: TextureFormat::Rgba8Unorm, blend: None, diff --git a/tests/tests/scissor_tests/mod.rs b/tests/tests/scissor_tests/mod.rs index 11b72ba7a..efc658501 100644 --- a/tests/tests/scissor_tests/mod.rs +++ b/tests/tests/scissor_tests/mod.rs @@ -42,16 +42,18 @@ async fn scissor_test_impl( label: Some("Pipeline"), layout: None, vertex: wgpu::VertexState { - entry_point: "vs_main", module: &shader, + entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, primitive: wgpu::PrimitiveState::default(), depth_stencil: None, multisample: wgpu::MultisampleState::default(), fragment: Some(wgpu::FragmentState { - entry_point: "fs_main", module: &shader, + entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(wgpu::ColorTargetState { format: wgpu::TextureFormat::Rgba8Unorm, blend: None, diff --git a/tests/tests/shader/mod.rs b/tests/tests/shader/mod.rs index 1a981971f..bb93c690e 100644 --- a/tests/tests/shader/mod.rs +++ b/tests/tests/shader/mod.rs @@ -307,6 +307,7 @@ async fn shader_input_output_test( layout: Some(&pll), module: &sm, entry_point: "cs_main", + constants: &Default::default(), }); // -- Initializing data -- diff --git a/tests/tests/shader/zero_init_workgroup_mem.rs b/tests/tests/shader/zero_init_workgroup_mem.rs index 6774f1aac..2bbcd87d9 100644 --- a/tests/tests/shader/zero_init_workgroup_mem.rs +++ b/tests/tests/shader/zero_init_workgroup_mem.rs @@ -87,6 +87,7 @@ static ZERO_INIT_WORKGROUP_MEMORY: GpuTestConfiguration = GpuTestConfiguration:: layout: Some(&pll), module: &sm, entry_point: "read", + constants: &Default::default(), }); let pipeline_write = ctx @@ -96,6 +97,7 @@ static ZERO_INIT_WORKGROUP_MEMORY: GpuTestConfiguration = GpuTestConfiguration:: layout: None, module: &sm, entry_point: "write", + constants: &Default::default(), }); // -- Initializing data -- diff --git a/tests/tests/shader_primitive_index/mod.rs b/tests/tests/shader_primitive_index/mod.rs index 096df9c0f..fa6bbcfb5 100644 --- a/tests/tests/shader_primitive_index/mod.rs +++ b/tests/tests/shader_primitive_index/mod.rs @@ -120,6 +120,9 @@ async fn pulling_common( label: None, layout: None, vertex: wgpu::VertexState { + module: &shader, + entry_point: "vs_main", + constants: &Default::default(), buffers: &[wgpu::VertexBufferLayout { array_stride: 8, step_mode: wgpu::VertexStepMode::Vertex, @@ -129,15 +132,14 @@ async fn pulling_common( shader_location: 0, }], }], - entry_point: "vs_main", - module: &shader, }, primitive: wgpu::PrimitiveState::default(), depth_stencil: None, multisample: wgpu::MultisampleState::default(), fragment: Some(wgpu::FragmentState { - entry_point: "fs_main", module: &shader, + entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(wgpu::ColorTargetState { format: wgpu::TextureFormat::Rgba8Unorm, blend: None, diff --git a/tests/tests/shader_view_format/mod.rs b/tests/tests/shader_view_format/mod.rs index 842388763..60efa0130 100644 --- a/tests/tests/shader_view_format/mod.rs +++ b/tests/tests/shader_view_format/mod.rs @@ -93,11 +93,13 @@ async fn reinterpret( vertex: wgpu::VertexState { module: shader, entry_point: "vs_main", + constants: &Default::default(), buffers: &[], }, fragment: Some(wgpu::FragmentState { module: shader, entry_point: "fs_main", + constants: &Default::default(), targets: &[Some(src_format.into())], }), primitive: wgpu::PrimitiveState { diff --git a/tests/tests/vertex_indices/mod.rs b/tests/tests/vertex_indices/mod.rs index e0a2cbae0..77e08489b 100644 --- a/tests/tests/vertex_indices/mod.rs +++ b/tests/tests/vertex_indices/mod.rs @@ -272,20 +272,23 @@ async fn vertex_index_common(ctx: TestingContext) { push_constant_ranges: &[], }); + let constants = &Default::default(); let mut pipeline_desc = wgpu::RenderPipelineDescriptor { label: None, layout: Some(&ppl), vertex: wgpu::VertexState { buffers: &[], - entry_point: "vs_main_builtin", module: &shader, + entry_point: "vs_main_builtin", + constants, }, primitive: wgpu::PrimitiveState::default(), depth_stencil: None, multisample: wgpu::MultisampleState::default(), fragment: Some(wgpu::FragmentState { - entry_point: "fs_main", module: &shader, + entry_point: "fs_main", + constants, targets: &[Some(wgpu::ColorTargetState { format: wgpu::TextureFormat::Rgba8Unorm, blend: None, diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 4892aecb7..c626d8193 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -2762,8 +2762,9 @@ impl Device { label: desc.label.to_hal(self.instance_flags), layout: pipeline_layout.raw(), stage: hal::ProgrammableStage { - entry_point: final_entry_point_name.as_ref(), module: shader_module.raw(), + entry_point: final_entry_point_name.as_ref(), + constants: desc.stage.constants.as_ref(), }, }; @@ -3178,6 +3179,7 @@ impl Device { hal::ProgrammableStage { module: vertex_shader_module.raw(), entry_point: &vertex_entry_point_name, + constants: stage_desc.constants.as_ref(), } }; @@ -3237,6 +3239,7 @@ impl Device { Some(hal::ProgrammableStage { module: shader_module.raw(), entry_point: &fragment_entry_point_name, + constants: fragment_state.stage.constants.as_ref(), }) } None => None, diff --git a/wgpu-core/src/pipeline.rs b/wgpu-core/src/pipeline.rs index 4a7651b32..b1689bd69 100644 --- a/wgpu-core/src/pipeline.rs +++ b/wgpu-core/src/pipeline.rs @@ -233,6 +233,14 @@ pub struct ProgrammableStageDescriptor<'a> { /// * If a single entry point associated with this stage must be in the shader, then proceed as /// if `Some(…)` was specified with that entry point's name. pub entry_point: Option>, + /// Specifies the values of pipeline-overridable constants in the shader module. + /// + /// If an `@id` attribute was specified on the declaration, + /// the key must be the pipeline constant ID as a decimal ASCII number; if not, + /// the key must be the constant's identifier name. + /// + /// The value may represent any of WGSL's concrete scalar types. + pub constants: Cow<'a, naga::back::PipelineConstants>, } /// Number of implicit bind groups derived at pipeline creation. diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index c238f299e..29dfd49d2 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -245,17 +245,20 @@ impl Example { .unwrap() }; + let constants = naga::back::PipelineConstants::default(); let pipeline_desc = hal::RenderPipelineDescriptor { label: None, layout: &pipeline_layout, vertex_stage: hal::ProgrammableStage { module: &shader, entry_point: "vs_main", + constants: &constants, }, vertex_buffers: &[], fragment_stage: Some(hal::ProgrammableStage { module: &shader, entry_point: "fs_main", + constants: &constants, }), primitive: wgt::PrimitiveState { topology: wgt::PrimitiveTopology::TriangleStrip, diff --git a/wgpu-hal/examples/ray-traced-triangle/main.rs b/wgpu-hal/examples/ray-traced-triangle/main.rs index c05feae82..2ed2d6462 100644 --- a/wgpu-hal/examples/ray-traced-triangle/main.rs +++ b/wgpu-hal/examples/ray-traced-triangle/main.rs @@ -371,6 +371,7 @@ impl Example { stage: hal::ProgrammableStage { module: &shader_module, entry_point: "main", + constants: &Default::default(), }, }) } diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 23bd409dc..69a846d13 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -222,10 +222,13 @@ impl super::Device { //TODO: reuse the writer let mut source = String::new(); let mut writer = hlsl::Writer::new(&mut source, &layout.naga_options); + let pipeline_options = hlsl::PipelineOptions { + constants: stage.constants.to_owned(), + }; let reflection_info = { profiling::scope!("naga::back::hlsl::write"); writer - .write(module, &stage.module.naga.info) + .write(module, &stage.module.naga.info, &pipeline_options) .map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("HLSL: {e:?}")))? }; diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index 50c07f3ff..171c53a93 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -218,6 +218,7 @@ impl super::Device { shader_stage: naga_stage, entry_point: stage.entry_point.to_string(), multiview: context.multiview, + constants: stage.constants.to_owned(), }; let shader = &stage.module.naga; diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 79bd54e66..a3f9ac572 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -1318,6 +1318,8 @@ pub struct ProgrammableStage<'a, A: Api> { /// The name of the entry point in the compiled shader. There must be a function with this name /// in the shader. pub entry_point: &'a str, + /// Pipeline constants + pub constants: &'a naga::back::PipelineConstants, } // Rust gets confused about the impl requirements for `A` @@ -1326,6 +1328,7 @@ impl Clone for ProgrammableStage<'_, A> { Self { module: self.module, entry_point: self.entry_point, + constants: self.constants, } } } diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index 179429f5d..382690938 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -112,6 +112,7 @@ impl super::Device { metal::MTLPrimitiveTopologyClass::Point => true, _ => false, }, + constants: stage.constants.to_owned(), }; let (source, info) = naga::back::msl::write_string( diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 70028cc70..2dcded220 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -734,6 +734,7 @@ impl super::Device { let pipeline_options = naga::back::spv::PipelineOptions { entry_point: stage.entry_point.to_string(), shader_stage: naga_stage, + constants: stage.constants.to_owned(), }; let needs_temp_options = !runtime_checks || !binding_map.is_empty() diff --git a/wgpu/src/backend/wgpu_core.rs b/wgpu/src/backend/wgpu_core.rs index 98f1ca1de..c73b0fbd1 100644 --- a/wgpu/src/backend/wgpu_core.rs +++ b/wgpu/src/backend/wgpu_core.rs @@ -1143,6 +1143,7 @@ impl crate::Context for ContextWgpuCore { stage: pipe::ProgrammableStageDescriptor { module: desc.vertex.module.id.into(), entry_point: Some(Borrowed(desc.vertex.entry_point)), + constants: Borrowed(desc.vertex.constants), }, buffers: Borrowed(&vertex_buffers), }, @@ -1153,6 +1154,7 @@ impl crate::Context for ContextWgpuCore { stage: pipe::ProgrammableStageDescriptor { module: frag.module.id.into(), entry_point: Some(Borrowed(frag.entry_point)), + constants: Borrowed(frag.constants), }, targets: Borrowed(frag.targets), }), @@ -1201,6 +1203,7 @@ impl crate::Context for ContextWgpuCore { stage: pipe::ProgrammableStageDescriptor { module: desc.module.id.into(), entry_point: Some(Borrowed(desc.entry_point)), + constants: Borrowed(desc.constants), }, }; diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index a49c72a1e..3bf77fd10 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -28,6 +28,7 @@ use std::{ any::Any, borrow::Cow, cmp::Ordering, + collections::HashMap, error, fmt, future::Future, marker::PhantomData, @@ -1467,6 +1468,14 @@ pub struct VertexState<'a> { /// The name of the entry point in the compiled shader. There must be a function with this name /// in the shader. pub entry_point: &'a str, + /// Specifies the values of pipeline-overridable constants in the shader module. + /// + /// If an `@id` attribute was specified on the declaration, + /// the key must be the pipeline constant ID as a decimal ASCII number; if not, + /// the key must be the constant's identifier name. + /// + /// The value may represent any of WGSL's concrete scalar types. + pub constants: &'a HashMap, /// The format of any vertex buffers used with this pipeline. pub buffers: &'a [VertexBufferLayout<'a>], } @@ -1486,6 +1495,14 @@ pub struct FragmentState<'a> { /// The name of the entry point in the compiled shader. There must be a function with this name /// in the shader. pub entry_point: &'a str, + /// Specifies the values of pipeline-overridable constants in the shader module. + /// + /// If an `@id` attribute was specified on the declaration, + /// the key must be the pipeline constant ID as a decimal ASCII number; if not, + /// the key must be the constant's identifier name. + /// + /// The value may represent any of WGSL's concrete scalar types. + pub constants: &'a HashMap, /// The color state of the render targets. pub targets: &'a [Option], } @@ -1575,6 +1592,14 @@ pub struct ComputePipelineDescriptor<'a> { /// The name of the entry point in the compiled shader. There must be a function with this name /// and no return value in the shader. pub entry_point: &'a str, + /// Specifies the values of pipeline-overridable constants in the shader module. + /// + /// If an `@id` attribute was specified on the declaration, + /// the key must be the pipeline constant ID as a decimal ASCII number; if not, + /// the key must be the constant's identifier name. + /// + /// The value may represent any of WGSL's concrete scalar types. + pub constants: &'a HashMap, } #[cfg(send_sync)] static_assertions::assert_impl_all!(ComputePipelineDescriptor<'_>: Send, Sync);