From 2e3b69dd476e8a491dbeb9ae58a5ab81ceeb5412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Kry=C5=84ski?= Date: Wed, 11 Nov 2020 21:37:19 +0100 Subject: [PATCH 1/5] wasm32: non-spirv shader specialization --- crates/bevy_render/src/shader/shader.rs | 29 +++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/crates/bevy_render/src/shader/shader.rs b/crates/bevy_render/src/shader/shader.rs index a117ed1a933e4..8aaa7b1046137 100644 --- a/crates/bevy_render/src/shader/shader.rs +++ b/crates/bevy_render/src/shader/shader.rs @@ -121,17 +121,38 @@ impl Shader { } } - #[allow(unused_variables)] + #[cfg(not(target_arch = "wasm32"))] pub fn get_spirv_shader(&self, macros: Option<&[String]>) -> Shader { Shader { - #[cfg(not(target_arch = "wasm32"))] source: ShaderSource::Spirv(self.get_spirv(macros)), - #[cfg(target_arch = "wasm32")] - source: self.source.clone(), stage: self.stage, } } + #[cfg(target_arch = "wasm32")] + pub fn get_spirv_shader(&self, macros: Option<&[String]>) -> Shader { + if let ShaderSource::Glsl(source) = &self.source { + assert!(source.starts_with("#version")); + let eol_index = source.find('\n').unwrap(); + let (version_str, source) = source.split_at(eol_index); + let mut processed = version_str.to_string(); + processed.push_str("\n"); + if let Some(macros) = macros { + for m in macros.iter() { + processed.push_str(&format!("#define {}\n", m)); + } + } + processed.push_str("#define WEBGL\n"); + processed.push_str(source); + Shader { + source: ShaderSource::Glsl(processed), + stage: self.stage, + } + } else { + panic!("spirv shader is not supported"); + } + } + pub fn reflect_layout(&self, enforce_bevy_conventions: bool) -> Option { if let ShaderSource::Spirv(ref spirv) = self.source { Some(ShaderLayout::from_spirv( From 9054b00d76b94f56040356ae20093916e38a482c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Kry=C5=84ski?= Date: Thu, 12 Nov 2020 01:35:10 +0100 Subject: [PATCH 2/5] add RenderResourceContext.get_specialized_shader --- .../src/pipeline/pipeline_compiler.rs | 6 +++- .../headless_render_resource_context.rs | 4 +++ .../src/renderer/render_resource_context.rs | 1 + crates/bevy_render/src/shader/mod.rs | 6 ++-- crates/bevy_render/src/shader/shader.rs | 28 ++----------------- .../src/shader/shader_reflect_wasm.rs | 7 ----- .../renderer/wgpu_render_resource_context.rs | 13 ++++++++- 7 files changed, 26 insertions(+), 39 deletions(-) delete mode 100644 crates/bevy_render/src/shader/shader_reflect_wasm.rs diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index 1c122d4993b46..3dbb7f54434a1 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -70,6 +70,7 @@ pub struct PipelineCompiler { impl PipelineCompiler { fn compile_shader( &mut self, + render_resource_context: &dyn RenderResourceContext, shaders: &mut Assets, shader_handle: &Handle, shader_specialization: &ShaderSpecialization, @@ -102,7 +103,8 @@ impl PipelineCompiler { .iter() .cloned() .collect::>(); - 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 weak_specialized_handle = specialized_handle.clone_weak(); specialized_shaders.push(SpecializedShader { @@ -141,6 +143,7 @@ impl PipelineCompiler { let source_descriptor = pipelines.get(source_pipeline).unwrap(); let mut specialized_descriptor = source_descriptor.clone(); specialized_descriptor.shader_stages.vertex = self.compile_shader( + render_resource_context, shaders, &specialized_descriptor.shader_stages.vertex, &pipeline_specialization.shader_specialization, @@ -151,6 +154,7 @@ impl PipelineCompiler { .as_ref() .map(|fragment| { self.compile_shader( + render_resource_context, shaders, fragment, &pipeline_specialization.shader_specialization, diff --git a/crates/bevy_render/src/renderer/headless_render_resource_context.rs b/crates/bevy_render/src/renderer/headless_render_resource_context.rs index 9c5d09c1fe08c..03e3177f4c636 100644 --- a/crates/bevy_render/src/renderer/headless_render_resource_context.rs +++ b/crates/bevy_render/src/renderer/headless_render_resource_context.rs @@ -148,4 +148,8 @@ impl RenderResourceContext for HeadlessRenderResourceContext { fn get_aligned_texture_size(&self, size: usize) -> usize { size } + + fn get_specialized_shader(&self, shader: &Shader, _macros: Option<&[String]>) -> Shader { + shader.clone() + } } diff --git a/crates/bevy_render/src/renderer/render_resource_context.rs b/crates/bevy_render/src/renderer/render_resource_context.rs index ecd255938808f..3e49b0bccafa4 100644 --- a/crates/bevy_render/src/renderer/render_resource_context.rs +++ b/crates/bevy_render/src/renderer/render_resource_context.rs @@ -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_shader_module(&self, shader_handle: &Handle, shaders: &Assets); fn create_shader_module_from_source(&self, shader_handle: &Handle, shader: &Shader); + fn get_specialized_shader(&self, shader: &Shader, macros: Option<&[String]>) -> Shader; fn remove_buffer(&self, buffer: BufferId); fn remove_texture(&self, texture: TextureId); fn remove_sampler(&self, sampler: SamplerId); diff --git a/crates/bevy_render/src/shader/mod.rs b/crates/bevy_render/src/shader/mod.rs index 47a6a0fed3f84..32e4673521c38 100644 --- a/crates/bevy_render/src/shader/mod.rs +++ b/crates/bevy_render/src/shader/mod.rs @@ -5,12 +5,10 @@ mod shader_defs; #[cfg(not(target_arch = "wasm32"))] mod shader_reflect; -#[cfg(target_arch = "wasm32")] -#[path = "shader_reflect_wasm.rs"] -mod shader_reflect; - pub use shader::*; pub use shader_defs::*; + +#[cfg(not(target_arch = "wasm32"))] pub use shader_reflect::*; use crate::pipeline::{BindGroupDescriptor, VertexBufferDescriptor}; diff --git a/crates/bevy_render/src/shader/shader.rs b/crates/bevy_render/src/shader/shader.rs index 8aaa7b1046137..2d7869597947e 100644 --- a/crates/bevy_render/src/shader/shader.rs +++ b/crates/bevy_render/src/shader/shader.rs @@ -23,7 +23,7 @@ impl Into for ShaderStage { } #[cfg(all(not(target_os = "ios"), not(target_arch = "wasm32")))] -fn glsl_to_spirv( +pub fn glsl_to_spirv( glsl_source: &str, stage: ShaderStage, shader_defs: Option<&[String]>, @@ -43,7 +43,7 @@ impl Into for ShaderStage { } #[cfg(target_os = "ios")] -fn glsl_to_spirv( +pub fn glsl_to_spirv( glsl_source: &str, stage: ShaderStage, shader_defs: Option<&[String]>, @@ -129,30 +129,6 @@ impl Shader { } } - #[cfg(target_arch = "wasm32")] - pub fn get_spirv_shader(&self, macros: Option<&[String]>) -> Shader { - if let ShaderSource::Glsl(source) = &self.source { - assert!(source.starts_with("#version")); - let eol_index = source.find('\n').unwrap(); - let (version_str, source) = source.split_at(eol_index); - let mut processed = version_str.to_string(); - processed.push_str("\n"); - if let Some(macros) = macros { - for m in macros.iter() { - processed.push_str(&format!("#define {}\n", m)); - } - } - processed.push_str("#define WEBGL\n"); - processed.push_str(source); - Shader { - source: ShaderSource::Glsl(processed), - stage: self.stage, - } - } else { - panic!("spirv shader is not supported"); - } - } - pub fn reflect_layout(&self, enforce_bevy_conventions: bool) -> Option { if let ShaderSource::Spirv(ref spirv) = self.source { Some(ShaderLayout::from_spirv( diff --git a/crates/bevy_render/src/shader/shader_reflect_wasm.rs b/crates/bevy_render/src/shader/shader_reflect_wasm.rs deleted file mode 100644 index aa40454716963..0000000000000 --- a/crates/bevy_render/src/shader/shader_reflect_wasm.rs +++ /dev/null @@ -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"); - } -} diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs index f47a227102667..a2a7ae5d20df2 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs @@ -12,7 +12,7 @@ use bevy_render::{ BindGroup, BufferId, BufferInfo, RenderResourceBinding, RenderResourceContext, RenderResourceId, SamplerId, TextureId, }, - shader::Shader, + shader::{glsl_to_spirv, Shader, ShaderSource}, texture::{Extent3d, SamplerDescriptor, TextureDescriptor}, }; use bevy_utils::tracing::trace; @@ -569,4 +569,15 @@ impl RenderResourceContext for WgpuRenderResourceContext { 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 + } + } } From 02e95edf415627cd9e2e751a404ed5c18ec9e4c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Kry=C5=84ski?= Date: Thu, 12 Nov 2020 02:17:19 +0100 Subject: [PATCH 3/5] define WGPU --- .../src/renderer/wgpu_render_resource_context.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs index a2a7ae5d20df2..07c9fdf7da191 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs @@ -571,9 +571,15 @@ impl RenderResourceContext for WgpuRenderResourceContext { } fn get_specialized_shader(&self, shader: &Shader, macros: Option<&[String]>) -> Shader { + let macros: Vec = macros + .unwrap_or(&[]) + .iter() + .chain((&["WGPU".to_string()]).iter()) + .cloned() + .collect(); let spirv_data = match shader.source { ShaderSource::Spirv(ref bytes) => bytes.clone(), - ShaderSource::Glsl(ref source) => glsl_to_spirv(&source, shader.stage, macros), + ShaderSource::Glsl(ref source) => glsl_to_spirv(&source, shader.stage, Some(¯os)), }; Shader { source: ShaderSource::Spirv(spirv_data), From 68b67a7b9328da838e61bed78d404a9fdf2d905c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Kry=C5=84ski?= Date: Thu, 12 Nov 2020 02:33:35 +0100 Subject: [PATCH 4/5] fix for wasm32 --- crates/bevy_render/src/shader/shader.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/bevy_render/src/shader/shader.rs b/crates/bevy_render/src/shader/shader.rs index 2d7869597947e..14e575f670366 100644 --- a/crates/bevy_render/src/shader/shader.rs +++ b/crates/bevy_render/src/shader/shader.rs @@ -129,6 +129,7 @@ impl Shader { } } + #[cfg(not(target_arch = "wasm32"))] pub fn reflect_layout(&self, enforce_bevy_conventions: bool) -> Option { if let ShaderSource::Spirv(ref spirv) = self.source { Some(ShaderLayout::from_spirv( @@ -139,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()"); } } + + #[cfg(target_arch = "wasm32")] + pub fn reflect_layout(&self, _enforce_bevy_conventions: bool) -> Option { + panic!("Cannot reflect layout on wasm32"); + } } /// All stages in a shader program From 38d93aacabba2317cc16f80a6d737b19d0b90dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Kry=C5=84ski?= Date: Fri, 13 Nov 2020 10:44:32 +0100 Subject: [PATCH 5/5] do not set WGPU macro --- .../src/renderer/wgpu_render_resource_context.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs index 07c9fdf7da191..a2a7ae5d20df2 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs @@ -571,15 +571,9 @@ impl RenderResourceContext for WgpuRenderResourceContext { } fn get_specialized_shader(&self, shader: &Shader, macros: Option<&[String]>) -> Shader { - let macros: Vec = macros - .unwrap_or(&[]) - .iter() - .chain((&["WGPU".to_string()]).iter()) - .cloned() - .collect(); let spirv_data = match shader.source { ShaderSource::Spirv(ref bytes) => bytes.clone(), - ShaderSource::Glsl(ref source) => glsl_to_spirv(&source, shader.stage, Some(¯os)), + ShaderSource::Glsl(ref source) => glsl_to_spirv(&source, shader.stage, macros), }; Shader { source: ShaderSource::Spirv(spirv_data),