add glsl support

This commit is contained in:
Carter Anderson 2021-07-07 17:11:37 -07:00
parent 326b20643f
commit 3542ddcd0c
5 changed files with 67 additions and 9 deletions

View file

@ -30,7 +30,7 @@ image = { version = "0.23.12", default-features = false }
# misc # misc
wgpu = "0.9" wgpu = "0.9"
naga = { git = "https://github.com/gfx-rs/naga", rev = "0cf5484bba530f1134badbd2a1c1a8e9daf2e9c3", features = ["glsl-in", "spv-out", "spv-in", "wgsl-in"] } naga = { git = "https://github.com/gfx-rs/naga", rev = "0cf5484bba530f1134badbd2a1c1a8e9daf2e9c3", features = ["glsl-in", "spv-in", "spv-out", "wgsl-in", "wgsl-out"] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
bitflags = "1.2.1" bitflags = "1.2.1"
smallvec = { version = "1.6", features = ["union", "const_generics"] } smallvec = { version = "1.6", features = ["union", "const_generics"] }

View file

@ -1,8 +1,8 @@
use bevy_asset::{AssetLoader, LoadContext, LoadedAsset}; use bevy_asset::{AssetLoader, LoadContext, LoadedAsset};
use bevy_reflect::{TypeUuid, Uuid}; use bevy_reflect::{TypeUuid, Uuid};
use bevy_utils::{tracing::error, BoxedFuture}; use bevy_utils::{tracing::error, BoxedFuture};
use naga::{valid::ModuleInfo, Module}; use naga::{valid::ModuleInfo, Module, ShaderStage};
use std::{borrow::Cow, marker::Copy}; use std::{borrow::Cow, collections::HashMap, marker::Copy};
use thiserror::Error; use thiserror::Error;
use wgpu::{ShaderFlags, ShaderModuleDescriptor, ShaderSource}; use wgpu::{ShaderFlags, ShaderModuleDescriptor, ShaderSource};
@ -21,6 +21,8 @@ pub enum ShaderReflectError {
#[error(transparent)] #[error(transparent)]
WgslParse(#[from] naga::front::wgsl::ParseError), WgslParse(#[from] naga::front::wgsl::ParseError),
#[error(transparent)] #[error(transparent)]
GlslParse(#[from] naga::front::glsl::ParseError),
#[error(transparent)]
SpirVParse(#[from] naga::front::spv::Error), SpirVParse(#[from] naga::front::spv::Error),
#[error(transparent)] #[error(transparent)]
Validation(#[from] naga::valid::ValidationError), Validation(#[from] naga::valid::ValidationError),
@ -31,6 +33,7 @@ pub enum ShaderReflectError {
#[uuid = "d95bc916-6c55-4de3-9622-37e7b6969fda"] #[uuid = "d95bc916-6c55-4de3-9622-37e7b6969fda"]
pub enum Shader { pub enum Shader {
Wgsl(Cow<'static, str>), Wgsl(Cow<'static, str>),
Glsl(Cow<'static, str>),
SpirV(Vec<u8>), SpirV(Vec<u8>),
// TODO: consider the following // TODO: consider the following
// PrecompiledSpirVMacros(HashMap<HashSet<String>, Vec<u32>>) // PrecompiledSpirVMacros(HashMap<HashSet<String>, Vec<u32>>)
@ -53,6 +56,10 @@ impl ShaderReflection {
}, },
) )
} }
pub fn get_wgsl(&self) -> Result<String, naga::back::wgsl::Error> {
naga::back::wgsl::write_string(&self.module, &self.module_info)
}
} }
impl Shader { impl Shader {
@ -60,6 +67,18 @@ impl Shader {
let module = match &self { let module = match &self {
// TODO: process macros here // TODO: process macros here
Shader::Wgsl(source) => naga::front::wgsl::parse_str(&source)?, Shader::Wgsl(source) => naga::front::wgsl::parse_str(&source)?,
Shader::Glsl(source) => {
let mut entry_points = HashMap::default();
entry_points.insert("vertex".to_string(), ShaderStage::Vertex);
entry_points.insert("fragment".to_string(), ShaderStage::Fragment);
naga::front::glsl::parse_str(
&source,
&naga::front::glsl::Options {
entry_points,
..Default::default()
},
)?
}
Shader::SpirV(source) => naga::front::spv::parse_u8_slice( Shader::SpirV(source) => naga::front::spv::parse_u8_slice(
&source, &source,
&naga::front::spv::Options { &naga::front::spv::Options {
@ -84,6 +103,10 @@ impl Shader {
Shader::Wgsl(source.into()) Shader::Wgsl(source.into())
} }
pub fn from_glsl(source: impl Into<Cow<'static, str>>) -> Shader {
Shader::Glsl(source.into())
}
pub fn from_spirv(source: Vec<u8>) -> Shader { pub fn from_spirv(source: Vec<u8>) -> Shader {
Shader::SpirV(source) Shader::SpirV(source)
} }
@ -124,10 +147,15 @@ impl<'a> From<&'a Shader> for ShaderModuleDescriptor<'a> {
label: None, label: None,
source: match shader { source: match shader {
Shader::Wgsl(source) => ShaderSource::Wgsl(source.clone()), Shader::Wgsl(source) => ShaderSource::Wgsl(source.clone()),
Shader::Glsl(source) => {
let reflection = shader.reflect().unwrap();
let wgsl = reflection.get_wgsl().unwrap();
ShaderSource::Wgsl(wgsl.into())
}
Shader::SpirV(_) => { Shader::SpirV(_) => {
// TODO: we can probably just transmute the u8 array to u32? // TODO: we can probably just transmute the u8 array to u32?
let x = shader.reflect().unwrap(); let reflection = shader.reflect().unwrap();
let spirv = x.get_spirv().unwrap(); let spirv = reflection.get_spirv().unwrap();
ShaderSource::SpirV(Cow::Owned(spirv)) ShaderSource::SpirV(Cow::Owned(spirv))
} }
}, },

View file

@ -28,8 +28,10 @@ pub struct SpriteShaders {
impl FromWorld for SpriteShaders { impl FromWorld for SpriteShaders {
fn from_world(world: &mut World) -> Self { fn from_world(world: &mut World) -> Self {
let render_device = world.get_resource::<RenderDevice>().unwrap(); let render_device = world.get_resource::<RenderDevice>().unwrap();
let shader = Shader::from_wgsl(include_str!("sprite.wgsl")); let shader_vert = Shader::from_glsl(include_str!("sprite.vert"));
let shader_module = render_device.create_shader_module(&shader); let shader_frag = Shader::from_glsl(include_str!("sprite.frag"));
let shader_module_vert = render_device.create_shader_module(&shader_vert);
let shader_module_frag = render_device.create_shader_module(&shader_frag);
let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
entries: &[BindGroupLayoutEntry { entries: &[BindGroupLayoutEntry {
@ -96,11 +98,11 @@ impl FromWorld for SpriteShaders {
}, },
], ],
}], }],
module: &shader_module, module: &shader_module_vert,
entry_point: "vertex", entry_point: "vertex",
}, },
fragment: Some(FragmentState { fragment: Some(FragmentState {
module: &shader_module, module: &shader_module_frag,
entry_point: "fragment", entry_point: "fragment",
targets: &[ColorTargetState { targets: &[ColorTargetState {
format: TextureFormat::bevy_default(), format: TextureFormat::bevy_default(),

View file

@ -0,0 +1,11 @@
#version 450
layout(location = 0) in vec2 v_Uv;
layout(location = 0) out vec4 o_Target;
layout(set = 1, binding = 0) uniform texture2D sprite_texture;
layout(set = 1, binding = 1) uniform sampler sprite_sampler;
void fragment() {
o_Target = texture(sampler2D(sprite_texture, sprite_sampler), v_Uv);
}

View file

@ -0,0 +1,17 @@
#version 450
layout(location = 0) in vec3 Vertex_Position;
layout(location = 1) in vec2 Vertex_Uv;
layout(location = 0) out vec2 v_Uv;
layout(set = 0, binding = 0) uniform View {
mat4 ViewProj;
vec4 ViewWorldPosition;
// vec3 ViewWorldPosition;
};
void vertex() {
v_Uv = Vertex_Uv;
gl_Position = ViewProj * vec4(Vertex_Position, 1.0);
}