Skip to content
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
21e3bfd
Unsure but these were prior changes
inner-daemons Jun 19, 2025
d9e089d
Merge branch 'dxil-passthrough' of https://github.com/supamaggie70inc…
inner-daemons Jun 19, 2025
818b1fe
Fixed feature thing
inner-daemons Jun 19, 2025
873a0ee
Mostly finished dxil passthrough
inner-daemons Jun 19, 2025
da84fed
Attempted to add HLSL passthrough
inner-daemons Jun 19, 2025
5680c9e
Tried to fix compiles
inner-daemons Jun 19, 2025
05b8cda
Tried to fix more clippy lints
inner-daemons Jun 19, 2025
4c28f2a
Added initial feature, going back to fix issues with DXIL rn
inner-daemons Jun 20, 2025
d050a20
Tried to fix some potential issues
inner-daemons Jun 20, 2025
5c1c8c8
Merge branch 'dxil-passthrough' into precompiled-shaders
inner-daemons Jun 20, 2025
3ca8ce4
Initial work
inner-daemons Jun 20, 2025
f7ffe36
Tried to fix metal compiles
inner-daemons Jun 20, 2025
5006d54
Fixed warning
inner-daemons Jun 20, 2025
d69e277
Added my ideas for changes
inner-daemons Jun 20, 2025
3f9b7b8
Tried to expose precompiled shaders to metal
inner-daemons Jun 20, 2025
0f17512
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jun 25, 2025
34d076a
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jun 27, 2025
6d49154
How do these things even happen?
inner-daemons Jun 27, 2025
4b19ca3
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 1, 2025
e7cc939
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 3, 2025
18dffd5
More work, adapted with some of Cw's advice
inner-daemons Jul 5, 2025
1eb4492
Tried to fix some compile errors. Now build!!!
inner-daemons Jul 5, 2025
8f1b59c
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 5, 2025
c4a3160
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 9, 2025
fc7152f
Small change
inner-daemons Jul 9, 2025
1a1dfe5
Update wgpu-types/src/features.rs
inner-daemons Jul 9, 2025
fa16188
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 9, 2025
4c8aa72
Deleted the precompiled shader spec
inner-daemons Jul 9, 2025
4e97df8
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 9, 2025
672738a
Pushing now to get hal errors on other backends
inner-daemons Jul 9, 2025
dfbeacc
Made some slight fixes, CI will now report more hal errors
inner-daemons Jul 9, 2025
5d0ed0b
Tried to write passthrough for webgpu backend
inner-daemons Jul 9, 2025
66c6000
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 9, 2025
98fcff9
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 9, 2025
b105dc0
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 10, 2025
ca381ca
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 10, 2025
681857e
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 11, 2025
b542ba5
Various changes as requested from review
inner-daemons Jul 11, 2025
ff61dde
Fixed issues with trace
inner-daemons Jul 11, 2025
1e454b2
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 11, 2025
3ae8b38
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 11, 2025
7f4e64f
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 16, 2025
0b02fda
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 23, 2025
8b48cc5
Fixed accidental merge change
inner-daemons Jul 23, 2025
9c84ef0
Merge branch 'trunk' into precompiled-shaders
inner-daemons Jul 24, 2025
f864fcd
Merge branch 'trunk' into precompiled-shaders
inner-daemons Aug 9, 2025
cfb676f
Tried to fix the tests and whatnot
inner-daemons Aug 9, 2025
ab1e89e
More small tweaks
inner-daemons Aug 9, 2025
7dde16f
A few more tweaks
inner-daemons Aug 9, 2025
8a9cbbd
Tried to fix spirv issue (I'm blind to vulkan compile rn)
inner-daemons Aug 9, 2025
d568b12
Ok thats embarassing
inner-daemons Aug 9, 2025
b584304
Final pass (single word changed in doc comment)
inner-daemons Aug 9, 2025
ac32244
Merge branch 'trunk' into precompiled-shaders
inner-daemons Aug 14, 2025
44a9320
Updated changelog
inner-daemons Aug 14, 2025
9981411
Apply suggestions from code review
inner-daemons Aug 14, 2025
52f90e6
Addressed more comments
inner-daemons Aug 14, 2025
ed15a65
Removed references to optional reflection information
inner-daemons Aug 14, 2025
9e89121
Merge branch 'trunk' into precompiled-shaders
inner-daemons Aug 17, 2025
ac7223f
Merge branch 'trunk' into precompiled-shaders
inner-daemons Aug 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ We have merged the acceleration structure feature into the `RayQuery` feature. T

By @Vecvec in [#7913](https://github.com/gfx-rs/wgpu/pull/7913).

### General
- Added `Features::EXPERIMENTAL_PRECOMPILED_SHADERS`, replacing existing passthrough types with a unified `CreateShaderModuleDescriptorPassthrough` which allows passing multiple shader codes for different backends. By @SupaMaggie70Incorporated in [#7834](https://github.com/gfx-rs/wgpu/pull/7834)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a major changes with a small things showing off the diff and the new API

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a new changelog entry, let me know if you want more changes to it


### Changes

#### General
Expand Down
15 changes: 6 additions & 9 deletions deno_webgpu/webidl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,10 +419,6 @@ pub enum GPUFeatureName {
VertexWritableStorage,
#[webidl(rename = "clear-texture")]
ClearTexture,
#[webidl(rename = "msl-shader-passthrough")]
MslShaderPassthrough,
#[webidl(rename = "spirv-shader-passthrough")]
SpirvShaderPassthrough,
#[webidl(rename = "multiview")]
Multiview,
#[webidl(rename = "vertex-attribute-64-bit")]
Expand All @@ -435,6 +431,8 @@ pub enum GPUFeatureName {
ShaderPrimitiveIndex,
#[webidl(rename = "shader-early-depth-test")]
ShaderEarlyDepthTest,
#[webidl(rename = "passthrough-shaders")]
PassthroughShaders,
}

pub fn feature_names_to_features(names: Vec<GPUFeatureName>) -> wgpu_types::Features {
Expand Down Expand Up @@ -482,14 +480,13 @@ pub fn feature_names_to_features(names: Vec<GPUFeatureName>) -> wgpu_types::Feat
GPUFeatureName::ConservativeRasterization => Features::CONSERVATIVE_RASTERIZATION,
GPUFeatureName::VertexWritableStorage => Features::VERTEX_WRITABLE_STORAGE,
GPUFeatureName::ClearTexture => Features::CLEAR_TEXTURE,
GPUFeatureName::MslShaderPassthrough => Features::MSL_SHADER_PASSTHROUGH,
GPUFeatureName::SpirvShaderPassthrough => Features::SPIRV_SHADER_PASSTHROUGH,
GPUFeatureName::Multiview => Features::MULTIVIEW,
GPUFeatureName::VertexAttribute64Bit => Features::VERTEX_ATTRIBUTE_64BIT,
GPUFeatureName::ShaderF64 => Features::SHADER_F64,
GPUFeatureName::ShaderI16 => Features::SHADER_I16,
GPUFeatureName::ShaderPrimitiveIndex => Features::SHADER_PRIMITIVE_INDEX,
GPUFeatureName::ShaderEarlyDepthTest => Features::SHADER_EARLY_DEPTH_TEST,
GPUFeatureName::PassthroughShaders => Features::EXPERIMENTAL_PASSTHROUGH_SHADERS,
};
features.set(feature, true);
}
Expand Down Expand Up @@ -626,9 +623,6 @@ pub fn features_to_feature_names(features: wgpu_types::Features) -> HashSet<GPUF
if features.contains(wgpu_types::Features::CLEAR_TEXTURE) {
return_features.insert(ClearTexture);
}
if features.contains(wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH) {
return_features.insert(SpirvShaderPassthrough);
}
if features.contains(wgpu_types::Features::MULTIVIEW) {
return_features.insert(Multiview);
}
Expand All @@ -648,6 +642,9 @@ pub fn features_to_feature_names(features: wgpu_types::Features) -> HashSet<GPUF
if features.contains(wgpu_types::Features::SHADER_EARLY_DEPTH_TEST) {
return_features.insert(ShaderEarlyDepthTest);
}
if features.contains(wgpu_types::Features::EXPERIMENTAL_PASSTHROUGH_SHADERS) {
return_features.insert(PassthroughShaders);
}

return_features
}
14 changes: 7 additions & 7 deletions examples/features/src/mesh_shader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ fn compile_glsl(
let output = cmd.wait_with_output().expect("Error waiting for glslc");
assert!(output.status.success());
unsafe {
device.create_shader_module_passthrough(wgpu::ShaderModuleDescriptorPassthrough::SpirV(
wgpu::ShaderModuleDescriptorSpirV {
label: None,
source: wgpu::util::make_spirv_raw(&output.stdout),
},
))
device.create_shader_module_passthrough(wgpu::ShaderModuleDescriptorPassthrough {
entry_point: "main".into(),
label: None,
spirv: Some(wgpu::util::make_spirv_raw(&output.stdout)),
..Default::default()
})
}
}

Expand Down Expand Up @@ -119,7 +119,7 @@ impl crate::framework::Example for Example {
Default::default()
}
fn required_features() -> wgpu::Features {
wgpu::Features::EXPERIMENTAL_MESH_SHADER | wgpu::Features::SPIRV_SHADER_PASSTHROUGH
wgpu::Features::EXPERIMENTAL_MESH_SHADER | wgpu::Features::EXPERIMENTAL_PASSTHROUGH_SHADERS
}
fn required_limits() -> wgpu::Limits {
wgpu::Limits::defaults().using_recommended_minimum_mesh_shader_values()
Expand Down
84 changes: 84 additions & 0 deletions player/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,90 @@ impl GlobalPlay for wgc::global::Global {
println!("shader compilation error:\n---{code}\n---\n{e}");
}
}
Action::CreateShaderModulePassthrough {
id,
data,
entry_point,
label,
num_workgroups,
reflection,
runtime_checks,
} => {
let spirv = data.iter().find_map(|a| {
if a.ends_with(".spv") {
let data = fs::read(dir.join(a)).unwrap();
assert!(data.len() % 4 == 0);
// Mom: we have bytemuck at home
let vec: Vec<u32> = data
.chunks_exact(4)
.map(|chunk| u32::from_ne_bytes(chunk.try_into().unwrap()))
.collect();
Some(Cow::Owned(vec))
} else {
None
}
});
let dxil = data.iter().find_map(|a| {
if a.ends_with(".dxil") {
let vec = std::fs::read(dir.join(a)).unwrap();
Some(Cow::Owned(vec))
} else {
None
}
});
let hlsl = data.iter().find_map(|a| {
if a.ends_with(".hlsl") {
let code = fs::read_to_string(dir.join(a)).unwrap();
Some(Cow::Owned(code))
} else {
None
}
});
let msl = data.iter().find_map(|a| {
if a.ends_with(".msl") {
let code = fs::read_to_string(dir.join(a)).unwrap();
Some(Cow::Owned(code))
} else {
None
}
});
let glsl = data.iter().find_map(|a| {
if a.ends_with(".glsl") {
let code = fs::read_to_string(dir.join(a)).unwrap();
Some(Cow::Owned(code))
} else {
None
}
});
let wgsl = data.iter().find_map(|a| {
if a.ends_with(".wgsl") {
let code = fs::read_to_string(dir.join(a)).unwrap();
Some(Cow::Owned(code))
} else {
None
}
});
let desc = wgt::CreateShaderModuleDescriptorPassthrough {
entry_point,
label,
num_workgroups,
reflection,
runtime_checks,

spirv,
dxil,
hlsl,
msl,
glsl,
wgsl,
};
let (_, error) = unsafe {
self.device_create_shader_module_passthrough(device, &desc, Some(id))
};
if let Some(e) = error {
println!("shader compilation error: {e}");
}
}
Action::DestroyShaderModule(id) => {
self.shader_module_drop(id);
}
Expand Down
14 changes: 7 additions & 7 deletions tests/tests/wgpu-gpu/mesh_shader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ fn compile_glsl(
let output = cmd.wait_with_output().expect("Error waiting for glslc");
assert!(output.status.success());
unsafe {
device.create_shader_module_passthrough(wgpu::ShaderModuleDescriptorPassthrough::SpirV(
wgpu::ShaderModuleDescriptorSpirV {
label: None,
source: wgpu::util::make_spirv_raw(&output.stdout),
},
))
device.create_shader_module_passthrough(wgpu::ShaderModuleDescriptorPassthrough {
entry_point: "main".into(),
label: None,
spirv: Some(wgpu::util::make_spirv_raw(&output.stdout)),
..Default::default()
})
}
}

Expand Down Expand Up @@ -267,7 +267,7 @@ fn default_gpu_test_config(draw_type: DrawType) -> GpuTestConfiguration {
.test_features_limits()
.features(
wgpu::Features::EXPERIMENTAL_MESH_SHADER
| wgpu::Features::SPIRV_SHADER_PASSTHROUGH
| wgpu::Features::EXPERIMENTAL_PASSTHROUGH_SHADERS
| match draw_type {
DrawType::Standard | DrawType::Indirect => wgpu::Features::empty(),
DrawType::MultiIndirect => wgpu::Features::MULTI_DRAW_INDIRECT,
Expand Down
52 changes: 22 additions & 30 deletions wgpu-core/src/device/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,36 +1094,28 @@ impl Global {

#[cfg(feature = "trace")]
if let Some(ref mut trace) = *device.trace.lock() {
let data = trace.make_binary(desc.trace_binary_ext(), desc.trace_data());
trace.add(trace::Action::CreateShaderModule {
let mut file_names = Vec::new();
for (data, ext) in [
(desc.spirv.as_ref().map(|a| bytemuck::cast_slice(a)), "spv"),
(desc.dxil.as_deref(), "dxil"),
(desc.hlsl.as_ref().map(|a| a.as_bytes()), "hlsl"),
(desc.msl.as_ref().map(|a| a.as_bytes()), "msl"),
(desc.glsl.as_ref().map(|a| a.as_bytes()), "glsl"),
(desc.wgsl.as_ref().map(|a| a.as_bytes()), "wgsl"),
] {
if let Some(data) = data {
file_names.push(trace.make_binary(ext, data));
}
}
trace.add(trace::Action::CreateShaderModulePassthrough {
id: fid.id(),
desc: match desc {
pipeline::ShaderModuleDescriptorPassthrough::SpirV(inner) => {
pipeline::ShaderModuleDescriptor {
label: inner.label.clone(),
runtime_checks: wgt::ShaderRuntimeChecks::unchecked(),
}
}
pipeline::ShaderModuleDescriptorPassthrough::Msl(inner) => {
pipeline::ShaderModuleDescriptor {
label: inner.label.clone(),
runtime_checks: wgt::ShaderRuntimeChecks::unchecked(),
}
}
pipeline::ShaderModuleDescriptorPassthrough::Dxil(inner) => {
pipeline::ShaderModuleDescriptor {
label: inner.label.clone(),
runtime_checks: wgt::ShaderRuntimeChecks::unchecked(),
}
}
pipeline::ShaderModuleDescriptorPassthrough::Hlsl(inner) => {
pipeline::ShaderModuleDescriptor {
label: inner.label.clone(),
runtime_checks: wgt::ShaderRuntimeChecks::unchecked(),
}
}
},
data,
data: file_names,

entry_point: desc.entry_point.clone(),
label: desc.label.clone(),
num_workgroups: desc.num_workgroups,
reflection: desc.reflection.clone(),
runtime_checks: desc.runtime_checks,
});
};

Expand All @@ -1138,7 +1130,7 @@ impl Global {
return (id, None);
};

let id = fid.assign(Fallible::Invalid(Arc::new(desc.label().to_string())));
let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
(id, Some(error))
}

Expand Down
76 changes: 48 additions & 28 deletions wgpu-core/src/device/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2125,39 +2125,59 @@ impl Device {
descriptor: &pipeline::ShaderModuleDescriptorPassthrough<'a>,
) -> Result<Arc<pipeline::ShaderModule>, pipeline::CreateShaderModuleError> {
self.check_is_valid()?;
let hal_shader = match descriptor {
pipeline::ShaderModuleDescriptorPassthrough::SpirV(inner) => {
self.require_features(wgt::Features::SPIRV_SHADER_PASSTHROUGH)?;
hal::ShaderInput::SpirV(&inner.source)
}
pipeline::ShaderModuleDescriptorPassthrough::Msl(inner) => {
self.require_features(wgt::Features::MSL_SHADER_PASSTHROUGH)?;
hal::ShaderInput::Msl {
shader: inner.source.to_string(),
entry_point: inner.entry_point.to_string(),
num_workgroups: inner.num_workgroups,
}
}
pipeline::ShaderModuleDescriptorPassthrough::Dxil(inner) => {
self.require_features(wgt::Features::HLSL_DXIL_SHADER_PASSTHROUGH)?;
hal::ShaderInput::Dxil {
shader: inner.source,
entry_point: inner.entry_point.clone(),
num_workgroups: inner.num_workgroups,
self.require_features(wgt::Features::EXPERIMENTAL_PASSTHROUGH_SHADERS)?;

// TODO: when we get to use if-let chains, this will be a little nicer!

log::info!("Backend: {}", self.backend());
let hal_shader = match self.backend() {
wgt::Backend::Vulkan => hal::ShaderInput::SpirV(
descriptor
.spirv
.as_ref()
.ok_or(pipeline::CreateShaderModuleError::NotCompiledForBackend)?,
),
wgt::Backend::Dx12 => {
if let Some(dxil) = &descriptor.dxil {
hal::ShaderInput::Dxil {
shader: dxil,
entry_point: descriptor.entry_point.clone(),
num_workgroups: descriptor.num_workgroups,
}
} else if let Some(hlsl) = &descriptor.hlsl {
hal::ShaderInput::Hlsl {
shader: hlsl,
entry_point: descriptor.entry_point.clone(),
num_workgroups: descriptor.num_workgroups,
}
} else {
return Err(pipeline::CreateShaderModuleError::NotCompiledForBackend);
}
}
pipeline::ShaderModuleDescriptorPassthrough::Hlsl(inner) => {
self.require_features(wgt::Features::HLSL_DXIL_SHADER_PASSTHROUGH)?;
hal::ShaderInput::Hlsl {
shader: inner.source,
entry_point: inner.entry_point.clone(),
num_workgroups: inner.num_workgroups,
}
wgt::Backend::Metal => hal::ShaderInput::Msl {
shader: descriptor
.msl
.as_ref()
.ok_or(pipeline::CreateShaderModuleError::NotCompiledForBackend)?,
entry_point: descriptor.entry_point.clone(),
num_workgroups: descriptor.num_workgroups,
},
wgt::Backend::Gl => hal::ShaderInput::Glsl {
shader: descriptor
.glsl
.as_ref()
.ok_or(pipeline::CreateShaderModuleError::NotCompiledForBackend)?,
entry_point: descriptor.entry_point.clone(),
num_workgroups: descriptor.num_workgroups,
},
wgt::Backend::Noop => {
return Err(pipeline::CreateShaderModuleError::NotCompiledForBackend)
}
wgt::Backend::BrowserWebGpu => unreachable!(),
};

let hal_desc = hal::ShaderModuleDescriptor {
label: descriptor.label().to_hal(self.instance_flags),
label: descriptor.label.to_hal(self.instance_flags),
runtime_checks: wgt::ShaderRuntimeChecks::unchecked(),
};

Expand All @@ -2180,7 +2200,7 @@ impl Device {
raw: ManuallyDrop::new(raw),
device: self.clone(),
interface: None,
label: descriptor.label().to_string(),
label: descriptor.label.to_string(),
};

Ok(Arc::new(module))
Expand Down
10 changes: 10 additions & 0 deletions wgpu-core/src/device/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ pub enum Action<'a> {
desc: crate::pipeline::ShaderModuleDescriptor<'a>,
data: FileName,
},
CreateShaderModulePassthrough {
id: id::ShaderModuleId,
data: Vec<FileName>,

entry_point: String,
label: crate::Label<'a>,
num_workgroups: (u32, u32, u32),
reflection: Option<wgt::ShaderModuleReflection>,
runtime_checks: wgt::ShaderRuntimeChecks,
},
DestroyShaderModule(id::ShaderModuleId),
CreateComputePipeline {
id: id::ComputePipelineId,
Expand Down
Loading
Loading