Allow configuring whether workgroup memory is zero initialised (#5508)

This commit is contained in:
Daniel McNab 2024-04-17 20:50:31 +01:00 committed by GitHub
parent 40db4df670
commit 965b00c06b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
59 changed files with 219 additions and 125 deletions

View File

@ -118,6 +118,7 @@ Bottom level categories:
- `wgpu::Texture::as_hal` now returns a user-defined type to match the other as_hal functions
- Added support for pipeline-overridable constants. By @teoxoy & @jimblandy in [#5500](https://github.com/gfx-rs/wgpu/pull/5500)
- Support disabling zero-initialization of workgroup local memory in compute shaders. By @DJMcNab in [#5508](https://github.com/gfx-rs/wgpu/pull/5508)
#### GLES

View File

@ -113,6 +113,7 @@ pub fn op_webgpu_create_compute_pipeline(
module: compute_shader_module_resource.1,
entry_point: compute.entry_point.map(Cow::from),
constants: Cow::Owned(compute.constants),
zero_initialize_workgroup_memory: true,
},
};
let implicit_pipelines = match layout {
@ -359,6 +360,8 @@ pub fn op_webgpu_create_render_pipeline(
module: fragment_shader_module_resource.1,
entry_point: Some(Cow::from(fragment.entry_point)),
constants: Cow::Owned(fragment.constants),
// Required to be true for WebGPU
zero_initialize_workgroup_memory: true,
},
targets: Cow::Owned(fragment.targets),
})
@ -382,6 +385,8 @@ pub fn op_webgpu_create_render_pipeline(
module: vertex_shader_module_resource.1,
entry_point: Some(Cow::Owned(args.vertex.entry_point)),
constants: Cow::Owned(args.vertex.constants),
// Required to be true for WebGPU
zero_initialize_workgroup_memory: true,
},
buffers: Cow::Owned(vertex_buffers),
},

View File

@ -132,7 +132,7 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &draw_shader,
entry_point: "main_vs",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[
wgpu::VertexBufferLayout {
array_stride: 4 * 4,
@ -149,7 +149,7 @@ impl crate::framework::Example for Example {
fragment: Some(wgpu::FragmentState {
module: &draw_shader,
entry_point: "main_fs",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: wgpu::PrimitiveState::default(),
@ -165,7 +165,7 @@ impl crate::framework::Example for Example {
layout: Some(&compute_pipeline_layout),
module: &compute_shader,
entry_point: "main",
constants: &Default::default(),
compilation_options: Default::default(),
});
// buffer for the three 2d triangle vertices of each instance

View File

@ -203,13 +203,13 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(wgpu::ColorTargetState {
format: config.view_formats[0],
blend: Some(wgpu::BlendState::ALPHA_BLENDING),

View File

@ -97,13 +97,13 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader_triangle_and_lines,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader_triangle_and_lines,
entry_point: "fs_main_red",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(RENDER_TARGET_FORMAT.into())],
}),
primitive: wgpu::PrimitiveState {
@ -122,13 +122,13 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader_triangle_and_lines,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader_triangle_and_lines,
entry_point: "fs_main_blue",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(RENDER_TARGET_FORMAT.into())],
}),
primitive: wgpu::PrimitiveState::default(),
@ -148,13 +148,13 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader_triangle_and_lines,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader_triangle_and_lines,
entry_point: "fs_main_white",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: wgpu::PrimitiveState {
@ -211,13 +211,13 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: wgpu::PrimitiveState::default(),

View File

@ -244,13 +244,13 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &vertex_buffers,
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: wgpu::PrimitiveState {
@ -272,13 +272,13 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &vertex_buffers,
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_wire",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(wgpu::ColorTargetState {
format: config.view_formats[0],
blend: Some(wgpu::BlendState {

View File

@ -109,7 +109,7 @@ async fn execute_gpu_inner(
layout: None,
module: &cs_module,
entry_point: "main",
constants: &Default::default(),
compilation_options: Default::default(),
});
// Instantiates the bind group, once again specifying the binding of buffers.

View File

@ -103,14 +103,14 @@ async fn execute(
layout: Some(&pipeline_layout),
module: &shaders_module,
entry_point: "patient_main",
constants: &Default::default(),
compilation_options: 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(),
compilation_options: Default::default(),
});
//----------------------------------------------------------

View File

@ -60,12 +60,12 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
module: &shader,
entry_point: "vs_main",
buffers: &[],
constants: &Default::default(),
compilation_options: Default::default(),
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(swapchain_format.into())],
}),
primitive: wgpu::PrimitiveState::default(),

View File

@ -110,7 +110,7 @@ async fn run() {
layout: Some(&pipeline_layout),
module: &shader,
entry_point: "main",
constants: &Default::default(),
compilation_options: Default::default(),
});
//----------------------------------------------------------

View File

@ -93,13 +93,13 @@ impl Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(TEXTURE_FORMAT.into())],
}),
primitive: wgpu::PrimitiveState {
@ -292,13 +292,13 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: wgpu::PrimitiveState {

View File

@ -54,7 +54,7 @@ impl Example {
vertex: wgpu::VertexState {
module: shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
@ -64,7 +64,7 @@ impl Example {
fragment: Some(wgpu::FragmentState {
module: shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: wgpu::PrimitiveState {

View File

@ -59,13 +59,13 @@ async fn run(_path: Option<String>) {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(wgpu::TextureFormat::Rgba8UnormSrgb.into())],
}),
primitive: wgpu::PrimitiveState::default(),

View File

@ -245,7 +245,7 @@ impl WgpuContext {
layout: Some(&pipeline_layout),
module: &shader,
entry_point: "main",
constants: &Default::default(),
compilation_options: Default::default(),
});
WgpuContext {

View File

@ -500,7 +500,7 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_bake",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[vb_desc.clone()],
},
fragment: None,
@ -633,7 +633,7 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[vb_desc],
},
fragment: Some(wgpu::FragmentState {
@ -643,7 +643,7 @@ impl crate::framework::Example for Example {
} else {
"fs_main_without_storage"
},
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: wgpu::PrimitiveState {

View File

@ -199,13 +199,13 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_sky",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_sky",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: wgpu::PrimitiveState {
@ -228,7 +228,7 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_entity",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
@ -238,7 +238,7 @@ impl crate::framework::Example for Example {
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_entity",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: wgpu::PrimitiveState {

View File

@ -131,13 +131,13 @@ impl<const SRGB: bool> crate::framework::Example for Example<SRGB> {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &vertex_buffers,
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(wgpu::ColorTargetState {
format: config.view_formats[0],
blend: Some(wgpu::BlendState::ALPHA_BLENDING),

View File

@ -74,13 +74,13 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &vertex_buffers,
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(wgpu::ColorTargetState {
format: config.view_formats[0],
blend: None,
@ -114,13 +114,13 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &vertex_buffers,
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: Default::default(),

View File

@ -100,7 +100,7 @@ async fn run(_path: Option<String>) {
layout: Some(&pipeline_layout),
module: &shader,
entry_point: "main",
constants: &Default::default(),
compilation_options: Default::default(),
});
log::info!("Wgpu context set up.");

View File

@ -321,7 +321,7 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &base_shader_module,
entry_point: "vert_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: vertex_size as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
@ -331,7 +331,7 @@ impl crate::framework::Example for Example {
fragment: Some(wgpu::FragmentState {
module: fragment_shader_module,
entry_point: fragment_entry_point,
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: wgpu::PrimitiveState {

View File

@ -298,7 +298,7 @@ fn compute_pass(
layout: None,
module,
entry_point: "main_cs",
constants: &Default::default(),
compilation_options: Default::default(),
});
let bind_group_layout = compute_pipeline.get_bind_group_layout(0);
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
@ -353,13 +353,13 @@ fn render_pass(
vertex: wgpu::VertexState {
module,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(format.into())],
}),
primitive: wgpu::PrimitiveState::default(),

View File

@ -179,13 +179,13 @@ impl WgpuContext {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(swapchain_format.into())],
}),
primitive: wgpu::PrimitiveState::default(),

View File

@ -512,7 +512,7 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &water_module,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: 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
@ -528,7 +528,7 @@ impl crate::framework::Example for Example {
fragment: Some(wgpu::FragmentState {
module: &water_module,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
// Describes how the colour will be interpolated
// and assigned to the output attachment.
targets: &[Some(wgpu::ColorTargetState {
@ -583,7 +583,7 @@ impl crate::framework::Example for Example {
vertex: wgpu::VertexState {
module: &terrain_module,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: terrain_vertex_size as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
@ -593,7 +593,7 @@ impl crate::framework::Example for Example {
fragment: Some(wgpu::FragmentState {
module: &terrain_module,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(config.view_formats[0].into())],
}),
primitive: wgpu::PrimitiveState {

View File

@ -58,6 +58,7 @@
module: Id(0, 1, Empty),
entry_point: None,
constants: {},
zero_initialize_workgroup_memory: true,
),
),
),

View File

@ -31,6 +31,7 @@
module: Id(0, 1, Empty),
entry_point: None,
constants: {},
zero_initialize_workgroup_memory: true,
),
),
),

View File

@ -59,6 +59,7 @@
module: Id(0, 1, Empty),
entry_point: None,
constants: {},
zero_initialize_workgroup_memory: true,
),
buffers: [],
),
@ -67,6 +68,7 @@
module: Id(0, 1, Empty),
entry_point: None,
constants: {},
zero_initialize_workgroup_memory: true,
),
targets: [
Some((

View File

@ -135,6 +135,7 @@
module: Id(0, 1, Empty),
entry_point: None,
constants: {},
zero_initialize_workgroup_memory: true,
),
),
),

View File

@ -136,6 +136,7 @@
module: Id(0, 1, Empty),
entry_point: None,
constants: {},
zero_initialize_workgroup_memory: true,
),
),
),

View File

@ -369,7 +369,7 @@ fn copy_via_compute(
layout: Some(&pll),
module: &sm,
entry_point: "copy_texture_to_buffer",
constants: &Default::default(),
compilation_options: Default::default(),
});
{

View File

@ -96,7 +96,7 @@ static BGRA8_UNORM_STORAGE: GpuTestConfiguration = GpuTestConfiguration::new()
label: None,
layout: Some(&pl),
entry_point: "main",
constants: &Default::default(),
compilation_options: Default::default(),
module: &module,
});

View File

@ -90,7 +90,7 @@ async fn bgl_dedupe(ctx: TestingContext) {
layout: Some(&pipeline_layout),
module: &module,
entry_point: "no_resources",
constants: &Default::default(),
compilation_options: Default::default(),
};
let pipeline = ctx.device.create_compute_pipeline(&desc);
@ -219,7 +219,7 @@ fn bgl_dedupe_with_dropped_user_handle(ctx: TestingContext) {
layout: Some(&pipeline_layout),
module: &module,
entry_point: "no_resources",
constants: &Default::default(),
compilation_options: Default::default(),
});
let mut encoder = ctx.device.create_command_encoder(&Default::default());
@ -265,7 +265,7 @@ fn bgl_dedupe_derived(ctx: TestingContext) {
layout: None,
module: &module,
entry_point: "resources",
constants: &Default::default(),
compilation_options: Default::default(),
});
// We create two bind groups, pulling the bind_group_layout from the pipeline each time.
@ -336,7 +336,7 @@ fn separate_programs_have_incompatible_derived_bgls(ctx: TestingContext) {
layout: None,
module: &module,
entry_point: "resources",
constants: &Default::default(),
compilation_options: Default::default(),
};
// Create two pipelines, creating a BG from the second.
let pipeline1 = ctx.device.create_compute_pipeline(&desc);
@ -398,7 +398,7 @@ fn derived_bgls_incompatible_with_regular_bgls(ctx: TestingContext) {
layout: None,
module: &module,
entry_point: "resources",
constants: &Default::default(),
compilation_options: Default::default(),
});
// Create a matching BGL

View File

@ -224,7 +224,7 @@ static MINIMUM_BUFFER_BINDING_SIZE_LAYOUT: GpuTestConfiguration = GpuTestConfigu
layout: Some(&pipeline_layout),
module: &shader_module,
entry_point: "main",
constants: &Default::default(),
compilation_options: Default::default(),
});
});
});
@ -293,7 +293,7 @@ static MINIMUM_BUFFER_BINDING_SIZE_DISPATCH: GpuTestConfiguration = GpuTestConfi
layout: Some(&pipeline_layout),
module: &shader_module,
entry_point: "main",
constants: &Default::default(),
compilation_options: Default::default(),
});
let buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor {

View File

@ -480,7 +480,7 @@ static DEVICE_DESTROY_THEN_MORE: GpuTestConfiguration = GpuTestConfiguration::ne
vertex: wgpu::VertexState {
module: &shader_module,
entry_point: "",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
primitive: wgpu::PrimitiveState::default(),
@ -499,7 +499,7 @@ static DEVICE_DESTROY_THEN_MORE: GpuTestConfiguration = GpuTestConfiguration::ne
layout: None,
module: &shader_module,
entry_point: "",
constants: &Default::default(),
compilation_options: Default::default(),
});
});
@ -736,7 +736,7 @@ fn vs_main() -> @builtin(position) vec4<f32> {
fragment: Some(wgpu::FragmentState {
module: &trivial_shaders_with_some_reversed_bindings,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(wgt::ColorTargetState {
format: wgt::TextureFormat::Bgra8Unorm,
blend: None,
@ -750,7 +750,7 @@ fn vs_main() -> @builtin(position) vec4<f32> {
vertex: wgpu::VertexState {
module: &trivial_shaders_with_some_reversed_bindings,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
primitive: wgt::PrimitiveState::default(),

View File

@ -97,7 +97,7 @@ async fn draw_test_with_reports(
buffers: &[],
module: &shader,
entry_point: "vs_main_builtin",
constants: &Default::default(),
compilation_options: Default::default(),
},
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
@ -105,7 +105,7 @@ async fn draw_test_with_reports(
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(wgpu::ColorTargetState {
format: wgpu::TextureFormat::Rgba8Unorm,
blend: None,

View File

@ -24,13 +24,13 @@ static NV12_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfigurati
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(target_format.into())],
}),
primitive: wgpu::PrimitiveState {

View File

@ -37,7 +37,7 @@ static OCCLUSION_QUERY: GpuTestConfiguration = GpuTestConfiguration::new()
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: None,

View File

@ -69,7 +69,7 @@ static PARTIALLY_BOUNDED_ARRAY: GpuTestConfiguration = GpuTestConfiguration::new
layout: Some(&pipeline_layout),
module: &cs_module,
entry_point: "main",
constants: &Default::default(),
compilation_options: Default::default(),
});
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {

View File

@ -28,7 +28,7 @@ static PIPELINE_DEFAULT_LAYOUT_BAD_MODULE: GpuTestConfiguration = GpuTestConfigu
layout: None,
module: &module,
entry_point: "doesn't exist",
constants: &Default::default(),
compilation_options: Default::default(),
});
pipeline.get_bind_group_layout(0);

View File

@ -103,7 +103,7 @@ async fn partial_update_test(ctx: TestingContext) {
layout: Some(&pipeline_layout),
module: &sm,
entry_point: "main",
constants: &Default::default(),
compilation_options: Default::default(),
});
let mut encoder = ctx

View File

@ -102,13 +102,13 @@ async fn multi_stage_data_binding_test(ctx: TestingContext) {
vertex: wgpu::VertexState {
module: &vs_sm,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &fs_sm,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(wgpu::ColorTargetState {
format: wgpu::TextureFormat::Rgba8Unorm,
blend: None,

View File

@ -52,7 +52,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration =
vertex: VertexState {
module: &module,
entry_point: "double_buffer_vert",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[
VertexBufferLayout {
array_stride: 16,
@ -72,7 +72,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration =
fragment: Some(FragmentState {
module: &module,
entry_point: "double_buffer_frag",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(ColorTargetState {
format: TextureFormat::Rgba8Unorm,
blend: None,
@ -90,7 +90,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration =
vertex: VertexState {
module: &module,
entry_point: "single_buffer_vert",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[VertexBufferLayout {
array_stride: 16,
step_mode: VertexStepMode::Vertex,
@ -103,7 +103,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration =
fragment: Some(FragmentState {
module: &module,
entry_point: "single_buffer_frag",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(ColorTargetState {
format: TextureFormat::Rgba8Unorm,
blend: None,

View File

@ -44,7 +44,7 @@ async fn scissor_test_impl(
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
primitive: wgpu::PrimitiveState::default(),
@ -53,7 +53,7 @@ async fn scissor_test_impl(
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(wgpu::ColorTargetState {
format: wgpu::TextureFormat::Rgba8Unorm,
blend: None,

View File

@ -307,7 +307,7 @@ async fn shader_input_output_test(
layout: Some(&pll),
module: &sm,
entry_point: "cs_main",
constants: &Default::default(),
compilation_options: Default::default(),
});
// -- Initializing data --

View File

@ -87,7 +87,7 @@ static ZERO_INIT_WORKGROUP_MEMORY: GpuTestConfiguration = GpuTestConfiguration::
layout: Some(&pll),
module: &sm,
entry_point: "read",
constants: &Default::default(),
compilation_options: Default::default(),
});
let pipeline_write = ctx
@ -97,7 +97,7 @@ static ZERO_INIT_WORKGROUP_MEMORY: GpuTestConfiguration = GpuTestConfiguration::
layout: None,
module: &sm,
entry_point: "write",
constants: &Default::default(),
compilation_options: Default::default(),
});
// -- Initializing data --

View File

@ -122,7 +122,7 @@ async fn pulling_common(
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: 8,
step_mode: wgpu::VertexStepMode::Vertex,
@ -139,7 +139,7 @@ async fn pulling_common(
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(wgpu::ColorTargetState {
format: wgpu::TextureFormat::Rgba8Unorm,
blend: None,

View File

@ -93,13 +93,13 @@ async fn reinterpret(
vertex: wgpu::VertexState {
module: shader,
entry_point: "vs_main",
constants: &Default::default(),
compilation_options: Default::default(),
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: shader,
entry_point: "fs_main",
constants: &Default::default(),
compilation_options: Default::default(),
targets: &[Some(src_format.into())],
}),
primitive: wgpu::PrimitiveState {

View File

@ -272,7 +272,6 @@ 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),
@ -280,7 +279,7 @@ async fn vertex_index_common(ctx: TestingContext) {
buffers: &[],
module: &shader,
entry_point: "vs_main_builtin",
constants,
compilation_options: Default::default(),
},
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
@ -288,7 +287,7 @@ async fn vertex_index_common(ctx: TestingContext) {
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
constants,
compilation_options: Default::default(),
targets: &[Some(wgpu::ColorTargetState {
format: wgpu::TextureFormat::Rgba8Unorm,
blend: None,

View File

@ -2789,6 +2789,7 @@ impl<A: HalApi> Device<A> {
module: shader_module.raw(),
entry_point: final_entry_point_name.as_ref(),
constants: desc.stage.constants.as_ref(),
zero_initialize_workgroup_memory: desc.stage.zero_initialize_workgroup_memory,
},
};
@ -3204,6 +3205,7 @@ impl<A: HalApi> Device<A> {
module: vertex_shader_module.raw(),
entry_point: &vertex_entry_point_name,
constants: stage_desc.constants.as_ref(),
zero_initialize_workgroup_memory: stage_desc.zero_initialize_workgroup_memory,
}
};
@ -3264,6 +3266,9 @@ impl<A: HalApi> Device<A> {
module: shader_module.raw(),
entry_point: &fragment_entry_point_name,
constants: fragment_state.stage.constants.as_ref(),
zero_initialize_workgroup_memory: fragment_state
.stage
.zero_initialize_workgroup_memory,
})
}
None => None,

View File

@ -241,6 +241,11 @@ pub struct ProgrammableStageDescriptor<'a> {
///
/// The value may represent any of WGSL's concrete scalar types.
pub constants: Cow<'a, naga::back::PipelineConstants>,
/// Whether workgroup scoped memory will be initialized with zero values for this stage.
///
/// This is required by the WebGPU spec, but may have overhead which can be avoided
/// for cross-platform applications
pub zero_initialize_workgroup_memory: bool,
}
/// Number of implicit bind groups derived at pipeline creation.

View File

@ -253,12 +253,14 @@ impl<A: hal::Api> Example<A> {
module: &shader,
entry_point: "vs_main",
constants: &constants,
zero_initialize_workgroup_memory: true,
},
vertex_buffers: &[],
fragment_stage: Some(hal::ProgrammableStage {
module: &shader,
entry_point: "fs_main",
constants: &constants,
zero_initialize_workgroup_memory: true,
}),
primitive: wgt::PrimitiveState {
topology: wgt::PrimitiveTopology::TriangleStrip,

View File

@ -372,6 +372,7 @@ impl<A: hal::Api> Example<A> {
module: &shader_module,
entry_point: "main",
constants: &Default::default(),
zero_initialize_workgroup_memory: true,
},
})
}

View File

@ -226,9 +226,20 @@ impl super::Device {
)
.map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("HLSL: {e:?}")))?;
let needs_temp_options = stage.zero_initialize_workgroup_memory
!= layout.naga_options.zero_initialize_workgroup_memory;
let mut temp_options;
let naga_options = if needs_temp_options {
temp_options = layout.naga_options.clone();
temp_options.zero_initialize_workgroup_memory = stage.zero_initialize_workgroup_memory;
&temp_options
} else {
&layout.naga_options
};
//TODO: reuse the writer
let mut source = String::new();
let mut writer = hlsl::Writer::new(&mut source, &layout.naga_options);
let mut writer = hlsl::Writer::new(&mut source, naga_options);
let reflection_info = {
profiling::scope!("naga::back::hlsl::write");
writer
@ -239,7 +250,7 @@ impl super::Device {
let full_stage = format!(
"{}_{}\0",
naga_stage.to_hlsl_str(),
layout.naga_options.shader_model.to_str()
naga_options.shader_model.to_str()
);
let ep_index = module

View File

@ -255,11 +255,23 @@ impl super::Device {
};
let mut output = String::new();
let needs_temp_options = stage.zero_initialize_workgroup_memory
!= context.layout.naga_options.zero_initialize_workgroup_memory;
let mut temp_options;
let naga_options = if needs_temp_options {
// We use a conditional here, as cloning the naga_options could be expensive
// That is, we want to avoid doing that unless we cannot avoid it
temp_options = context.layout.naga_options.clone();
temp_options.zero_initialize_workgroup_memory = stage.zero_initialize_workgroup_memory;
&temp_options
} else {
&context.layout.naga_options
};
let mut writer = glsl::Writer::new(
&mut output,
&module,
&info,
&context.layout.naga_options,
naga_options,
&pipeline_options,
policies,
)
@ -305,6 +317,7 @@ impl super::Device {
naga_stage: naga_stage.to_owned(),
shader_id: stage.module.id,
entry_point: stage.entry_point.to_owned(),
zero_initialize_workgroup_memory: stage.zero_initialize_workgroup_memory,
});
}
let mut guard = self

View File

@ -602,6 +602,7 @@ struct ProgramStage {
naga_stage: naga::ShaderStage,
shader_id: ShaderId,
entry_point: String,
zero_initialize_workgroup_memory: bool,
}
#[derive(PartialEq, Eq, Hash)]

View File

@ -1459,6 +1459,11 @@ pub struct ProgrammableStage<'a, A: Api> {
pub entry_point: &'a str,
/// Pipeline constants
pub constants: &'a naga::back::PipelineConstants,
/// Whether workgroup scoped memory will be initialized with zero values for this stage.
///
/// This is required by the WebGPU spec, but may have overhead which can be avoided
/// for cross-platform applications
pub zero_initialize_workgroup_memory: bool,
}
// Rust gets confused about the impl requirements for `A`
@ -1468,6 +1473,7 @@ impl<A: Api> Clone for ProgrammableStage<'_, A> {
module: self.module,
entry_point: self.entry_point,
constants: self.constants,
zero_initialize_workgroup_memory: self.zero_initialize_workgroup_memory,
}
}
}

View File

@ -112,7 +112,7 @@ impl super::Device {
// TODO: support bounds checks on binding arrays
binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
},
zero_initialize_workgroup_memory: true,
zero_initialize_workgroup_memory: stage.zero_initialize_workgroup_memory,
};
let pipeline_options = naga::back::msl::PipelineOptions {

View File

@ -2,6 +2,7 @@ use super::conv;
use arrayvec::ArrayVec;
use ash::{extensions::khr, vk};
use naga::back::spv::ZeroInitializeWorkgroupMemoryMode;
use parking_lot::Mutex;
use std::{
@ -737,7 +738,8 @@ impl super::Device {
};
let needs_temp_options = !runtime_checks
|| !binding_map.is_empty()
|| naga_shader.debug_source.is_some();
|| naga_shader.debug_source.is_some()
|| !stage.zero_initialize_workgroup_memory;
let mut temp_options;
let options = if needs_temp_options {
temp_options = self.naga_options.clone();
@ -760,6 +762,10 @@ impl super::Device {
file_name: debug.file_name.as_ref().as_ref(),
})
}
if !stage.zero_initialize_workgroup_memory {
temp_options.zero_initialize_workgroup_memory =
ZeroInitializeWorkgroupMemoryMode::None;
}
&temp_options
} else {

View File

@ -1143,7 +1143,11 @@ 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),
constants: Borrowed(desc.vertex.compilation_options.constants),
zero_initialize_workgroup_memory: desc
.vertex
.compilation_options
.zero_initialize_workgroup_memory,
},
buffers: Borrowed(&vertex_buffers),
},
@ -1154,7 +1158,10 @@ impl crate::Context for ContextWgpuCore {
stage: pipe::ProgrammableStageDescriptor {
module: frag.module.id.into(),
entry_point: Some(Borrowed(frag.entry_point)),
constants: Borrowed(frag.constants),
constants: Borrowed(frag.compilation_options.constants),
zero_initialize_workgroup_memory: frag
.compilation_options
.zero_initialize_workgroup_memory,
},
targets: Borrowed(frag.targets),
}),
@ -1203,7 +1210,10 @@ impl crate::Context for ContextWgpuCore {
stage: pipe::ProgrammableStageDescriptor {
module: desc.module.id.into(),
entry_point: Some(Borrowed(desc.entry_point)),
constants: Borrowed(desc.constants),
constants: Borrowed(desc.compilation_options.constants),
zero_initialize_workgroup_memory: desc
.compilation_options
.zero_initialize_workgroup_memory,
},
};

View File

@ -1647,14 +1647,10 @@ 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.
/// Advanced options for when this pipeline is compiled
///
/// 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<String, f64>,
/// This implements `Default`, and for most users can be set to `Default::default()`
pub compilation_options: PipelineCompilationOptions<'a>,
/// The format of any vertex buffers used with this pipeline.
pub buffers: &'a [VertexBufferLayout<'a>],
}
@ -1674,14 +1670,10 @@ 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.
/// Advanced options for when this pipeline is compiled
///
/// 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<String, f64>,
/// This implements `Default`, and for most users can be set to `Default::default()`
pub compilation_options: PipelineCompilationOptions<'a>,
/// The color state of the render targets.
pub targets: &'a [Option<ColorTargetState>],
}
@ -1754,6 +1746,41 @@ pub struct ComputePassDescriptor<'a> {
#[cfg(send_sync)]
static_assertions::assert_impl_all!(ComputePassDescriptor<'_>: Send, Sync);
#[derive(Clone, Debug)]
/// Advanced options for use when a pipeline is compiled
///
/// This implements `Default`, and for most users can be set to `Default::default()`
pub struct PipelineCompilationOptions<'a> {
/// 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<String, f64>,
/// Whether workgroup scoped memory will be initialized with zero values for this stage.
///
/// This is required by the WebGPU spec, but may have overhead which can be avoided
/// for cross-platform applications
pub zero_initialize_workgroup_memory: bool,
}
impl<'a> Default for PipelineCompilationOptions<'a> {
fn default() -> Self {
// HashMap doesn't have a const constructor, due to the use of RandomState
// This does introduce some synchronisation costs, but these should be minor,
// and might be cheaper than the alternative of getting new random state
static DEFAULT_CONSTANTS: std::sync::OnceLock<HashMap<String, f64>> =
std::sync::OnceLock::new();
let constants = DEFAULT_CONSTANTS.get_or_init(Default::default);
Self {
constants,
zero_initialize_workgroup_memory: true,
}
}
}
/// Describes a compute pipeline.
///
/// For use with [`Device::create_compute_pipeline`].
@ -1771,14 +1798,10 @@ 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.
/// Advanced options for when this pipeline is compiled
///
/// 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<String, f64>,
/// This implements `Default`, and for most users can be set to `Default::default()`
pub compilation_options: PipelineCompilationOptions<'a>,
}
#[cfg(send_sync)]
static_assertions::assert_impl_all!(ComputePipelineDescriptor<'_>: Send, Sync);