diff --git a/Cargo.toml b/Cargo.toml index 7186adb940..e913e3ef58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -164,6 +164,9 @@ bevy_gizmos = ["bevy_internal/bevy_gizmos", "bevy_color"] # Provides a collection of developer tools bevy_dev_tools = ["bevy_internal/bevy_dev_tools"] +# Enable passthrough loading for SPIR-V shaders (Only supported on Vulkan, shader capabilities and extensions must agree with the platform implementation) +spirv_shader_passthrough = ["bevy_internal/spirv_shader_passthrough"] + # Tracing support, saving a file in Chrome Tracing format trace_chrome = ["trace", "bevy_internal/trace_chrome"] diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 2cd6e22162..9550379682 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -44,6 +44,9 @@ ktx2 = ["bevy_render/ktx2"] zlib = ["bevy_render/zlib"] zstd = ["bevy_render/zstd"] +# Enable SPIR-V passthrough +spirv_shader_passthrough = ["bevy_render/spirv_shader_passthrough"] + # Include tonemapping LUT KTX2 files. tonemapping_luts = ["bevy_core_pipeline/tonemapping_luts"] diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 834fca03f1..628b5e6e21 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -27,6 +27,9 @@ shader_format_spirv = ["wgpu/spirv", "naga/spv-in", "naga/spv-out"] zlib = ["flate2"] zstd = ["ruzstd"] +# Enable SPIR-V shader passthrough +spirv_shader_passthrough = [] + trace = ["profiling"] tracing-tracy = [] ci_limits = [] diff --git a/crates/bevy_render/src/renderer/render_device.rs b/crates/bevy_render/src/renderer/render_device.rs index 1c0b26b912..4c2e41186f 100644 --- a/crates/bevy_render/src/renderer/render_device.rs +++ b/crates/bevy_render/src/renderer/render_device.rs @@ -49,6 +49,28 @@ impl RenderDevice { /// Creates a [`ShaderModule`](wgpu::ShaderModule) from either SPIR-V or WGSL source code. #[inline] pub fn create_shader_module(&self, desc: wgpu::ShaderModuleDescriptor) -> wgpu::ShaderModule { + #[cfg(feature = "spirv_shader_passthrough")] + match &desc.source { + wgpu::ShaderSource::SpirV(source) + if self + .features() + .contains(wgpu::Features::SPIRV_SHADER_PASSTHROUGH) => + { + // SAFETY: + // This call passes binary data to the backend as-is and can potentially result in a driver crash or bogus behaviour. + // No attempt is made to ensure that data is valid SPIR-V. + unsafe { + self.device + .create_shader_module_spirv(&wgpu::ShaderModuleDescriptorSpirV { + label: desc.label, + source: source.clone(), + }) + } + } + _ => self.device.create_shader_module(desc), + } + + #[cfg(not(feature = "spirv_shader_passthrough"))] self.device.create_shader_module(desc) } diff --git a/docs/cargo_features.md b/docs/cargo_features.md index c360c2eb8c..ca6b982b71 100644 --- a/docs/cargo_features.md +++ b/docs/cargo_features.md @@ -78,6 +78,7 @@ The default feature set enables most of the expected features of a game engine, |serialize|Enable serialization support through serde| |shader_format_glsl|Enable support for shaders in GLSL| |shader_format_spirv|Enable support for shaders in SPIR-V| +|spirv_shader_passthrough|Enable passthrough loading for SPIR-V shaders (Only supported on Vulkan, shader capabilities and extensions must agree with the platform implementation)| |symphonia-aac|AAC audio format support (through symphonia)| |symphonia-all|AAC, FLAC, MP3, MP4, OGG/VORBIS, and WAV audio formats support (through symphonia)| |symphonia-flac|FLAC audio format support (through symphonia)|