Skip to content

Commit 1fcb7d0

Browse files
committed
Set naga capabilities corresponding to wgpu features (#4824)
# Objective At the moment all extra capabilities are disabled when validating shaders with naga: https://github.com/bevyengine/bevy/blob/c7c08f95cb784afc366eb2dcedd21d9d40e72d32/crates/bevy_render/src/render_resource/shader.rs#L146-L149 This means these features can't be used even if the corresponding wgpu features are active. ## Solution With these changes capabilities are now set corresponding to `RenderDevice::features`. --- I have validated these changes for push constants with a project I am currently working on. Though bevy does not support creating pipelines with push constants yet, so I was only able to see that shaders are validated and compiled as expected.
1 parent f0218b9 commit 1fcb7d0

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

crates/bevy_render/src/render_resource/pipeline_cache.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ impl ShaderCache {
123123
&self.shaders,
124124
&self.import_path_shaders,
125125
)?;
126-
let module_descriptor = match processed.get_module_descriptor() {
126+
let module_descriptor = match processed
127+
.get_module_descriptor(render_device.features())
128+
{
127129
Ok(module_descriptor) => module_descriptor,
128130
Err(err) => {
129131
return Err(PipelineCacheError::AsModuleDescriptorError(err, processed));

crates/bevy_render/src/render_resource/shader.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ use bevy_asset::{AssetLoader, Handle, LoadContext, LoadedAsset};
22
use bevy_reflect::{TypeUuid, Uuid};
33
use bevy_utils::{tracing::error, BoxedFuture, HashMap};
44
use naga::back::wgsl::WriterFlags;
5+
use naga::valid::Capabilities;
56
use naga::{valid::ModuleInfo, Module};
67
use once_cell::sync::Lazy;
78
use regex::Regex;
89
use std::{
910
borrow::Cow, collections::HashSet, marker::Copy, ops::Deref, path::PathBuf, str::FromStr,
1011
};
1112
use thiserror::Error;
13+
use wgpu::Features;
1214
use wgpu::{util::make_spirv, ShaderModuleDescriptor, ShaderSource};
1315

1416
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
@@ -125,7 +127,7 @@ impl ProcessedShader {
125127
}
126128
}
127129

128-
pub fn reflect(&self) -> Result<ShaderReflection, ShaderReflectError> {
130+
pub fn reflect(&self, features: Features) -> Result<ShaderReflection, ShaderReflectError> {
129131
let module = match &self {
130132
// TODO: process macros here
131133
ProcessedShader::Wgsl(source) => naga::front::wgsl::parse_str(source)?,
@@ -143,19 +145,34 @@ impl ProcessedShader {
143145
},
144146
)?,
145147
};
146-
let module_info = naga::valid::Validator::new(
147-
naga::valid::ValidationFlags::default(),
148-
naga::valid::Capabilities::default(),
149-
)
150-
.validate(&module)?;
148+
const CAPABILITIES: &[(Features, Capabilities)] = &[
149+
(Features::PUSH_CONSTANTS, Capabilities::PUSH_CONSTANT),
150+
(Features::SHADER_FLOAT64, Capabilities::FLOAT64),
151+
(
152+
Features::SHADER_PRIMITIVE_INDEX,
153+
Capabilities::PRIMITIVE_INDEX,
154+
),
155+
];
156+
let mut capabilities = Capabilities::empty();
157+
for (feature, capability) in CAPABILITIES {
158+
if features.contains(*feature) {
159+
capabilities |= *capability;
160+
}
161+
}
162+
let module_info =
163+
naga::valid::Validator::new(naga::valid::ValidationFlags::default(), capabilities)
164+
.validate(&module)?;
151165

152166
Ok(ShaderReflection {
153167
module,
154168
module_info,
155169
})
156170
}
157171

158-
pub fn get_module_descriptor(&self) -> Result<ShaderModuleDescriptor, AsModuleDescriptorError> {
172+
pub fn get_module_descriptor(
173+
&self,
174+
features: Features,
175+
) -> Result<ShaderModuleDescriptor, AsModuleDescriptorError> {
159176
Ok(ShaderModuleDescriptor {
160177
label: None,
161178
source: match self {
@@ -164,12 +181,12 @@ impl ProcessedShader {
164181
// Parse and validate the shader early, so that (e.g. while hot reloading) we can
165182
// display nicely formatted error messages instead of relying on just displaying the error string
166183
// returned by wgpu upon creating the shader module.
167-
let _ = self.reflect()?;
184+
let _ = self.reflect(features)?;
168185

169186
ShaderSource::Wgsl(source.clone())
170187
}
171188
ProcessedShader::Glsl(_source, _stage) => {
172-
let reflection = self.reflect()?;
189+
let reflection = self.reflect(features)?;
173190
// TODO: it probably makes more sense to convert this to spirv, but as of writing
174191
// this comment, naga's spirv conversion is broken
175192
let wgsl = reflection.get_wgsl()?;

0 commit comments

Comments
 (0)