Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full Ray-Traced Renderer #10

Merged
merged 16 commits into from
Mar 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
[workspace]
resolver = "2"
members = [
"blade-egui",
"blade-graphics",
"blade-macros",
"blade-render",
"run-wasm",
]
exclude = []

[workspace.dependencies]
naga = { git = "https://github.com/kvark/naga", branch = "ray-query", features = ["wgsl-in", "span", "validate"] }
bytemuck = { version = "1", features = ["derive"] }
egui = "0.20"
glam = { version = "0.23", features = ["mint"] }
log = "0.4"
mint = "0.5"
naga = { git = "https://github.com/kvark/naga", branch = "storage-array", features = ["wgsl-in", "span", "validate"] }
web-sys = "0.3.60"

[lib]

[package]
name = "blade"
description = "Sharp and simple graphics library"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
rust-version = "1.65"
keywords = ["graphics"]
Expand All @@ -27,13 +34,16 @@ readme = "docs/README.md"
[features]

[dependencies]
blade-macros = { version = "0.1.0", path = "blade-macros" }
blade-graphics = { version = "0.1.0", path = "blade-graphics" }
blade-macros = { version = "0.2.0", path = "blade-macros" }
blade-graphics = { version = "0.2.0", path = "blade-graphics" }
blade-render = { version = "0.1.0", path = "blade-render" }

[dev-dependencies]
bytemuck = { version = "1", features = ["derive"] }
blade-egui = { version = "0.1.0", path = "blade-egui" }
bytemuck = { workspace = true }
egui = { workspace = true }
del-msh = "0.1"
egui = { version = "0.20", features = ["bytemuck"] }
glam = { workspace = true }
naga = { workspace = true }
nanorand = { version = "0.7", default-features = false, features = ["wyrand"] }
winit = "0.27"
Expand Down
16 changes: 16 additions & 0 deletions blade-egui/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "blade-egui"
version = "0.1.0"
edition = "2021"
description = "egui integration for Blade"
keywords = ["graphics"]
license = "MIT"
repository = "https://github.com/kvark/blade"

[lib]

[dependencies]
blade = { package = "blade-graphics", version = "0.2", path = "../blade-graphics"}
blade-macros = { version = "0.2", path = "../blade-macros"}
bytemuck = { workspace = true }
egui = { workspace = true, features = ["bytemuck"] }
File renamed without changes.
8 changes: 5 additions & 3 deletions examples/particle/belt.rs → blade-egui/src/belt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ pub struct BeltDescriptor {
pub min_chunk_size: u64,
}

/// A belt of buffers, used by the EguiPainter to cheaply
/// find staging space for uploads.
pub struct BufferBelt {
desc: BeltDescriptor,
buffers: Vec<(ReusableBuffer, blade::SyncPoint)>,
Expand All @@ -23,11 +25,11 @@ impl BufferBelt {
}
}

pub fn delete(self, context: &blade::Context) {
for (buffer, _) in self.buffers {
pub fn destroy(&mut self, context: &blade::Context) {
for (buffer, _) in self.buffers.drain(..) {
context.destroy_buffer(buffer.raw);
}
for (buffer, _) in self.active {
for (buffer, _) in self.active.drain(..) {
context.destroy_buffer(buffer.raw);
}
}
Expand Down
18 changes: 11 additions & 7 deletions examples/particle/gui.rs → blade-egui/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use super::belt::{BeltDescriptor, BufferBelt};
#![allow(irrefutable_let_patterns)]

mod belt;

use belt::{BeltDescriptor, BufferBelt};
use std::{
collections::hash_map::{Entry, HashMap},
fs, mem, ptr,
Expand All @@ -11,13 +15,13 @@ struct Uniforms {
padding: [f32; 2],
}

#[derive(blade::ShaderData)]
#[derive(blade_macros::ShaderData)]
struct Globals {
r_uniforms: Uniforms,
r_sampler: blade::Sampler,
}

#[derive(blade::ShaderData)]
#[derive(blade_macros::ShaderData)]
struct Locals {
r_vertex_data: blade::BufferPiece,
r_texture: blade::TextureView,
Expand Down Expand Up @@ -84,16 +88,16 @@ pub struct GuiPainter {
}

impl GuiPainter {
pub fn delete(self, context: &blade::Context) {
self.belt.delete(context);
for (_, gui_texture) in self.textures {
pub fn destroy(&mut self, context: &blade::Context) {
self.belt.destroy(context);
for (_, gui_texture) in self.textures.drain() {
gui_texture.delete(context);
}
context.destroy_sampler(self.sampler);
}

pub fn new(context: &blade::Context, output_format: blade::TextureFormat) -> Self {
let shader_source = fs::read_to_string("examples/particle/gui.wgsl").unwrap();
let shader_source = fs::read_to_string("blade-egui/shader.wgsl").unwrap();
let shader = context.create_shader(blade::ShaderDesc {
source: &shader_source,
});
Expand Down
8 changes: 4 additions & 4 deletions blade-graphics/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "blade-graphics"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
description = "Graphics abstraction for Blade"
keywords = ["graphics"]
Expand All @@ -14,15 +14,15 @@ bitflags = "1"
bytemuck = "1"
codespan-reporting = "0.11"
hidden-trait = "0.1"
log = "0.4"
mint = "0.5"
log = { workspace = true }
mint = { workspace = true }
naga = { workspace = true, features = ["clone"] }
raw-window-handle = "0.5"

[target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies]
block = "0.1"
core-graphics-types = "0.1"
metal = { git = "https://github.com/gfx-rs/metal-rs", rev = "33c96191390c1f9c69060f9703667e95dd75b475" }
metal = { git = "https://github.com/gfx-rs/metal-rs", rev = "64d98e700c301aee0a0855ae2f1008750ef33ca9" }
objc = "0.2.5"
naga = { workspace = true, features = ["msl-out"] }

Expand Down
10 changes: 10 additions & 0 deletions blade-graphics/src/gles/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ impl crate::ShaderBindable for super::TextureView {
}
}
}
impl<'a, const N: crate::ResourceIndex> crate::ShaderBindable for &'a crate::TextureArray<N> {
fn bind_to(&self, _ctx: &mut super::PipelineContext, _index: u32) {
unimplemented!()
}
}
impl crate::ShaderBindable for super::Sampler {
fn bind_to(&self, ctx: &mut super::PipelineContext, index: u32) {
for &slot in ctx.targets[index as usize].iter() {
Expand All @@ -59,6 +64,11 @@ impl crate::ShaderBindable for crate::BufferPiece {
}
}
}
impl<'a, const N: crate::ResourceIndex> crate::ShaderBindable for &'a crate::BufferArray<N> {
fn bind_to(&self, _ctx: &mut super::PipelineContext, _index: u32) {
unimplemented!()
}
}
impl crate::ShaderBindable for super::AccelerationStructure {
fn bind_to(&self, ctx: &mut super::PipelineContext, index: u32) {
for _ in ctx.targets[index as usize].iter() {
Expand Down
4 changes: 3 additions & 1 deletion blade-graphics/src/gles/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ impl super::Context {
targets.push(params[0] as u32);
}
}
crate::ShaderBinding::AccelerationStructure => {
crate::ShaderBinding::TextureArray { .. }
| crate::ShaderBinding::BufferArray { .. }
| crate::ShaderBinding::AccelerationStructure => {
unimplemented!()
}
crate::ShaderBinding::Plain { size } => {
Expand Down
58 changes: 57 additions & 1 deletion blade-graphics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub struct Capabilities {
pub enum Memory {
/// Device-local memory. Fast for GPU operations.
Device,
/// Shared CPU-GPU memory. Not so far for GPU.
/// Shared CPU-GPU memory. Not so fast for GPU.
Shared,
/// Upload memory. Can only be transferred on GPU.
Upload,
Expand Down Expand Up @@ -123,6 +123,53 @@ impl Buffer {
}
}

pub type ResourceIndex = u32;
/// An array of resources to be used with shader bindings.
/// The generic argument tells the maximum number of resources.
pub struct ResourceArray<T, const N: ResourceIndex> {
data: Vec<T>,
free_list: Vec<ResourceIndex>,
}
impl<T, const N: ResourceIndex> ResourceArray<T, N> {
pub fn new() -> Self {
Self {
data: Vec::with_capacity(N as usize),
free_list: Vec::new(),
}
}
pub fn alloc(&mut self, value: T) -> ResourceIndex {
if let Some(index) = self.free_list.pop() {
self.data[index as usize] = value;
index
} else {
let index = self.data.len() as u32;
assert!(index < N);
self.data.push(value);
index
}
}
pub fn free(&mut self, index: ResourceIndex) {
self.free_list.push(index);
}
pub fn clear(&mut self) {
self.data.clear();
self.free_list.clear();
}
}
impl<T, const N: ResourceIndex> std::ops::Index<ResourceIndex> for ResourceArray<T, N> {
type Output = T;
fn index(&self, index: ResourceIndex) -> &T {
&self.data[index as usize]
}
}
impl<T, const N: ResourceIndex> std::ops::IndexMut<ResourceIndex> for ResourceArray<T, N> {
fn index_mut(&mut self, index: ResourceIndex) -> &mut T {
&mut self.data[index as usize]
}
}
pub type BufferArray<const N: ResourceIndex> = ResourceArray<BufferPiece, N>;
pub type TextureArray<const N: ResourceIndex> = ResourceArray<TextureView, N>;

#[derive(Clone, Copy, Debug)]
pub struct TexturePiece {
pub texture: Texture,
Expand Down Expand Up @@ -376,6 +423,7 @@ pub struct AccelerationStructureInstance {
pub acceleration_structure_index: u32,
pub transform: Transform,
pub mask: u32,
pub custom_index: u32,
}

#[derive(Clone, Copy, Debug, PartialEq)]
Expand Down Expand Up @@ -411,8 +459,10 @@ impl ShaderFunction<'_> {
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ShaderBinding {
Texture,
TextureArray { count: u32 },
Sampler,
Buffer,
BufferArray { count: u32 },
AccelerationStructure,
Plain { size: u32 },
}
Expand All @@ -438,6 +488,12 @@ impl HasShaderBinding for Sampler {
impl HasShaderBinding for BufferPiece {
const TYPE: ShaderBinding = ShaderBinding::Buffer;
}
impl<'a, const N: ResourceIndex> HasShaderBinding for &'a BufferArray<N> {
const TYPE: ShaderBinding = ShaderBinding::BufferArray { count: N };
}
impl<'a, const N: ResourceIndex> HasShaderBinding for &'a TextureArray<N> {
const TYPE: ShaderBinding = ShaderBinding::TextureArray { count: N };
}
impl HasShaderBinding for AccelerationStructure {
const TYPE: ShaderBinding = ShaderBinding::AccelerationStructure;
}
Expand Down
13 changes: 13 additions & 0 deletions blade-graphics/src/metal/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ impl crate::ShaderBindable for super::TextureView {
}
}
}
impl<'a, const N: crate::ResourceIndex> crate::ShaderBindable for &'a crate::TextureArray<N> {
fn bind_to(&self, _ctx: &mut super::PipelineContext, _index: u32) {
unimplemented!()
}
}
impl crate::ShaderBindable for super::Sampler {
fn bind_to(&self, ctx: &mut super::PipelineContext, index: u32) {
//self.raw.set_sampler_state(index as _, sampler.as_ref());
Expand Down Expand Up @@ -62,6 +67,11 @@ impl crate::ShaderBindable for crate::BufferPiece {
}
}
}
impl<'a, const N: crate::ResourceIndex> crate::ShaderBindable for &'a crate::BufferArray<N> {
fn bind_to(&self, _ctx: &mut super::PipelineContext, _index: u32) {
unimplemented!()
}
}
impl crate::ShaderBindable for crate::AccelerationStructure {
fn bind_to(&self, ctx: &mut super::PipelineContext, index: u32) {
let slot = ctx.targets[index as usize] as _;
Expand Down Expand Up @@ -337,6 +347,9 @@ impl crate::traits::AccelerationStructureEncoder
&primitive_acceleration_structures,
));
descriptor.set_instance_count(instance_count as _);
descriptor.set_instance_descriptor_type(
metal::MTLAccelerationStructureInstanceDescriptorType::UserID,
);
descriptor.set_instance_descriptor_buffer(instance_data.buffer.as_ref());
descriptor.set_instance_descriptor_buffer_offset(instance_data.offset);

Expand Down
1 change: 1 addition & 0 deletions blade-graphics/src/metal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ impl AccelerationStructure {
}
}

//TODO: make this copyable?
#[derive(Clone, Debug)]
pub struct SyncPoint {
cmd_buf: metal::CommandBuffer,
Expand Down
2 changes: 2 additions & 0 deletions blade-graphics/src/metal/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ impl super::PipelineLayout {
num_buffers += 1;
num_buffers - 1
}
crate::ShaderBinding::TextureArray { .. }
| crate::ShaderBinding::BufferArray { .. } => unimplemented!(),
crate::ShaderBinding::AccelerationStructure => {
num_buffers += 1;
num_buffers - 1
Expand Down
7 changes: 4 additions & 3 deletions blade-graphics/src/metal/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,19 @@ impl super::Context {
let mut instance_descriptors = Vec::with_capacity(instances.len());
for instance in instances {
let transposed = mint::ColumnMatrix3x4::from(instance.transform);
instance_descriptors.push(metal::MTLAccelerationStructureInstanceDescriptor {
instance_descriptors.push(metal::MTLAccelerationStructureUserIDInstanceDescriptor {
acceleration_structure_index: instance.acceleration_structure_index,
mask: instance.mask,
transformation_matrix: transposed.into(),
options: metal::MTLAccelerationStructureInstanceOptions::None,
intersection_function_table_offset: 0,
user_id: instance.custom_index,
});
}
let buffer = self.device.lock().unwrap().new_buffer_with_data(
instance_descriptors.as_ptr() as *const _,
(mem::size_of::<metal::MTLAccelerationStructureInstanceDescriptor>() * instances.len())
as _,
(mem::size_of::<metal::MTLAccelerationStructureUserIDInstanceDescriptor>()
* instances.len()) as _,
metal::MTLResourceOptions::StorageModeShared,
);
super::Buffer {
Expand Down
2 changes: 1 addition & 1 deletion blade-graphics/src/shader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl super::Context {
let flags = naga::valid::ValidationFlags::all() ^ naga::valid::ValidationFlags::BINDINGS;
let mut caps = naga::valid::Capabilities::empty();
caps.set(
naga::valid::Capabilities::RAY_QUERY,
naga::valid::Capabilities::RAY_QUERY | naga::valid::Capabilities::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
!device_caps.ray_query.is_empty(),
);
let info = naga::valid::Validator::new(flags, caps)
Expand Down
Loading