wasm32: non-spirv shader specialization (#843)

wasm32: non-spirv shader specialization
This commit is contained in:
Mariusz Kryński 2020-11-15 21:07:17 +01:00 committed by GitHub
parent 18195bfa91
commit 515d750004
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 33 additions and 19 deletions

View file

@ -70,6 +70,7 @@ pub struct PipelineCompiler {
impl PipelineCompiler { impl PipelineCompiler {
fn compile_shader( fn compile_shader(
&mut self, &mut self,
render_resource_context: &dyn RenderResourceContext,
shaders: &mut Assets<Shader>, shaders: &mut Assets<Shader>,
shader_handle: &Handle<Shader>, shader_handle: &Handle<Shader>,
shader_specialization: &ShaderSpecialization, shader_specialization: &ShaderSpecialization,
@ -102,7 +103,8 @@ impl PipelineCompiler {
.iter() .iter()
.cloned() .cloned()
.collect::<Vec<String>>(); .collect::<Vec<String>>();
let compiled_shader = shader.get_spirv_shader(Some(&shader_def_vec)); let compiled_shader =
render_resource_context.get_specialized_shader(shader, Some(&shader_def_vec));
let specialized_handle = shaders.add(compiled_shader); let specialized_handle = shaders.add(compiled_shader);
let weak_specialized_handle = specialized_handle.clone_weak(); let weak_specialized_handle = specialized_handle.clone_weak();
specialized_shaders.push(SpecializedShader { specialized_shaders.push(SpecializedShader {
@ -141,6 +143,7 @@ impl PipelineCompiler {
let source_descriptor = pipelines.get(source_pipeline).unwrap(); let source_descriptor = pipelines.get(source_pipeline).unwrap();
let mut specialized_descriptor = source_descriptor.clone(); let mut specialized_descriptor = source_descriptor.clone();
specialized_descriptor.shader_stages.vertex = self.compile_shader( specialized_descriptor.shader_stages.vertex = self.compile_shader(
render_resource_context,
shaders, shaders,
&specialized_descriptor.shader_stages.vertex, &specialized_descriptor.shader_stages.vertex,
&pipeline_specialization.shader_specialization, &pipeline_specialization.shader_specialization,
@ -151,6 +154,7 @@ impl PipelineCompiler {
.as_ref() .as_ref()
.map(|fragment| { .map(|fragment| {
self.compile_shader( self.compile_shader(
render_resource_context,
shaders, shaders,
fragment, fragment,
&pipeline_specialization.shader_specialization, &pipeline_specialization.shader_specialization,

View file

@ -148,4 +148,8 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
fn get_aligned_texture_size(&self, size: usize) -> usize { fn get_aligned_texture_size(&self, size: usize) -> usize {
size size
} }
fn get_specialized_shader(&self, shader: &Shader, _macros: Option<&[String]>) -> Shader {
shader.clone()
}
} }

View file

@ -29,6 +29,7 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> BufferId; fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> BufferId;
fn create_shader_module(&self, shader_handle: &Handle<Shader>, shaders: &Assets<Shader>); fn create_shader_module(&self, shader_handle: &Handle<Shader>, shaders: &Assets<Shader>);
fn create_shader_module_from_source(&self, shader_handle: &Handle<Shader>, shader: &Shader); fn create_shader_module_from_source(&self, shader_handle: &Handle<Shader>, shader: &Shader);
fn get_specialized_shader(&self, shader: &Shader, macros: Option<&[String]>) -> Shader;
fn remove_buffer(&self, buffer: BufferId); fn remove_buffer(&self, buffer: BufferId);
fn remove_texture(&self, texture: TextureId); fn remove_texture(&self, texture: TextureId);
fn remove_sampler(&self, sampler: SamplerId); fn remove_sampler(&self, sampler: SamplerId);

View file

@ -5,12 +5,10 @@ mod shader_defs;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
mod shader_reflect; mod shader_reflect;
#[cfg(target_arch = "wasm32")]
#[path = "shader_reflect_wasm.rs"]
mod shader_reflect;
pub use shader::*; pub use shader::*;
pub use shader_defs::*; pub use shader_defs::*;
#[cfg(not(target_arch = "wasm32"))]
pub use shader_reflect::*; pub use shader_reflect::*;
use crate::pipeline::{BindGroupDescriptor, VertexBufferDescriptor}; use crate::pipeline::{BindGroupDescriptor, VertexBufferDescriptor};

View file

@ -23,7 +23,7 @@ impl Into<bevy_glsl_to_spirv::ShaderType> for ShaderStage {
} }
#[cfg(all(not(target_os = "ios"), not(target_arch = "wasm32")))] #[cfg(all(not(target_os = "ios"), not(target_arch = "wasm32")))]
fn glsl_to_spirv( pub fn glsl_to_spirv(
glsl_source: &str, glsl_source: &str,
stage: ShaderStage, stage: ShaderStage,
shader_defs: Option<&[String]>, shader_defs: Option<&[String]>,
@ -43,7 +43,7 @@ impl Into<shaderc::ShaderKind> for ShaderStage {
} }
#[cfg(target_os = "ios")] #[cfg(target_os = "ios")]
fn glsl_to_spirv( pub fn glsl_to_spirv(
glsl_source: &str, glsl_source: &str,
stage: ShaderStage, stage: ShaderStage,
shader_defs: Option<&[String]>, shader_defs: Option<&[String]>,
@ -121,17 +121,15 @@ impl Shader {
} }
} }
#[allow(unused_variables)] #[cfg(not(target_arch = "wasm32"))]
pub fn get_spirv_shader(&self, macros: Option<&[String]>) -> Shader { pub fn get_spirv_shader(&self, macros: Option<&[String]>) -> Shader {
Shader { Shader {
#[cfg(not(target_arch = "wasm32"))]
source: ShaderSource::Spirv(self.get_spirv(macros)), source: ShaderSource::Spirv(self.get_spirv(macros)),
#[cfg(target_arch = "wasm32")]
source: self.source.clone(),
stage: self.stage, stage: self.stage,
} }
} }
#[cfg(not(target_arch = "wasm32"))]
pub fn reflect_layout(&self, enforce_bevy_conventions: bool) -> Option<ShaderLayout> { pub fn reflect_layout(&self, enforce_bevy_conventions: bool) -> Option<ShaderLayout> {
if let ShaderSource::Spirv(ref spirv) = self.source { if let ShaderSource::Spirv(ref spirv) = self.source {
Some(ShaderLayout::from_spirv( Some(ShaderLayout::from_spirv(
@ -142,6 +140,11 @@ impl Shader {
panic!("Cannot reflect layout of non-SpirV shader. Try compiling this shader to SpirV first using self.get_spirv_shader()"); panic!("Cannot reflect layout of non-SpirV shader. Try compiling this shader to SpirV first using self.get_spirv_shader()");
} }
} }
#[cfg(target_arch = "wasm32")]
pub fn reflect_layout(&self, _enforce_bevy_conventions: bool) -> Option<ShaderLayout> {
panic!("Cannot reflect layout on wasm32");
}
} }
/// All stages in a shader program /// All stages in a shader program

View file

@ -1,7 +0,0 @@
use crate::shader::ShaderLayout;
impl ShaderLayout {
pub fn from_spirv(_spirv_data: &[u32], _bevy_conventions: bool) -> ShaderLayout {
panic!("reflecting shader layout from spirv data is not available");
}
}

View file

@ -12,7 +12,7 @@ use bevy_render::{
BindGroup, BufferId, BufferInfo, RenderResourceBinding, RenderResourceContext, BindGroup, BufferId, BufferInfo, RenderResourceBinding, RenderResourceContext,
RenderResourceId, SamplerId, TextureId, RenderResourceId, SamplerId, TextureId,
}, },
shader::Shader, shader::{glsl_to_spirv, Shader, ShaderSource},
texture::{Extent3d, SamplerDescriptor, TextureDescriptor}, texture::{Extent3d, SamplerDescriptor, TextureDescriptor},
}; };
use bevy_utils::tracing::trace; use bevy_utils::tracing::trace;
@ -569,4 +569,15 @@ impl RenderResourceContext for WgpuRenderResourceContext {
size size
} }
} }
fn get_specialized_shader(&self, shader: &Shader, macros: Option<&[String]>) -> Shader {
let spirv_data = match shader.source {
ShaderSource::Spirv(ref bytes) => bytes.clone(),
ShaderSource::Glsl(ref source) => glsl_to_spirv(&source, shader.stage, macros),
};
Shader {
source: ShaderSource::Spirv(spirv_data),
..*shader
}
}
} }