Set naga capabilities corresponding to wgpu features (#4824)
# Objective
At the moment all extra capabilities are disabled when validating shaders with naga:
c7c08f95cb/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.
This commit is contained in:
parent
f0218b9b2b
commit
1fcb7d0c2e
@ -123,7 +123,9 @@ impl ShaderCache {
|
|||||||
&self.shaders,
|
&self.shaders,
|
||||||
&self.import_path_shaders,
|
&self.import_path_shaders,
|
||||||
)?;
|
)?;
|
||||||
let module_descriptor = match processed.get_module_descriptor() {
|
let module_descriptor = match processed
|
||||||
|
.get_module_descriptor(render_device.features())
|
||||||
|
{
|
||||||
Ok(module_descriptor) => module_descriptor,
|
Ok(module_descriptor) => module_descriptor,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Err(PipelineCacheError::AsModuleDescriptorError(err, processed));
|
return Err(PipelineCacheError::AsModuleDescriptorError(err, processed));
|
||||||
|
@ -2,6 +2,7 @@ use bevy_asset::{AssetLoader, Handle, LoadContext, LoadedAsset};
|
|||||||
use bevy_reflect::{TypeUuid, Uuid};
|
use bevy_reflect::{TypeUuid, Uuid};
|
||||||
use bevy_utils::{tracing::error, BoxedFuture, HashMap};
|
use bevy_utils::{tracing::error, BoxedFuture, HashMap};
|
||||||
use naga::back::wgsl::WriterFlags;
|
use naga::back::wgsl::WriterFlags;
|
||||||
|
use naga::valid::Capabilities;
|
||||||
use naga::{valid::ModuleInfo, Module};
|
use naga::{valid::ModuleInfo, Module};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
@ -9,6 +10,7 @@ use std::{
|
|||||||
borrow::Cow, collections::HashSet, marker::Copy, ops::Deref, path::PathBuf, str::FromStr,
|
borrow::Cow, collections::HashSet, marker::Copy, ops::Deref, path::PathBuf, str::FromStr,
|
||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use wgpu::Features;
|
||||||
use wgpu::{util::make_spirv, ShaderModuleDescriptor, ShaderSource};
|
use wgpu::{util::make_spirv, ShaderModuleDescriptor, ShaderSource};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
|
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
|
||||||
@ -125,7 +127,7 @@ impl ProcessedShader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reflect(&self) -> Result<ShaderReflection, ShaderReflectError> {
|
pub fn reflect(&self, features: Features) -> Result<ShaderReflection, ShaderReflectError> {
|
||||||
let module = match &self {
|
let module = match &self {
|
||||||
// TODO: process macros here
|
// TODO: process macros here
|
||||||
ProcessedShader::Wgsl(source) => naga::front::wgsl::parse_str(source)?,
|
ProcessedShader::Wgsl(source) => naga::front::wgsl::parse_str(source)?,
|
||||||
@ -143,11 +145,23 @@ impl ProcessedShader {
|
|||||||
},
|
},
|
||||||
)?,
|
)?,
|
||||||
};
|
};
|
||||||
let module_info = naga::valid::Validator::new(
|
const CAPABILITIES: &[(Features, Capabilities)] = &[
|
||||||
naga::valid::ValidationFlags::default(),
|
(Features::PUSH_CONSTANTS, Capabilities::PUSH_CONSTANT),
|
||||||
naga::valid::Capabilities::default(),
|
(Features::SHADER_FLOAT64, Capabilities::FLOAT64),
|
||||||
)
|
(
|
||||||
.validate(&module)?;
|
Features::SHADER_PRIMITIVE_INDEX,
|
||||||
|
Capabilities::PRIMITIVE_INDEX,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
let mut capabilities = Capabilities::empty();
|
||||||
|
for (feature, capability) in CAPABILITIES {
|
||||||
|
if features.contains(*feature) {
|
||||||
|
capabilities |= *capability;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let module_info =
|
||||||
|
naga::valid::Validator::new(naga::valid::ValidationFlags::default(), capabilities)
|
||||||
|
.validate(&module)?;
|
||||||
|
|
||||||
Ok(ShaderReflection {
|
Ok(ShaderReflection {
|
||||||
module,
|
module,
|
||||||
@ -155,7 +169,10 @@ impl ProcessedShader {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_module_descriptor(&self) -> Result<ShaderModuleDescriptor, AsModuleDescriptorError> {
|
pub fn get_module_descriptor(
|
||||||
|
&self,
|
||||||
|
features: Features,
|
||||||
|
) -> Result<ShaderModuleDescriptor, AsModuleDescriptorError> {
|
||||||
Ok(ShaderModuleDescriptor {
|
Ok(ShaderModuleDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
source: match self {
|
source: match self {
|
||||||
@ -164,12 +181,12 @@ impl ProcessedShader {
|
|||||||
// Parse and validate the shader early, so that (e.g. while hot reloading) we can
|
// Parse and validate the shader early, so that (e.g. while hot reloading) we can
|
||||||
// display nicely formatted error messages instead of relying on just displaying the error string
|
// display nicely formatted error messages instead of relying on just displaying the error string
|
||||||
// returned by wgpu upon creating the shader module.
|
// returned by wgpu upon creating the shader module.
|
||||||
let _ = self.reflect()?;
|
let _ = self.reflect(features)?;
|
||||||
|
|
||||||
ShaderSource::Wgsl(source.clone())
|
ShaderSource::Wgsl(source.clone())
|
||||||
}
|
}
|
||||||
ProcessedShader::Glsl(_source, _stage) => {
|
ProcessedShader::Glsl(_source, _stage) => {
|
||||||
let reflection = self.reflect()?;
|
let reflection = self.reflect(features)?;
|
||||||
// TODO: it probably makes more sense to convert this to spirv, but as of writing
|
// TODO: it probably makes more sense to convert this to spirv, but as of writing
|
||||||
// this comment, naga's spirv conversion is broken
|
// this comment, naga's spirv conversion is broken
|
||||||
let wgsl = reflection.get_wgsl()?;
|
let wgsl = reflection.get_wgsl()?;
|
||||||
|
Loading…
Reference in New Issue
Block a user