whoops, forgor this file
This commit is contained in:
parent
3c6baa591d
commit
8ccdfad42a
315
crates/renderer/src/render_graph/graph_builder.rs
Normal file
315
crates/renderer/src/render_graph/graph_builder.rs
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
use std::{cell::UnsafeCell, collections::BTreeMap, marker::PhantomData};
|
||||
|
||||
use ash::vk;
|
||||
use derive_more::derive::{Deref, DerefMut};
|
||||
|
||||
use crate::{
|
||||
buffers, images,
|
||||
render_graph::{
|
||||
recorder::CommandList,
|
||||
resources::{self, ResourceId},
|
||||
},
|
||||
};
|
||||
|
||||
pub struct GraphResourceRegistry {
|
||||
images: BTreeMap<ResourceId, UnsafeCell<images::Image>>,
|
||||
views: BTreeMap<ResourceId, UnsafeCell<images::ImageView>>,
|
||||
buffers: BTreeMap<ResourceId, UnsafeCell<buffers::Buffer>>,
|
||||
}
|
||||
|
||||
#[derive(Deref, DerefMut)]
|
||||
struct StagingBuffer<'a> {
|
||||
id: ResourceId,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
buffer: &'a mut buffers::Buffer,
|
||||
}
|
||||
|
||||
#[derive(Deref, DerefMut)]
|
||||
struct Buffer<'a> {
|
||||
id: ResourceId,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
buffer: &'a mut buffers::Buffer,
|
||||
}
|
||||
|
||||
pub struct GraphBuilder<'r> {
|
||||
_pd: PhantomData<fn(&'r ())>,
|
||||
}
|
||||
impl<'r> GraphBuilder<'r> {
|
||||
fn make_command_list<'cmd>(&self) -> CommandList<'cmd> {
|
||||
todo!()
|
||||
}
|
||||
fn make_staging_buffer(&self, _size: u64) -> StagingBuffer<'r> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn make_buffer(
|
||||
&self,
|
||||
_size: u64,
|
||||
_usage: vk::BufferUsageFlags,
|
||||
_location: gpu_allocator::MemoryLocation,
|
||||
) -> Buffer<'r> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// we need to know which queue currently owns this buffer to be able to
|
||||
// transfer it to the correct queue family when using it
|
||||
fn import_buffer(&self, _buffer: buffers::Buffer, _owning_queue: Option<u32>) -> Buffer<'r> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
mod api_demo {
|
||||
|
||||
use crate::{EguiState, pipeline::Pipeline, render_graph::commands};
|
||||
|
||||
use super::*;
|
||||
use ash::vk::{self, BufferUsageFlags};
|
||||
use gpu_allocator::MemoryLocation;
|
||||
use indexmap::IndexMap;
|
||||
|
||||
fn egui_graph<'a>(
|
||||
egui_state: &mut EguiState,
|
||||
draw_data: Vec<egui::ClippedPrimitive>,
|
||||
builder: GraphBuilder,
|
||||
render_target: ResourceId,
|
||||
extent: (u32, u32),
|
||||
pipeline: &'a Pipeline,
|
||||
descriptor: vk::DescriptorSet,
|
||||
) -> CommandList<'a> {
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
struct Vertex {
|
||||
pos: glam::Vec2,
|
||||
uv: glam::Vec2,
|
||||
color: egui::epaint::Color32,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct DrawCall(vk::DrawIndexedIndirectCommand);
|
||||
unsafe impl bytemuck::Zeroable for DrawCall {}
|
||||
unsafe impl bytemuck::Pod for DrawCall {}
|
||||
|
||||
let mut vertices = Vec::new();
|
||||
let mut indices = Vec::new();
|
||||
let mut draw_calls = Vec::new();
|
||||
let mut textures = IndexMap::new();
|
||||
let mut textures_indices = Vec::new();
|
||||
for draw in draw_data {
|
||||
let egui::epaint::Primitive::Mesh(mesh) = draw.primitive else {
|
||||
continue;
|
||||
};
|
||||
|
||||
draw_calls.push(DrawCall(vk::DrawIndexedIndirectCommand {
|
||||
index_count: mesh.indices.len() as u32,
|
||||
instance_count: 1,
|
||||
first_index: indices.len() as u32,
|
||||
vertex_offset: vertices.len() as i32,
|
||||
first_instance: 0,
|
||||
}));
|
||||
|
||||
vertices.extend(mesh.vertices.iter().map(|v| Vertex {
|
||||
pos: glam::vec2(v.pos.x, v.pos.y),
|
||||
uv: glam::vec2(v.uv.x, v.uv.y),
|
||||
color: v.color,
|
||||
}));
|
||||
|
||||
indices.extend(mesh.indices);
|
||||
let texture = egui_state.textures.get(&mesh.texture_id).cloned().unwrap();
|
||||
if !textures.contains_key(&texture.id) {
|
||||
textures.insert(texture.id, texture);
|
||||
}
|
||||
let idx = textures.get_index_of(&texture.id).unwrap();
|
||||
textures_indices.push(idx as u32);
|
||||
}
|
||||
|
||||
let vertex_size = vertices.len() * size_of::<Vertex>();
|
||||
let index_size = indices.len() * size_of::<u32>();
|
||||
let draw_calls_size = draw_calls.len() * size_of::<DrawCall>();
|
||||
let textures_indices_size = textures_indices.len() * size_of::<u32>();
|
||||
let staging_size = vertex_size + index_size + draw_calls_size + textures_indices_size;
|
||||
let mut staging = builder.make_staging_buffer(staging_size as u64);
|
||||
|
||||
use core::io::BorrowedBuf;
|
||||
let mut buf = BorrowedBuf::from(staging.map_mut().unwrap());
|
||||
let mut cursor = buf.unfilled();
|
||||
cursor.append(bytemuck::cast_slice(&vertices));
|
||||
cursor.append(bytemuck::cast_slice(&indices));
|
||||
cursor.append(bytemuck::cast_slice(&draw_calls));
|
||||
cursor.append(bytemuck::cast_slice(&textures_indices));
|
||||
|
||||
let vertex_buffer = builder.make_buffer(
|
||||
vertex_size as u64,
|
||||
BufferUsageFlags::TRANSFER_DST | BufferUsageFlags::VERTEX_BUFFER,
|
||||
MemoryLocation::GpuOnly,
|
||||
);
|
||||
let index_buffer = builder.make_buffer(
|
||||
index_size as u64,
|
||||
BufferUsageFlags::TRANSFER_DST | BufferUsageFlags::INDEX_BUFFER,
|
||||
MemoryLocation::GpuOnly,
|
||||
);
|
||||
let indirect_buffer = builder.make_buffer(
|
||||
draw_calls_size as u64,
|
||||
BufferUsageFlags::TRANSFER_DST | BufferUsageFlags::INDIRECT_BUFFER,
|
||||
MemoryLocation::GpuOnly,
|
||||
);
|
||||
let texture_indices = builder.make_buffer(
|
||||
textures_indices_size as u64,
|
||||
BufferUsageFlags::TRANSFER_DST | BufferUsageFlags::STORAGE_BUFFER,
|
||||
MemoryLocation::GpuOnly,
|
||||
);
|
||||
|
||||
let mut cmd = builder.make_command_list();
|
||||
cmd.push(commands::Copy {
|
||||
src: resources::BufferSlice {
|
||||
buffer: resources::Buffer(staging.id),
|
||||
range: resources::BufferRange {
|
||||
offset: 0,
|
||||
size: vertex_size as u64,
|
||||
},
|
||||
},
|
||||
dst: resources::BufferSlice {
|
||||
buffer: resources::Buffer(vertex_buffer.id),
|
||||
range: resources::BufferRange {
|
||||
offset: 0,
|
||||
size: vertex_size as u64,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
cmd.push(commands::Copy {
|
||||
src: resources::BufferSlice {
|
||||
buffer: resources::Buffer(staging.id),
|
||||
range: resources::BufferRange {
|
||||
offset: vertex_size as u64,
|
||||
size: (vertex_size + index_size) as u64,
|
||||
},
|
||||
},
|
||||
dst: resources::BufferSlice {
|
||||
buffer: resources::Buffer(index_buffer.id),
|
||||
range: resources::BufferRange {
|
||||
offset: 0,
|
||||
size: index_size as u64,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
cmd.push(commands::Copy {
|
||||
src: resources::BufferSlice {
|
||||
buffer: resources::Buffer(staging.id),
|
||||
range: resources::BufferRange {
|
||||
offset: (vertex_size + index_size) as u64,
|
||||
size: draw_calls_size as u64,
|
||||
},
|
||||
},
|
||||
dst: resources::BufferSlice {
|
||||
buffer: resources::Buffer(indirect_buffer.id),
|
||||
range: resources::BufferRange {
|
||||
offset: 0,
|
||||
size: draw_calls_size as u64,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
cmd.push(commands::Copy {
|
||||
src: resources::BufferSlice {
|
||||
buffer: resources::Buffer(staging.id),
|
||||
range: resources::BufferRange {
|
||||
offset: (vertex_size + index_size + draw_calls_size) as u64,
|
||||
size: textures_indices_size as u64,
|
||||
},
|
||||
},
|
||||
dst: resources::BufferSlice {
|
||||
buffer: resources::Buffer(texture_indices.id),
|
||||
range: resources::BufferRange {
|
||||
offset: 0,
|
||||
size: textures_indices_size as u64,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
let mut pass_cmd = cmd.begin_rendering(
|
||||
vec![resources::TextureRegion {
|
||||
texture: resources::Texture(render_target),
|
||||
range: resources::TextureRange {
|
||||
aspect: vk::ImageAspectFlags::COLOR,
|
||||
mip_levels: (0..).into(),
|
||||
array_layers: (0..).into(),
|
||||
origin: (0, 0, 0),
|
||||
extent: (extent.0, extent.1, 1),
|
||||
},
|
||||
}],
|
||||
None,
|
||||
None,
|
||||
extent,
|
||||
1,
|
||||
);
|
||||
|
||||
pass_cmd.push(commands::SetScissor {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: extent.0,
|
||||
height: extent.1,
|
||||
});
|
||||
pass_cmd.push(commands::SetViewport {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
width: extent.0 as f32,
|
||||
height: extent.1 as f32,
|
||||
min_depth: 0.0,
|
||||
max_depth: 1.0,
|
||||
});
|
||||
|
||||
fn factory<T>() -> T {
|
||||
unimplemented!()
|
||||
}
|
||||
pass_cmd.push(commands::BindPipeline(
|
||||
pipeline.raw(),
|
||||
pipeline.bind_point(),
|
||||
));
|
||||
pass_cmd.push(commands::BindDescriptorSets {
|
||||
pipeline_layout: pipeline.layout().raw(),
|
||||
sets: vec![descriptor],
|
||||
first_set: 0,
|
||||
bind_point: vk::PipelineBindPoint::GRAPHICS,
|
||||
});
|
||||
pass_cmd.push(commands::PushConstants {
|
||||
pipeline_layout: pipeline.layout().raw(),
|
||||
stage_flags: vk::ShaderStageFlags::VERTEX,
|
||||
offset: 0,
|
||||
data: bytemuck::pod_collect_to_vec(
|
||||
&[extent.0 as f32, extent.1 as f32].map(f32::to_bits),
|
||||
),
|
||||
});
|
||||
pass_cmd.push(commands::Draw {
|
||||
data: commands::DrawIndexedIndirectData {
|
||||
indirect_buffer: resources::Buffer(indirect_buffer.id).full_slice(),
|
||||
count: draw_calls.len() as u32,
|
||||
stride: size_of::<DrawCall>() as u32,
|
||||
},
|
||||
vertex_buffers: vec![resources::BufferSlice {
|
||||
buffer: resources::Buffer(vertex_buffer.id),
|
||||
range: resources::BufferRange {
|
||||
offset: 0,
|
||||
size: vertex_size as u64,
|
||||
},
|
||||
}],
|
||||
index_buffer: Some((
|
||||
resources::BufferSlice {
|
||||
buffer: resources::Buffer(index_buffer.id),
|
||||
range: resources::BufferRange {
|
||||
offset: 0,
|
||||
size: index_size as u64,
|
||||
},
|
||||
},
|
||||
commands::IndexFormat::Uint32,
|
||||
)),
|
||||
});
|
||||
|
||||
pass_cmd.finalise();
|
||||
|
||||
cmd
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue