Expose Pipeline Compilation Zero Initialize Workgroup Memory Option (#16301)

# Objective

- wgpu 0.20 made workgroup vars stop being zero-init by default. this
broke some applications (cough foresight cough) and now we workaround
it. wgpu exposes a compilation option that zero initializes workgroup
memory by default, but bevy does not expose it.

## Solution

- expose the compilation option wgpu gives us

## Testing

- ran examples: 3d_scene, compute_shader_game_of_life, gpu_readback,
lines, specialized_mesh_pipeline. they all work
- confirmed fix for our own problems

---

</details>

## Migration Guide

- add `zero_initialize_workgroup_memory: false,` to
`ComputePipelineDescriptor` or `RenderPipelineDescriptor` structs to
preserve 0.14 functionality, add `zero_initialize_workgroup_memory:
true,` to restore bevy 0.13 functionality.
This commit is contained in:
atlv 2024-11-08 16:42:37 -05:00 committed by GitHub
parent 0ac495f7f4
commit c29e67153b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
42 changed files with 79 additions and 6 deletions

View file

@ -89,6 +89,7 @@ impl SpecializedComputePipeline for AutoExposurePipeline {
AutoExposurePass::Average => "compute_average".into(),
},
push_constant_ranges: vec![],
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -98,6 +98,7 @@ impl SpecializedRenderPipeline for BlitPipeline {
..Default::default()
},
push_constant_ranges: Vec::new(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -127,6 +127,7 @@ impl SpecializedRenderPipeline for BloomDownsamplingPipeline {
depth_stencil: None,
multisample: MultisampleState::default(),
push_constant_ranges: Vec::new(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -124,6 +124,7 @@ impl SpecializedRenderPipeline for BloomUpsamplingPipeline {
depth_stencil: None,
multisample: MultisampleState::default(),
push_constant_ranges: Vec::new(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -233,6 +233,7 @@ impl SpecializedRenderPipeline for CasPipeline {
depth_stencil: None,
multisample: MultisampleState::default(),
push_constant_ranges: Vec::new(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -160,6 +160,7 @@ impl FromWorld for CopyDeferredLightingIdPipeline {
}),
multisample: MultisampleState::default(),
push_constant_ranges: vec![],
zero_initialize_workgroup_memory: false,
});
Self {

View file

@ -806,6 +806,7 @@ impl SpecializedRenderPipeline for DepthOfFieldPipeline {
},
targets,
}),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -196,6 +196,7 @@ impl SpecializedRenderPipeline for FxaaPipeline {
depth_stencil: None,
multisample: MultisampleState::default(),
push_constant_ranges: Vec::new(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -141,6 +141,7 @@ impl SpecializedRenderPipeline for MotionBlurPipeline {
depth_stencil: None,
multisample: MultisampleState::default(),
push_constant_ranges: vec![],
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -208,6 +208,7 @@ fn specialize_oit_resolve_pipeline(
depth_stencil: None,
multisample: MultisampleState::default(),
push_constant_ranges: vec![],
zero_initialize_workgroup_memory: false,
}
}

View file

@ -344,6 +344,7 @@ impl SpecializedRenderPipeline for PostProcessingPipeline {
depth_stencil: None,
multisample: default(),
push_constant_ranges: vec![],
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -233,6 +233,7 @@ impl SpecializedRenderPipeline for SkyboxPipeline {
write_mask: ColorWrites::ALL,
})],
}),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -105,6 +105,7 @@ impl SpecializedRenderPipeline for SkyboxPrepassPipeline {
entry_point: "fragment".into(),
targets: prepass_target_descriptors(key.normal_prepass, true, false),
}),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -512,6 +512,7 @@ impl SpecializedRenderPipeline for SmaaEdgeDetectionPipeline {
bias: default(),
}),
multisample: MultisampleState::default(),
zero_initialize_workgroup_memory: false,
}
}
}
@ -571,6 +572,7 @@ impl SpecializedRenderPipeline for SmaaBlendingWeightCalculationPipeline {
bias: default(),
}),
multisample: MultisampleState::default(),
zero_initialize_workgroup_memory: false,
}
}
}
@ -607,6 +609,7 @@ impl SpecializedRenderPipeline for SmaaNeighborhoodBlendingPipeline {
primitive: PrimitiveState::default(),
depth_stencil: None,
multisample: MultisampleState::default(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -355,6 +355,7 @@ impl SpecializedRenderPipeline for TaaPipeline {
depth_stencil: None,
multisample: MultisampleState::default(),
push_constant_ranges: Vec::new(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -307,6 +307,7 @@ impl SpecializedRenderPipeline for TonemappingPipeline {
depth_stencil: None,
multisample: MultisampleState::default(),
push_constant_ranges: Vec::new(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -161,6 +161,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline {
},
label: Some("LineGizmo Pipeline 2D".into()),
push_constant_ranges: vec![],
zero_initialize_workgroup_memory: false,
}
}
}
@ -261,6 +262,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline {
},
label: Some("LineJointGizmo Pipeline 2D".into()),
push_constant_ranges: vec![],
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -158,6 +158,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline {
},
label: Some("LineGizmo Pipeline".into()),
push_constant_ranges: vec![],
zero_initialize_workgroup_memory: false,
}
}
}
@ -256,6 +257,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline {
},
label: Some("LineJointGizmo Pipeline".into()),
push_constant_ranges: vec![],
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -390,6 +390,7 @@ impl SpecializedRenderPipeline for DeferredLightingLayout {
}),
multisample: MultisampleState::default(),
push_constant_ranges: vec![],
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -200,6 +200,7 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass<M: Material>(
entry_point: material_fragment.entry_point,
targets: material_fragment.targets,
}),
zero_initialize_workgroup_memory: false,
};
let material_id = instance_manager.get_material_id(material_id.untyped());
@ -353,6 +354,7 @@ pub fn prepare_material_meshlet_meshes_prepass<M: Material>(
entry_point,
targets: material_fragment.targets,
}),
zero_initialize_workgroup_memory: false,
};
let material_id = instance_manager.get_material_id(material_id.untyped());

View file

@ -76,6 +76,7 @@ impl FromWorld for MeshletPipelines {
shader: MESHLET_FILL_CLUSTER_BUFFERS_SHADER_HANDLE,
shader_defs: vec!["MESHLET_FILL_CLUSTER_BUFFERS_PASS".into()],
entry_point: "fill_cluster_buffers".into(),
zero_initialize_workgroup_memory: false,
},
),
@ -92,6 +93,7 @@ impl FromWorld for MeshletPipelines {
"MESHLET_FIRST_CULLING_PASS".into(),
],
entry_point: "cull_clusters".into(),
zero_initialize_workgroup_memory: false,
}),
cull_second: pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
@ -107,6 +109,7 @@ impl FromWorld for MeshletPipelines {
"MESHLET_SECOND_CULLING_PASS".into(),
],
entry_point: "cull_clusters".into(),
zero_initialize_workgroup_memory: false,
}),
downsample_depth_first: pipeline_cache.queue_compute_pipeline(
@ -120,6 +123,7 @@ impl FromWorld for MeshletPipelines {
shader: MESHLET_DOWNSAMPLE_DEPTH_SHADER_HANDLE,
shader_defs: vec!["MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT".into()],
entry_point: "downsample_depth_first".into(),
zero_initialize_workgroup_memory: false,
},
),
@ -134,6 +138,7 @@ impl FromWorld for MeshletPipelines {
shader: MESHLET_DOWNSAMPLE_DEPTH_SHADER_HANDLE,
shader_defs: vec!["MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT".into()],
entry_point: "downsample_depth_second".into(),
zero_initialize_workgroup_memory: false,
},
),
@ -148,6 +153,7 @@ impl FromWorld for MeshletPipelines {
shader: MESHLET_DOWNSAMPLE_DEPTH_SHADER_HANDLE,
shader_defs: vec![],
entry_point: "downsample_depth_first".into(),
zero_initialize_workgroup_memory: false,
},
),
@ -162,6 +168,7 @@ impl FromWorld for MeshletPipelines {
shader: MESHLET_DOWNSAMPLE_DEPTH_SHADER_HANDLE,
shader_defs: vec![],
entry_point: "downsample_depth_second".into(),
zero_initialize_workgroup_memory: false,
},
),
@ -182,6 +189,7 @@ impl FromWorld for MeshletPipelines {
.into(),
],
entry_point: "rasterize_cluster".into(),
zero_initialize_workgroup_memory: false,
},
),
@ -203,6 +211,7 @@ impl FromWorld for MeshletPipelines {
.into(),
],
entry_point: "rasterize_cluster".into(),
zero_initialize_workgroup_memory: false,
},
),
@ -226,6 +235,7 @@ impl FromWorld for MeshletPipelines {
.into(),
],
entry_point: "rasterize_cluster".into(),
zero_initialize_workgroup_memory: false,
}),
visibility_buffer_hardware_raster: pipeline_cache.queue_render_pipeline(
@ -269,6 +279,7 @@ impl FromWorld for MeshletPipelines {
write_mask: ColorWrites::empty(),
})],
}),
zero_initialize_workgroup_memory: false,
},
),
@ -309,6 +320,7 @@ impl FromWorld for MeshletPipelines {
write_mask: ColorWrites::empty(),
})],
}),
zero_initialize_workgroup_memory: false,
},
),
@ -356,6 +368,7 @@ impl FromWorld for MeshletPipelines {
write_mask: ColorWrites::empty(),
})],
}),
zero_initialize_workgroup_memory: false,
}),
resolve_depth: pipeline_cache.queue_render_pipeline(RenderPipelineDescriptor {
@ -381,6 +394,7 @@ impl FromWorld for MeshletPipelines {
entry_point: "resolve_depth".into(),
targets: vec![],
}),
zero_initialize_workgroup_memory: false,
}),
resolve_depth_shadow_view: pipeline_cache.queue_render_pipeline(
@ -407,6 +421,7 @@ impl FromWorld for MeshletPipelines {
entry_point: "resolve_depth".into(),
targets: vec![],
}),
zero_initialize_workgroup_memory: false,
},
),
@ -434,6 +449,7 @@ impl FromWorld for MeshletPipelines {
entry_point: "resolve_material_depth".into(),
targets: vec![],
}),
zero_initialize_workgroup_memory: false,
},
),
@ -448,6 +464,7 @@ impl FromWorld for MeshletPipelines {
shader: MESHLET_REMAP_1D_TO_2D_DISPATCH_SHADER_HANDLE,
shader_defs: vec![],
entry_point: "remap_dispatch".into(),
zero_initialize_workgroup_memory: false,
})
}),
}

View file

@ -571,6 +571,7 @@ where
},
push_constant_ranges: vec![],
label: Some("prepass_pipeline".into()),
zero_initialize_workgroup_memory: false,
};
// This is a bit risky because it's possible to change something that would

View file

@ -290,6 +290,7 @@ impl SpecializedComputePipeline for PreprocessPipeline {
shader: MESH_PREPROCESS_SHADER_HANDLE,
shader_defs,
entry_point: "main".into(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -2020,6 +2020,7 @@ impl SpecializedMeshPipeline for MeshPipeline {
alpha_to_coverage_enabled,
},
label: Some(label),
zero_initialize_workgroup_memory: false,
})
}
}

View file

@ -448,6 +448,7 @@ impl FromWorld for SsaoPipelines {
shader: PREPROCESS_DEPTH_SHADER_HANDLE,
shader_defs: Vec::new(),
entry_point: "preprocess_depth".into(),
zero_initialize_workgroup_memory: false,
});
let spatial_denoise_pipeline =
@ -461,6 +462,7 @@ impl FromWorld for SsaoPipelines {
shader: SPATIAL_DENOISE_SHADER_HANDLE,
shader_defs: Vec::new(),
entry_point: "spatial_denoise".into(),
zero_initialize_workgroup_memory: false,
});
Self {
@ -513,6 +515,7 @@ impl SpecializedComputePipeline for SsaoPipelines {
shader: SSAO_SHADER_HANDLE,
shader_defs,
entry_point: "ssao".into(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -560,6 +560,7 @@ impl SpecializedRenderPipeline for ScreenSpaceReflectionsPipeline {
primitive: default(),
depth_stencil: None,
multisample: default(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -600,6 +600,7 @@ impl SpecializedRenderPipeline for VolumetricFogPipeline {
write_mask: ColorWrites::ALL,
})],
}),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -108,6 +108,9 @@ pub struct RenderPipelineDescriptor {
pub multisample: MultisampleState,
/// The compiled fragment stage, its entry point, and the color targets.
pub fragment: Option<FragmentState>,
/// Whether to zero-initialize workgroup memory by default. If you're not sure, set this to true.
/// If this is false, reading from workgroup variables before writing to them will result in garbage values.
pub zero_initialize_workgroup_memory: bool,
}
#[derive(Clone, Debug, Eq, PartialEq)]
@ -147,4 +150,7 @@ pub struct ComputePipelineDescriptor {
/// The name of the entry point in the compiled shader. There must be a
/// function with this name in the shader.
pub entry_point: Cow<'static, str>,
/// Whether to zero-initialize workgroup memory by default. If you're not sure, set this to true.
/// If this is false, reading from workgroup variables before writing to them will result in garbage values.
pub zero_initialize_workgroup_memory: bool,
}

View file

@ -669,6 +669,7 @@ impl PipelineCache {
let device = self.device.clone();
let shader_cache = self.shader_cache.clone();
let layout_cache = self.layout_cache.clone();
create_pipeline_task(
async move {
let mut shader_cache = shader_cache.lock().unwrap();
@ -731,10 +732,10 @@ impl PipelineCache {
)
});
// TODO: Expose this somehow
// TODO: Expose the rest of this somehow
let compilation_options = PipelineCompilationOptions {
constants: &std::collections::HashMap::new(),
zero_initialize_workgroup_memory: false,
constants: &default(),
zero_initialize_workgroup_memory: descriptor.zero_initialize_workgroup_memory,
};
let descriptor = RawRenderPipelineDescriptor {
@ -779,6 +780,7 @@ impl PipelineCache {
let device = self.device.clone();
let shader_cache = self.shader_cache.clone();
let layout_cache = self.layout_cache.clone();
create_pipeline_task(
async move {
let mut shader_cache = shader_cache.lock().unwrap();
@ -812,10 +814,11 @@ impl PipelineCache {
layout: layout.as_ref().map(|layout| -> &PipelineLayout { layout }),
module: &compute_module,
entry_point: Some(&descriptor.entry_point),
// TODO: Expose this somehow
// TODO: Expose the rest of this somehow
compilation_options: PipelineCompilationOptions {
constants: &std::collections::HashMap::new(),
zero_initialize_workgroup_memory: false,
constants: &default(),
zero_initialize_workgroup_memory: descriptor
.zero_initialize_workgroup_memory,
},
cache: None,
};

View file

@ -496,6 +496,7 @@ impl SpecializedRenderPipeline for ScreenshotToScreenPipeline {
})],
}),
push_constant_ranges: Vec::new(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -674,6 +674,7 @@ impl SpecializedMeshPipeline for Mesh2dPipeline {
alpha_to_coverage_enabled: false,
},
label: Some(label.into()),
zero_initialize_workgroup_memory: false,
})
}
}

View file

@ -323,6 +323,7 @@ impl SpecializedRenderPipeline for SpritePipeline {
},
label: Some("sprite_pipeline".into()),
push_constant_ranges: Vec::new(),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -206,6 +206,7 @@ impl SpecializedRenderPipeline for BoxShadowPipeline {
alpha_to_coverage_enabled: false,
},
label: Some("box_shadow_pipeline".into()),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -121,6 +121,7 @@ impl SpecializedRenderPipeline for UiPipeline {
alpha_to_coverage_enabled: false,
},
label: Some("ui_pipeline".into()),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -199,6 +199,7 @@ where
alpha_to_coverage_enabled: false,
},
label: Some("ui_material_pipeline".into()),
zero_initialize_workgroup_memory: false,
};
if let Some(vertex_shader) = &self.vertex_shader {
descriptor.vertex.shader = vertex_shader.clone();

View file

@ -219,6 +219,7 @@ impl SpecializedRenderPipeline for UiTextureSlicePipeline {
alpha_to_coverage_enabled: false,
},
label: Some("ui_texture_slice_pipeline".into()),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -220,6 +220,7 @@ impl SpecializedRenderPipeline for ColoredMesh2dPipeline {
alpha_to_coverage_enabled: false,
},
label: Some("colored_mesh2d_pipeline".into()),
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -179,6 +179,7 @@ impl FromWorld for GameOfLifePipeline {
shader: shader.clone(),
shader_defs: vec![],
entry_point: Cow::from("init"),
zero_initialize_workgroup_memory: false,
});
let update_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
label: None,
@ -187,6 +188,7 @@ impl FromWorld for GameOfLifePipeline {
shader,
shader_defs: vec![],
entry_point: Cow::from("update"),
zero_initialize_workgroup_memory: false,
});
GameOfLifePipeline {

View file

@ -343,6 +343,7 @@ impl SpecializedRenderPipeline for CustomPhasePipeline {
mask: !0,
alpha_to_coverage_enabled: false,
},
zero_initialize_workgroup_memory: false,
}
}
}

View file

@ -287,6 +287,7 @@ impl FromWorld for PostProcessPipeline {
depth_stencil: None,
multisample: MultisampleState::default(),
push_constant_ranges: vec![],
zero_initialize_workgroup_memory: false,
});
Self {

View file

@ -180,6 +180,7 @@ impl FromWorld for ComputePipeline {
shader: shader.clone(),
shader_defs: Vec::new(),
entry_point: "main".into(),
zero_initialize_workgroup_memory: false,
});
ComputePipeline { layout, pipeline }
}

View file

@ -263,6 +263,7 @@ impl SpecializedMeshPipeline for CustomMeshPipeline {
count: mesh_key.msaa_samples(),
..MultisampleState::default()
},
zero_initialize_workgroup_memory: false,
})
}
}