Skip to content

Commit

Permalink
moved shader annotations into renderling-shader (#59)
Browse files Browse the repository at this point in the history
  • Loading branch information
schell authored Nov 24, 2023
1 parent 7afed4e commit 6c052fc
Show file tree
Hide file tree
Showing 71 changed files with 514 additions and 760 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ members = [
"crates/renderling",
"crates/renderling-shader",
"crates/renderling-gpui",
"crates/sandbox", "crates/renderling-derive",
"crates/renderling-derive",
"crates/sandbox",
]

exclude = ["./shaders"]
Expand Down
7 changes: 3 additions & 4 deletions NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ Just pro-cons on tech choices and little things I don't want to forget whil impl

* sharing code on CPU and GPU
- sanity testing GPU code on CPU using regular tests
- ability to run shaders on either CPU or GPU and profile
* it's Rust
- using cargo and Rust module system
- expressions!

## cons / limititions

* can't use enums (but you can't in glsl or hlsl or msl or wgsl either)
* struct layout size/alignment errors can be really tricky
* ~~can't use enums (but you can't in glsl or hlsl or msl or wgsl either)~~ you _can_ but they must be simple
* ~~struct layout size/alignment errors can be really tricky~~ solved by using a slab
* rust code must be no-std
* don't use `while let` or `while` loops
* for loops are hit or miss, sometimes they work and sometimes they don't
Expand All @@ -46,8 +47,6 @@ Just pro-cons on tech choices and little things I don't want to forget whil impl
## cons

* no support for arrays of textures on web, yet
* not yet 1.0 (on by default in chrome beta)
* ~~what happens if WebGPU the standard fails? (everyone doubts it will)~~
* atomics are not supported in the Naga SPIRV frontend, which limits the capabilities of compute
- see [the related Naga issue](https://github.com/gfx-rs/naga/issues/2301)

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# renderling 🍖

This aspires to be a modern "GPU-driven" renderer. It is alpha software. I'm still learning, but quickly!
Expand Down
66 changes: 50 additions & 16 deletions crates/renderling-derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! Provides derive macros for `renderling`.
use quote::quote;
use syn::{
spanned::Spanned, Data, DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed,
Ident, Type, WhereClause, WherePredicate, Index,
spanned::Spanned, Data, DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, Ident,
Index, Type, WhereClause, WherePredicate,
};

enum FieldName {
Index(Index),
Ident(Ident)
Ident(Ident),
}

struct Params {
Expand Down Expand Up @@ -54,7 +54,12 @@ fn get_params(input: &DeriveInput) -> syn::Result<Params> {
.ident
.clone()
.map(FieldName::Ident)
.unwrap_or_else(|| FieldName::Index(Index{index:i as u32, span: field.span()}))
.unwrap_or_else(|| {
FieldName::Index(Index {
index: i as u32,
span: field.span(),
})
})
})
.collect();
Ok(Params {
Expand All @@ -72,7 +77,7 @@ pub fn derive_from_slab(input: proc_macro::TokenStream) -> proc_macro::TokenStre
let Params {
sizes,
field_tys,
field_names
field_names,
} = match get_params(&input) {
Ok(c) => c,
Err(e) => return e.into_compile_error().into(),
Expand All @@ -93,25 +98,54 @@ pub fn derive_from_slab(input: proc_macro::TokenStream) -> proc_macro::TokenStre
constrain_system_data_types(where_clause, &field_tys)
}
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let set_index_field_names = field_names.iter().map(|name| match name {
FieldName::Index(i) => quote!{
let index = self.#i.read_slab(index, slab);
},
FieldName::Ident(field) => quote! {
let index = self.#field.read_slab(index, slab);
},
})
.collect::<Vec<_>>();
let write_index_field_names = field_names.into_iter().map(|name| match name {
FieldName::Index(i) => quote!{
let set_index_field_names = field_names
.iter()
.map(|name| match name {
FieldName::Index(i) => quote! {
let index = self.#i.read_slab(index, slab);
},
FieldName::Ident(field) => quote! {
let index = self.#field.read_slab(index, slab);
},
})
.collect::<Vec<_>>();
let write_index_field_names = field_names
.iter()
.map(|name| match name {
FieldName::Index(i) => quote! {
let index = self.#i.write_slab(index, slab);
},
FieldName::Ident(field) => quote! {
let index = self.#field.write_slab(index, slab);
},
})
.collect::<Vec<_>>();

let mut offset_tys = vec![];
let mut offsets = vec![];
for (name, ty) in field_names.iter().zip(field_tys.iter()) {
let ident = match name {
FieldName::Index(i) => Ident::new(&format!("offset_of_{}", i.index), i.span),
FieldName::Ident(field) => Ident::new(&format!("offset_of_{}", field), field.span()),
};
offsets.push(
quote!{
pub fn #ident() -> usize {
#(<#offset_tys as renderling_shader::slab::Slabbed>::slab_size()+)*
0
}
}
);
offset_tys.push(ty.clone());
}

let output = quote! {
#[automatically_derived]
/// Offsets into the slab buffer for each field.
impl #impl_generics #name #ty_generics {
#(#offsets)*
}

#[automatically_derived]
impl #impl_generics renderling_shader::slab::Slabbed for #name #ty_generics #where_clause
{
Expand Down
19 changes: 17 additions & 2 deletions crates/renderling-shader/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,30 @@ use core::marker::PhantomData;
use crate::id::Id;
use crate::slab::Slabbed;

#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
#[repr(C)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy)]
pub struct Array<T: Slabbed> {
index: u32,
len: u32,
_phantom: PhantomData<T>,
}

impl<T: Slabbed> core::fmt::Debug for Array<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Array")
.field("index", &self.index)
.field("len", &self.len)
.field("_phantom", &self._phantom)
.finish()
}
}

impl<T: Slabbed> PartialEq for Array<T> {
fn eq(&self, other: &Self) -> bool {
self.index == other.index && self.len == other.len
}
}

impl<T: Slabbed> Slabbed for Array<T> {
fn slab_size() -> usize {
2
Expand Down
52 changes: 39 additions & 13 deletions crates/renderling-shader/src/convolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use glam::{UVec2, Vec2, Vec3, Vec4, Vec4Swizzles};
use spirv_std::{
image::{Cubemap, Image2d},
num_traits::Zero,
Sampler,
spirv, Sampler,
};

#[cfg(target_arch = "spirv")]
Expand Down Expand Up @@ -148,21 +148,23 @@ pub fn integrate_brdf_doesnt_work(mut n_dot_v: f32, roughness: f32) -> Vec2 {
Vec2::new(a, b)
}

#[spirv(vertex)]
pub fn vertex_prefilter_environment_cubemap(
constants: &GpuConstants,
#[spirv(uniform, descriptor_set = 0, binding = 0)] constants: &GpuConstants,
in_pos: Vec3,
out_pos: &mut Vec3,
gl_pos: &mut Vec4,
#[spirv(position)] gl_pos: &mut Vec4,
) {
*out_pos = in_pos;
*gl_pos = constants.camera_projection * constants.camera_view * in_pos.extend(1.0);
}

/// Lambertian prefilter.
#[spirv(fragment)]
pub fn fragment_prefilter_environment_cubemap(
roughness: &f32,
environment_cubemap: &Cubemap,
sampler: &Sampler,
#[spirv(uniform, descriptor_set = 0, binding = 1)] roughness: &f32,
#[spirv(descriptor_set = 0, binding = 2)] environment_cubemap: &Cubemap,
#[spirv(descriptor_set = 0, binding = 3)] sampler: &Sampler,
in_pos: Vec3,
frag_color: &mut Vec4,
) {
Expand Down Expand Up @@ -222,29 +224,37 @@ pub fn calc_lod(n_dot_l: f32) -> f32 {
.log2()
}

pub fn vertex_generate_mipmap(vertex_id: u32, out_uv: &mut Vec2, gl_pos: &mut Vec4) {
#[spirv(vertex)]
pub fn vertex_generate_mipmap(
#[spirv(vertex_index)] vertex_id: u32,
out_uv: &mut Vec2,
#[spirv(position)] gl_pos: &mut Vec4,
) {
let i = vertex_id as usize;
*out_uv = crate::math::UV_COORD_QUAD_CCW[i];
*gl_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[i];
}

#[spirv(fragment)]
pub fn fragment_generate_mipmap(
texture: &Image2d,
sampler: &Sampler,
#[spirv(descriptor_set = 0, binding = 0)] texture: &Image2d,
#[spirv(descriptor_set = 0, binding = 1)] sampler: &Sampler,
in_uv: Vec2,
frag_color: &mut Vec4,
) {
*frag_color = texture.sample(*sampler, in_uv);
}

#[spirv(fragment)]
pub fn fragment_bloom(
horizontal: bool,
UVec2{x, y}: &UVec2,
texture: &Image2d,
sampler: &Sampler,
#[spirv(uniform, descriptor_set = 0, binding = 0)] horizontal: &u32,
#[spirv(uniform, descriptor_set = 0, binding = 1)] UVec2 { x, y }: &UVec2,
#[spirv(descriptor_set = 0, binding = 2)] texture: &Image2d,
#[spirv(descriptor_set = 0, binding = 3)] sampler: &Sampler,
in_uv: Vec2,
frag_color: &mut Vec4,
) {
let horizontal = *horizontal != 0;
let weight = [0.227027f32, 0.1945946, 0.1216216, 0.054054, 0.016216];
let texel_offset = 1.0 / Vec2::new(*x as f32, *y as f32);
let mut result = texture.sample(*sampler, in_uv).xyz() * weight[0];
Expand All @@ -263,6 +273,22 @@ pub fn fragment_bloom(
*frag_color = result.extend(1.0);
}

#[spirv(vertex)]
pub fn vertex_brdf_lut_convolution(
in_pos: glam::Vec3,
in_uv: glam::Vec2,
out_uv: &mut glam::Vec2,
#[spirv(position)] gl_pos: &mut glam::Vec4,
) {
*out_uv = in_uv;
*gl_pos = in_pos.extend(1.0);
}

#[spirv(fragment)]
pub fn fragment_brdf_lut_convolution(in_uv: glam::Vec2, out_color: &mut glam::Vec2) {
*out_color = integrate_brdf(in_uv.x, in_uv.y);
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
9 changes: 7 additions & 2 deletions crates/renderling-shader/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl DebugChannel {
Self::Emissive,
Self::UvEmissive,
Self::EmissiveFactor,
Self::EmissiveStrength
Self::EmissiveStrength,
]
}
}
Expand All @@ -101,10 +101,15 @@ impl DebugChannel {
///
/// Create one using `DebugChannel::into`.
#[repr(transparent)]
#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
#[derive(Default, Clone, Copy, PartialEq, Eq, bytemuck::Pod, bytemuck::Zeroable, Slabbed)]
pub struct DebugMode(u32);

impl core::fmt::Debug for DebugMode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("DebugMode").field(&self.0).finish()
}
}

impl From<DebugChannel> for DebugMode {
fn from(value: DebugChannel) -> Self {
DebugMode(value as u32)
Expand Down
32 changes: 32 additions & 0 deletions crates/renderling-shader/src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,38 @@ impl<T> std::fmt::Debug for Id<T> {
}
}

impl<T> core::ops::Add<usize> for Id<T> {
type Output = Self;

fn add(self, rhs: usize) -> Self::Output {
Id::new(self.0 + rhs as u32)
}
}

impl<T> core::ops::Add<Id<T>> for usize {
type Output = Id<T>;

fn add(self, rhs: Id<T>) -> Self::Output {
Id::new(self as u32 + rhs.0 as u32)
}
}

impl<T> core::ops::Add<u32> for Id<T> {
type Output = Self;

fn add(self, rhs: u32) -> Self::Output {
Id::new(self.0 + rhs)
}
}

impl<T> core::ops::Add<Id<T>> for u32 {
type Output = Id<T>;

fn add(self, rhs: Id<T>) -> Self::Output {
Id::new(self + rhs.0)
}
}

impl<T> Id<T> {
pub const NONE: Self = Id::new(ID_NONE);

Expand Down
Loading

0 comments on commit 6c052fc

Please sign in to comment.