Skip to content

Commit

Permalink
Add shader compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
elftausend committed Jan 24, 2024
1 parent e68a3ef commit 9043c3b
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/devices/webgl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
use self::context::Context;

mod context;
mod shader;

pub struct WebGL<Mods = Base> {
pub modules: Mods,
Expand Down
25 changes: 25 additions & 0 deletions src/devices/webgl/shader.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use web_sys::{WebGl2RenderingContext, WebGlShader};

pub fn compile_shader(
context: &WebGl2RenderingContext,
shader_type: u32,
source: &str,
) -> Result<WebGlShader, String> {
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")))
}
}
78 changes: 73 additions & 5 deletions src/devices/wgsl/glsl.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
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<String>
pub sources: Vec<Shader>
}

impl Glsl {
#[inline]
pub fn from_wgsl(src: impl AsRef<str>) -> Result<Self, TranslateError> {
Ok(Glsl {
sources: parse_and_output(src, write_glsl)?,
})
}

#[inline]
pub fn compile_all(&self, context: &WebGl2RenderingContext) -> Result<Vec<WebGlShader>, String> {
self.sources.iter().map(|s| s.compile(context)).collect()
}
}

pub fn write_glsl(
module: &naga::Module,
info: &ModuleInfo,
shader_stage: naga::ShaderStage,
entry_point: &str,
) -> Result<String, TranslateError> {
) -> Result<Shader, TranslateError> {
let mut glsl = String::new();
let options = Options::default();
let pipeline_options = PipelineOptions {
Expand All @@ -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<WebGlShader, String> {
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<WebGlShader, String> {
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)]
Expand All @@ -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<f32>) -> @builtin(position) vec4<f32> {
return position;
}
@fragment
fn fs_main() -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
}
";
let glsl = Glsl::from_wgsl(wgsl).unwrap();
println!("{}", glsl.sources[0].src);
}
}

0 comments on commit 9043c3b

Please sign in to comment.