whoops, forgor this file

This commit is contained in:
janis 2026-04-12 21:39:28 +02:00
parent 3c6baa591d
commit 8ccdfad42a
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8

View 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
}
}