diff --git a/src/devices/webgl/mod.rs b/src/devices/webgl/mod.rs index 9808592e..d2ff8b7a 100644 --- a/src/devices/webgl/mod.rs +++ b/src/devices/webgl/mod.rs @@ -9,6 +9,7 @@ use crate::{ use self::context::Context; mod context; +mod shader; pub struct WebGL { pub modules: Mods, diff --git a/src/devices/webgl/shader.rs b/src/devices/webgl/shader.rs new file mode 100644 index 00000000..1770c698 --- /dev/null +++ b/src/devices/webgl/shader.rs @@ -0,0 +1,25 @@ +use web_sys::{WebGl2RenderingContext, WebGlShader}; + +pub fn compile_shader( + context: &WebGl2RenderingContext, + shader_type: u32, + source: &str, +) -> Result { + let shader = context + .create_shader(shader_type) + .ok_or_else(|| String::from("Unable to create shader object"))?; + context.shader_source(&shader, source); + context.compile_shader(&shader); + + if context + .get_shader_parameter(&shader, WebGl2RenderingContext::COMPILE_STATUS) + .as_bool() + .unwrap_or(false) + { + Ok(shader) + } else { + Err(context + .get_shader_info_log(&shader) + .unwrap_or_else(|| String::from("Unknown error creating shader"))) + } +} diff --git a/src/devices/wgsl/glsl.rs b/src/devices/wgsl/glsl.rs index 9987bad4..b3832f50 100644 --- a/src/devices/wgsl/glsl.rs +++ b/src/devices/wgsl/glsl.rs @@ -1,22 +1,29 @@ use naga::{ back::glsl::{Options, PipelineOptions}, proc::BoundsCheckPolicies, - valid::ModuleInfo, + valid::ModuleInfo, ShaderStage, }; +use web_sys::{WebGl2RenderingContext, WebGlShader}; use super::{parse_and_output, error::TranslateError}; #[derive(Debug, Clone)] pub struct Glsl { - pub sources: Vec + pub sources: Vec } impl Glsl { + #[inline] pub fn from_wgsl(src: impl AsRef) -> Result { Ok(Glsl { sources: parse_and_output(src, write_glsl)?, }) } + + #[inline] + pub fn compile_all(&self, context: &WebGl2RenderingContext) -> Result, String> { + self.sources.iter().map(|s| s.compile(context)).collect() + } } pub fn write_glsl( @@ -24,7 +31,7 @@ pub fn write_glsl( info: &ModuleInfo, shader_stage: naga::ShaderStage, entry_point: &str, -) -> Result { +) -> Result { let mut glsl = String::new(); let options = Options::default(); let pipeline_options = PipelineOptions { @@ -43,7 +50,52 @@ pub fn write_glsl( ) .map_err(TranslateError::BackendGlsl)?; writer.write().map_err(TranslateError::BackendGlsl)?; - Ok(glsl) + Ok(Shader { + shader_stage, + src: glsl + }) +} + +#[derive(Debug, Clone)] +pub struct Shader { + pub shader_stage: ShaderStage, + pub src: String +} + +impl Shader { + pub fn compile(&self, context: &WebGl2RenderingContext) -> Result { + let shader_type = match self.shader_stage { + ShaderStage::Vertex => WebGl2RenderingContext::VERTEX_SHADER, + ShaderStage::Fragment => WebGl2RenderingContext::FRAGMENT_SHADER, + _ => panic!("Unsupported shader stage: {:?}", self.shader_stage) + }; + compile_shader(context, shader_type, &self.src) + } +} + + +pub fn compile_shader( + context: &WebGl2RenderingContext, + shader_type: u32, + source: &str, +) -> Result { + let shader = context + .create_shader(shader_type) + .ok_or_else(|| String::from("Unable to create shader object"))?; + context.shader_source(&shader, source); + context.compile_shader(&shader); + + if context + .get_shader_parameter(&shader, WebGl2RenderingContext::COMPILE_STATUS) + .as_bool() + .unwrap_or(false) + { + Ok(shader) + } else { + Err(context + .get_shader_info_log(&shader) + .unwrap_or_else(|| String::from("Unknown error creating shader"))) + } } #[cfg(test)] @@ -60,7 +112,23 @@ mod tests { "; let glsl = Glsl::from_wgsl(wgsl).unwrap(); let is = format!("{glsl:?}"); - let should = r##"Glsl { sources: ["#version 310 es\n\nprecision highp float;\nprecision highp int;\n\nlayout(location = 0) out vec4 _fs2p_location0;\n\nvoid main() {\n _fs2p_location0 = vec4(1.0, 0.0, 0.0, 1.0);\n return;\n}\n\n"] }"##; + let should = r##"Glsl { sources: [(Fragment, "#version 310 es\n\nprecision highp float;\nprecision highp int;\n\nlayout(location = 0) out vec4 _fs2p_location0;\n\nvoid main() {\n _fs2p_location0 = vec4(1.0, 0.0, 0.0, 1.0);\n return;\n}\n\n")] }"##; assert_eq!(is, should); } + + #[test] + fn test_wgsl_to_glsl_translation2() { + let wgsl = " + @vertex + fn vs_main(@location(0) position: vec4) -> @builtin(position) vec4 { + return position; + } + @fragment + fn fs_main() -> @location(0) vec4 { + return vec4(1.0, 0.0, 0.0, 1.0); + } + "; + let glsl = Glsl::from_wgsl(wgsl).unwrap(); + println!("{}", glsl.sources[0].src); + } }