iiiiiii dooooooooont know.......

This commit is contained in:
janis 2026-04-17 20:35:04 +02:00
parent 30fc9f9f44
commit c20a4fa1a3
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
4 changed files with 305 additions and 450 deletions

View file

@ -12,6 +12,8 @@
//! recorded sequentially, in the order they were inserted into a command //! recorded sequentially, in the order they were inserted into a command
//! buffer. During command insertion //! buffer. During command insertion
use std::marker::PhantomData;
use crate::{ use crate::{
device::DeviceOwned, device::DeviceOwned,
render_graph::recorder::{CommandRecorder, SideEffectMap}, render_graph::recorder::{CommandRecorder, SideEffectMap},
@ -21,6 +23,7 @@ use super::resources::*;
pub struct ImportResource<T: Resource> { pub struct ImportResource<T: Resource> {
pub resource: T, pub resource: T,
pub range: Option<Subresource>,
pub access: vk::AccessFlags2, pub access: vk::AccessFlags2,
pub stage: vk::PipelineStageFlags2, pub stage: vk::PipelineStageFlags2,
pub layout: Option<vk::ImageLayout>, pub layout: Option<vk::ImageLayout>,
@ -28,12 +31,9 @@ pub struct ImportResource<T: Resource> {
impl<T: Resource> Command for ImportResource<T> { impl<T: Resource> Command for ImportResource<T> {
fn side_effects(&self, mut map: SideEffectMap) { fn side_effects(&self, mut map: SideEffectMap) {
self.resource let range = self.range.unwrap_or_else(|| self.resource.full_range());
.side_effect(map.reborrow().into_side_effect_map2( map.with(self.stage, self.access, self.layout)
self.stage, .insert_range(self.resource.id(), range);
self.access,
self.layout,
));
} }
fn apply(self, _recorder: &mut CommandRecorder) { fn apply(self, _recorder: &mut CommandRecorder) {
@ -55,16 +55,16 @@ impl<T: AsRef<[BufferRows]>> BufferImageBufferCopyRegion for T {
} }
} }
pub trait ImageCopyRegion { pub trait ImageCopyRegion<T: IntoImageSubresourceRange> {
fn regions(&self) -> &[TextureRegion]; fn regions(&self) -> &[TextureRegion<T>];
} }
impl ImageCopyRegion for TextureRegion { impl<T: IntoImageSubresourceRange> ImageCopyRegion<T> for TextureRegion<T> {
fn regions(&self) -> &[TextureRegion] { fn regions(&self) -> &[TextureRegion<T>] {
core::slice::from_ref(self) core::slice::from_ref(self)
} }
} }
impl<T: AsRef<[TextureRegion]>> ImageCopyRegion for T { impl<U: IntoImageSubresourceRange, T: AsRef<[TextureRegion<U>]>> ImageCopyRegion<U> for T {
fn regions(&self) -> &[TextureRegion] { fn regions(&self) -> &[TextureRegion<U>] {
self.as_ref() self.as_ref()
} }
} }
@ -90,39 +90,43 @@ pub struct CopyBuffers<T: BufferCopyRegion> {
pub dst_region: T, pub dst_region: T,
} }
pub struct CopyTextures<T: ImageCopyRegion> { pub struct CopyTextures<T: ImageCopyRegion<R>, R: IntoImageSubresourceRange> {
pub src: Texture, pub src: Texture,
pub src_region: T, pub src_region: T,
pub dst: Texture, pub dst: Texture,
pub dst_region: T, pub dst_region: T,
_pd: PhantomData<R>,
} }
pub struct CopyBufferToTexture<T: BufferImageBufferCopyRegion, U: ImageCopyRegion> { pub struct CopyBufferToTexture<
T: BufferImageBufferCopyRegion,
U: ImageCopyRegion<R>,
R: IntoImageSubresourceLayers,
> {
pub src: Buffer, pub src: Buffer,
pub src_region: T, pub src_region: T,
pub dst: Texture, pub dst: Texture,
pub dst_region: U, pub dst_region: U,
_pd: PhantomData<R>,
} }
pub struct CopyTextureToBuffer<T: ImageCopyRegion, U: BufferImageBufferCopyRegion> { pub struct CopyTextureToBuffer<
T: ImageCopyRegion<R>,
U: BufferImageBufferCopyRegion,
R: IntoImageSubresourceLayers,
> {
pub src: Texture, pub src: Texture,
pub src_region: T, pub src_region: T,
pub dst: Buffer, pub dst: Buffer,
pub dst_region: U, pub dst_region: U,
_pd: PhantomData<R>,
} }
fn copy_side_effects_inner<T, U>(_src: &T, _dst: &U, _map: SideEffectMap) impl<T, U, R> Command for CopyBufferToTexture<T, U, R>
where
T: Resource,
U: Resource,
{
unimplemented!()
}
impl<T, U> Command for CopyBufferToTexture<T, U>
where where
T: BufferImageBufferCopyRegion, T: BufferImageBufferCopyRegion,
U: ImageCopyRegion, U: ImageCopyRegion<R>,
R: IntoImageSubresourceLayers,
{ {
fn side_effects(&self, mut map: SideEffectMap) { fn side_effects(&self, mut map: SideEffectMap) {
let block_size = self.dst.format().block_size() as u64; let block_size = self.dst.format().block_size() as u64;
@ -170,7 +174,7 @@ where
vk::AccessFlags2::TRANSFER_WRITE, vk::AccessFlags2::TRANSFER_WRITE,
Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL), Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL),
) )
.insert_range(dst_id, dst_region.range); .insert_range(dst_id, dst_region.range.into_range());
} }
} }
@ -190,13 +194,7 @@ where
.buffer_image_height(src_region.row_count) .buffer_image_height(src_region.row_count)
.image_offset(dst_region.offset) .image_offset(dst_region.offset)
.image_extent(dst_region.extent) .image_extent(dst_region.extent)
.image_subresource( .image_subresource(dst_region.range.into_layers())
vk::ImageSubresourceLayers::default()
.aspect_mask(dst_region.range.aspect)
.mip_level(dst_region.range.mip_level)
.base_array_layer(dst_region.range.array_layers.start())
.layer_count(dst_region.range.array_layers.len()),
)
}) })
.collect::<Box<[_]>>(); .collect::<Box<[_]>>();
@ -212,10 +210,11 @@ where
} }
} }
impl<T, U> Command for CopyTextureToBuffer<T, U> impl<T, U, R> Command for CopyTextureToBuffer<T, U, R>
where where
T: ImageCopyRegion, T: ImageCopyRegion<R>,
U: BufferImageBufferCopyRegion, U: BufferImageBufferCopyRegion,
R: IntoImageSubresourceLayers,
{ {
fn side_effects(&self, mut map: SideEffectMap) { fn side_effects(&self, mut map: SideEffectMap) {
let block_size = self.src.format().block_size() as u64; let block_size = self.src.format().block_size() as u64;
@ -250,7 +249,7 @@ where
vk::AccessFlags2::TRANSFER_READ, vk::AccessFlags2::TRANSFER_READ,
Some(vk::ImageLayout::TRANSFER_SRC_OPTIMAL), Some(vk::ImageLayout::TRANSFER_SRC_OPTIMAL),
) )
.insert_range(dst_id, src_region.range); .insert_range(dst_id, src_region.range.into_range());
map.with( map.with(
vk::PipelineStageFlags2::COPY, vk::PipelineStageFlags2::COPY,
@ -283,13 +282,7 @@ where
.buffer_image_height(dst_region.row_count) .buffer_image_height(dst_region.row_count)
.image_offset(src_region.offset) .image_offset(src_region.offset)
.image_extent(src_region.extent) .image_extent(src_region.extent)
.image_subresource( .image_subresource(src_region.range.into_layers())
vk::ImageSubresourceLayers::default()
.aspect_mask(src_region.range.aspect)
.mip_level(src_region.range.mip_level)
.base_array_layer(src_region.range.array_layers.start())
.layer_count(src_region.range.array_layers.len()),
)
}) })
.collect::<Box<[_]>>(); .collect::<Box<[_]>>();
@ -357,9 +350,10 @@ where
} }
} }
impl<T> Command for CopyTextures<T> impl<T, R> Command for CopyTextures<T, R>
where where
T: ImageCopyRegion, T: ImageCopyRegion<R>,
R: IntoImageSubresourceLayers,
{ {
fn side_effects(&self, mut map: SideEffectMap) { fn side_effects(&self, mut map: SideEffectMap) {
for region in self.src_region.regions() { for region in self.src_region.regions() {
@ -368,7 +362,7 @@ where
vk::AccessFlags2::TRANSFER_READ, vk::AccessFlags2::TRANSFER_READ,
None, None,
) )
.insert_range(self.src.id(), region.range); .insert_range(self.src.id(), region.range.into_range());
} }
for region in self.dst_region.regions() { for region in self.dst_region.regions() {
@ -377,7 +371,7 @@ where
vk::AccessFlags2::TRANSFER_WRITE, vk::AccessFlags2::TRANSFER_WRITE,
None, None,
) )
.insert_range(self.dst.id(), region.range); .insert_range(self.dst.id(), region.range.into_range());
} }
} }
@ -393,9 +387,9 @@ where
.map(|(src_region, dst_region)| { .map(|(src_region, dst_region)| {
vk::ImageCopy2::default() vk::ImageCopy2::default()
.src_offset(src_region.offset) .src_offset(src_region.offset)
.src_subresource(src_region.range.into()) .src_subresource(src_region.range.into_layers())
.dst_offset(dst_region.offset) .dst_offset(dst_region.offset)
.dst_subresource(dst_region.range.into()) .dst_subresource(dst_region.range.into_layers())
.extent(src_region.extent) .extent(src_region.extent)
}) })
.collect::<Box<[_]>>(); .collect::<Box<[_]>>();
@ -413,20 +407,20 @@ where
} }
} }
pub struct ClearTexture { pub struct ClearTexture<R: IntoImageSubresourceRange> {
pub dst: Texture, pub dst: Texture,
pub dst_region: TextureRegion, pub dst_region: TextureRegion<R>,
pub clear_value: [f32; 4], pub clear_value: [f32; 4],
} }
impl Command for ClearTexture { impl<R: IntoImageSubresourceRange> Command for ClearTexture<R> {
fn side_effects(&self, mut map: SideEffectMap) { fn side_effects(&self, mut map: SideEffectMap) {
map.with( map.with(
vk::PipelineStageFlags2::CLEAR, vk::PipelineStageFlags2::CLEAR,
vk::AccessFlags2::TRANSFER_WRITE, vk::AccessFlags2::TRANSFER_WRITE,
Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL), Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL),
) )
.insert_range(self.dst.id(), self.dst_region.range); .insert_range(self.dst.id(), self.dst_region.range.into_range());
} }
fn apply(self, recorder: &mut CommandRecorder) { fn apply(self, recorder: &mut CommandRecorder) {
@ -443,33 +437,43 @@ impl Command for ClearTexture {
recorder.get_image_handle(self.dst.id()), recorder.get_image_handle(self.dst.id()),
vk::ImageLayout::TRANSFER_DST_OPTIMAL, vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&values, &values,
&[self.dst_region.range.into()], &[self.dst_region.range.into_range()],
); );
} }
} }
} }
pub struct UpdateBuffer { pub struct UpdateBuffer {
pub dst: Write<BufferSlice>, pub dst: Buffer,
pub dst_region: BufferRange,
pub data: Vec<u8>, pub data: Vec<u8>,
} }
impl Command for UpdateBuffer { impl Command for UpdateBuffer {
fn side_effects(&self, mut map: SideEffectMap) { fn side_effects(&self, mut map: SideEffectMap) {
self.dst.side_effect(map.reborrow().into_side_effect_map2( map.with(
vk::PipelineStageFlags2::TRANSFER, vk::PipelineStageFlags2::TRANSFER,
vk::AccessFlags2::TRANSFER_WRITE, vk::AccessFlags2::TRANSFER_WRITE,
None, None,
)); )
.insert_range(self.dst.id(), self.dst_region);
} }
fn apply(self, _recorder: &mut CommandRecorder) {} fn apply(self, _recorder: &mut CommandRecorder) {}
} }
pub struct RenderAttachment {
pub texture: Texture,
pub region: vk::ImageSubresourceRange,
pub layout: vk::ImageLayout,
pub load_op: vk::AttachmentLoadOp,
pub store_op: vk::AttachmentStoreOp,
}
pub struct BeginRendering { pub struct BeginRendering {
pub color_attachments: Vec<TextureRegion>, pub color_attachments: Vec<RenderAttachment>,
pub depth_attachment: Option<TextureRegion>, pub depth_attachment: Option<RenderAttachment>,
pub stencil_attachment: Option<TextureRegion>, pub stencil_attachment: Option<RenderAttachment>,
pub area: (u32, u32), pub area: (u32, u32),
pub layers: u32, pub layers: u32,
} }
@ -482,26 +486,40 @@ impl Command for BeginRendering {
// pass instance referencing framebuffer-local stages must contain // pass instance referencing framebuffer-local stages must contain
// only framebuffer-local stages. // only framebuffer-local stages.
// TODO: consider loadop and storeop? map.with(
attachment.side_effect(map.reborrow().into_side_effect_map2(
vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT, vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT,
vk::AccessFlags2::COLOR_ATTACHMENT_READ, if attachment.load_op == vk::AttachmentLoadOp::LOAD {
Some(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL), vk::AccessFlags2::COLOR_ATTACHMENT_READ
)); } else {
vk::AccessFlags2::empty()
},
Some(attachment.layout),
)
.insert_range(attachment.texture.id(), attachment.region);
} }
if let Some(depth) = &self.depth_attachment { if let Some(depth) = &self.depth_attachment {
depth.side_effect(map.reborrow().into_side_effect_map2( map.with(
vk::PipelineStageFlags2::EARLY_FRAGMENT_TESTS, vk::PipelineStageFlags2::EARLY_FRAGMENT_TESTS,
vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_READ, if depth.load_op == vk::AttachmentLoadOp::LOAD {
Some(vk::ImageLayout::DEPTH_ATTACHMENT_OPTIMAL), vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_READ
)); } else {
vk::AccessFlags2::empty()
},
Some(depth.layout),
)
.insert_range(depth.texture.id(), depth.region);
} }
if let Some(stencil) = &self.stencil_attachment { if let Some(stencil) = &self.stencil_attachment {
stencil.side_effect(map.reborrow().into_side_effect_map2( map.with(
vk::PipelineStageFlags2::EARLY_FRAGMENT_TESTS, vk::PipelineStageFlags2::EARLY_FRAGMENT_TESTS,
vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_READ, if stencil.load_op == vk::AttachmentLoadOp::LOAD {
Some(vk::ImageLayout::STENCIL_ATTACHMENT_OPTIMAL), vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_READ
)); } else {
vk::AccessFlags2::empty()
},
Some(stencil.layout),
)
.insert_range(stencil.texture.id(), stencil.region);
} }
} }
@ -512,7 +530,7 @@ pub struct EndRendering;
impl Command for EndRendering { impl Command for EndRendering {
fn side_effects(&self, _map: SideEffectMap) { fn side_effects(&self, _map: SideEffectMap) {
// No resource access, but ends the render pass // TODO: need the beginrendering struct to declare the store-op dependencies.
} }
fn apply(self, _recorder: &mut CommandRecorder) {} fn apply(self, _recorder: &mut CommandRecorder) {}
@ -543,11 +561,12 @@ pub struct BindVertexBuffers {
impl Command for BindVertexBuffers { impl Command for BindVertexBuffers {
fn side_effects(&self, mut map: SideEffectMap) { fn side_effects(&self, mut map: SideEffectMap) {
for buffer in &self.buffers { for buffer in &self.buffers {
buffer.side_effect(map.reborrow().into_side_effect_map2( map.with(
vk::PipelineStageFlags2::VERTEX_ATTRIBUTE_INPUT, vk::PipelineStageFlags2::VERTEX_ATTRIBUTE_INPUT,
vk::AccessFlags2::VERTEX_ATTRIBUTE_READ, vk::AccessFlags2::VERTEX_ATTRIBUTE_READ,
None, None,
)); )
.insert_range(buffer.id(), buffer.range);
} }
} }
@ -577,11 +596,12 @@ pub struct BindIndexBuffer(pub BufferSlice, pub IndexFormat);
impl Command for BindIndexBuffer { impl Command for BindIndexBuffer {
fn side_effects(&self, mut map: SideEffectMap) { fn side_effects(&self, mut map: SideEffectMap) {
self.0.side_effect(map.reborrow().into_side_effect_map2( map.with(
vk::PipelineStageFlags2::INDEX_INPUT, vk::PipelineStageFlags2::INDEX_INPUT,
vk::AccessFlags2::INDEX_READ, vk::AccessFlags2::INDEX_READ,
None, None,
)); )
.insert_range(self.0.id(), self.0.range);
} }
fn apply(self, recorder: &mut CommandRecorder) { fn apply(self, recorder: &mut CommandRecorder) {
@ -726,27 +746,11 @@ pub enum IndexFormat {
pub struct Draw<T: IsDrawData> { pub struct Draw<T: IsDrawData> {
pub data: T, pub data: T,
pub vertex_buffers: Vec<BufferSlice>,
pub index_buffer: Option<(BufferSlice, IndexFormat)>,
} }
impl<T: IsDrawData> Command for Draw<T> { impl<T: IsDrawData> Command for Draw<T> {
fn side_effects(&self, mut map: SideEffectMap) { fn side_effects(&self, mut map: SideEffectMap) {
self.data.side_effects(map.reborrow()); self.data.side_effects(map.reborrow());
for vertex_buffer in &self.vertex_buffers {
vertex_buffer.side_effect(map.reborrow().into_side_effect_map2(
vk::PipelineStageFlags2::VERTEX_ATTRIBUTE_INPUT,
vk::AccessFlags2::VERTEX_ATTRIBUTE_READ,
None,
));
}
if let Some((index_buffer, _)) = &self.index_buffer {
index_buffer.side_effect(map.reborrow().into_side_effect_map2(
vk::PipelineStageFlags2::INDEX_INPUT,
vk::AccessFlags2::INDEX_READ,
None,
));
}
} }
fn apply(self, _recorder: &mut CommandRecorder) {} fn apply(self, _recorder: &mut CommandRecorder) {}
@ -782,29 +786,28 @@ impl IsDrawData for DrawData {}
impl IsDrawData for DrawIndexedData {} impl IsDrawData for DrawIndexedData {}
impl IsDrawData for DrawIndirectData { impl IsDrawData for DrawIndirectData {
fn side_effects(&self, mut map: SideEffectMap) { fn side_effects(&self, mut map: SideEffectMap) {
self.indirect_buffer map.with(
.side_effect(map.reborrow().into_side_effect_map2( vk::PipelineStageFlags2::DRAW_INDIRECT,
vk::PipelineStageFlags2::DRAW_INDIRECT, vk::AccessFlags2::INDIRECT_COMMAND_READ,
vk::AccessFlags2::INDIRECT_COMMAND_READ, None,
None, )
)); .insert_range(self.indirect_buffer.id(), self.indirect_buffer.range);
} }
} }
impl IsDrawData for DrawIndexedIndirectData { impl IsDrawData for DrawIndexedIndirectData {
fn side_effects(&self, mut map: SideEffectMap) { fn side_effects(&self, mut map: SideEffectMap) {
self.indirect_buffer map.with(
.side_effect(map.reborrow().into_side_effect_map2( vk::PipelineStageFlags2::DRAW_INDIRECT,
vk::PipelineStageFlags2::DRAW_INDIRECT, vk::AccessFlags2::INDIRECT_COMMAND_READ,
vk::AccessFlags2::INDIRECT_COMMAND_READ, None,
None, )
)); .insert_range(self.indirect_buffer.id(), self.indirect_buffer.range);
} }
} }
impl OutsideRenderPass for BeginRendering {} impl OutsideRenderPass for BeginRendering {}
impl InsideRenderPass for EndRendering {} impl InsideRenderPass for EndRendering {}
impl<T: Resource, U: Resource> OutsideRenderPass for Copy<T, U> {} impl<T: IntoImageSubresourceRange> OutsideRenderPass for ClearTexture<T> {}
impl OutsideRenderPass for ClearTexture {}
impl OutsideRenderPass for UpdateBuffer {} impl OutsideRenderPass for UpdateBuffer {}
impl InsideRenderPass for BindPipeline {} impl InsideRenderPass for BindPipeline {}

View file

@ -80,7 +80,11 @@ impl<'r> GraphBuilder<'r> {
mod api_demo { mod api_demo {
use crate::{EguiState, pipeline::Pipeline, render_graph::commands}; use crate::{
EguiState,
pipeline::Pipeline,
render_graph::{commands, resources::TextureRegion},
};
use super::*; use super::*;
use ash::vk::{self, BufferUsageFlags}; use ash::vk::{self, BufferUsageFlags};
@ -180,84 +184,86 @@ mod api_demo {
); );
let mut cmd = builder.make_command_list(); let mut cmd = builder.make_command_list();
cmd.push(commands::Copy { // cmd.push(commands::Copy {
src: resources::BufferSlice { // src: resources::BufferSlice {
buffer: resources::Buffer(staging.id), // buffer: resources::Buffer(staging.id),
range: resources::BufferRange { // range: resources::BufferRange {
offset: 0, // offset: 0,
size: vertex_size as u64, // size: vertex_size as u64,
}, // },
}, // },
dst: resources::BufferSlice { // dst: resources::BufferSlice {
buffer: resources::Buffer(vertex_buffer.id), // buffer: resources::Buffer(vertex_buffer.id),
range: resources::BufferRange { // range: resources::BufferRange {
offset: 0, // offset: 0,
size: vertex_size as u64, // size: vertex_size as u64,
}, // },
}, // },
}); // });
cmd.push(commands::Copy { // cmd.push(commands::Copy {
src: resources::BufferSlice { // src: resources::BufferSlice {
buffer: resources::Buffer(staging.id), // buffer: resources::Buffer(staging.id),
range: resources::BufferRange { // range: resources::BufferRange {
offset: vertex_size as u64, // offset: vertex_size as u64,
size: (vertex_size + index_size) as u64, // size: (vertex_size + index_size) as u64,
}, // },
}, // },
dst: resources::BufferSlice { // dst: resources::BufferSlice {
buffer: resources::Buffer(index_buffer.id), // buffer: resources::Buffer(index_buffer.id),
range: resources::BufferRange { // range: resources::BufferRange {
offset: 0, // offset: 0,
size: index_size as u64, // size: index_size as u64,
}, // },
}, // },
}); // });
cmd.push(commands::Copy { // cmd.push(commands::Copy {
src: resources::BufferSlice { // src: resources::BufferSlice {
buffer: resources::Buffer(staging.id), // buffer: resources::Buffer(staging.id),
range: resources::BufferRange { // range: resources::BufferRange {
offset: (vertex_size + index_size) as u64, // offset: (vertex_size + index_size) as u64,
size: draw_calls_size as u64, // size: draw_calls_size as u64,
}, // },
}, // },
dst: resources::BufferSlice { // dst: resources::BufferSlice {
buffer: resources::Buffer(indirect_buffer.id), // buffer: resources::Buffer(indirect_buffer.id),
range: resources::BufferRange { // range: resources::BufferRange {
offset: 0, // offset: 0,
size: draw_calls_size as u64, // size: draw_calls_size as u64,
}, // },
}, // },
}); // });
cmd.push(commands::Copy { // cmd.push(commands::Copy {
src: resources::BufferSlice { // src: resources::BufferSlice {
buffer: resources::Buffer(staging.id), // buffer: resources::Buffer(staging.id),
range: resources::BufferRange { // range: resources::BufferRange {
offset: (vertex_size + index_size + draw_calls_size) as u64, // offset: (vertex_size + index_size + draw_calls_size) as u64,
size: textures_indices_size as u64, // size: textures_indices_size as u64,
}, // },
}, // },
dst: resources::BufferSlice { // dst: resources::BufferSlice {
buffer: resources::Buffer(texture_indices.id), // buffer: resources::Buffer(texture_indices.id),
range: resources::BufferRange { // range: resources::BufferRange {
offset: 0, // offset: 0,
size: textures_indices_size as u64, // size: textures_indices_size as u64,
}, // },
}, // },
}); // });
let mut pass_cmd = cmd.begin_rendering( let mut pass_cmd = cmd.begin_rendering(
vec![resources::TextureRegion { vec![commands::RenderAttachment {
texture: resources::Texture(render_target), texture: resources::Texture(render_target),
range: resources::TextureRange { region: vk::ImageSubresourceRange::default()
aspect: vk::ImageAspectFlags::COLOR, .aspect_mask(vk::ImageAspectFlags::COLOR)
mip_levels: (0..).into(), .base_mip_level(0)
array_layers: (0..).into(), .level_count(1)
origin: (0, 0, 0), .base_array_layer(0)
extent: (extent.0, extent.1, 1), .layer_count(1),
}, layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
load_op: vk::AttachmentLoadOp::LOAD,
store_op: vk::AttachmentStoreOp::STORE,
}], }],
None, None,
None, None,
@ -301,29 +307,32 @@ mod api_demo {
&[extent.0 as f32, extent.1 as f32].map(f32::to_bits), &[extent.0 as f32, extent.1 as f32].map(f32::to_bits),
), ),
}); });
pass_cmd.push(commands::Draw { pass_cmd.push(commands::BindVertexBuffers {
data: commands::DrawIndexedIndirectData { buffers: vec![resources::BufferSlice {
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), buffer: resources::Buffer(vertex_buffer.id),
range: resources::BufferRange { range: resources::BufferRange {
offset: 0, offset: 0,
size: vertex_size as u64, size: vertex_size as u64,
}, },
}], }],
index_buffer: Some(( first_binding: 0,
resources::BufferSlice { });
buffer: resources::Buffer(index_buffer.id), pass_cmd.push(commands::BindIndexBuffer(
range: resources::BufferRange { resources::BufferSlice {
offset: 0, buffer: resources::Buffer(index_buffer.id),
size: index_size as u64, range: resources::BufferRange {
}, offset: 0,
size: index_size as u64,
}, },
commands::IndexFormat::Uint32, },
)), commands::IndexFormat::Uint32,
));
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,
},
}); });
pass_cmd.finalise(); pass_cmd.finalise();

View file

@ -11,7 +11,7 @@ use crate::{
commands::CommandBuffer, commands::CommandBuffer,
images::ImageDesc, images::ImageDesc,
render_graph::{ render_graph::{
commands::{Command, InsideRenderPass, OutsideRenderPass}, commands::{Command, InsideRenderPass, OutsideRenderPass, RenderAttachment},
resources::{ resources::{
ResourceId, Subresource, SubresourceScope, SubresourceScopeInner, TextureRegion, ResourceId, Subresource, SubresourceScope, SubresourceScopeInner, TextureRegion,
}, },
@ -83,6 +83,12 @@ impl<T> VecOrSingle<T> {
VecOrSingle::Single(item) => core::slice::from_ref::<T>(item).iter(), VecOrSingle::Single(item) => core::slice::from_ref::<T>(item).iter(),
} }
} }
fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> {
match self {
VecOrSingle::Vec(items) => items.as_mut_slice().iter_mut(),
VecOrSingle::Single(item) => core::slice::from_mut::<T>(item).iter_mut(),
}
}
} }
#[derive(Default)] #[derive(Default)]
@ -94,13 +100,35 @@ struct SideEffects {
pub struct SideEffectMap<'a>(&'a mut SideEffects, u32); pub struct SideEffectMap<'a>(&'a mut SideEffects, u32);
impl<'a> SideEffectMap<'a> { impl<'a> SideEffectMap<'a> {
pub fn insert(&mut self, id: ResourceId, scope: SubresourceScope) { pub fn insert(&mut self, id: ResourceId, new_scope: SubresourceScope) {
self.0.resources.insert(id); self.0.resources.insert(id);
self.0
.map 'inserted: {
.entry((id, self.1)) 'outer: for ((_rid, _cid), scopes) in self.0.map.range_mut((id, 0)..=(id, self.1)).rev()
.and_modify(|entry| entry.push(scope)) {
.or_insert_with(|| scope.into()); for scope in scopes.iter_mut().rev() {
if scope.try_merge(&new_scope) {
// if we can fold this scope with a previous one, we can
// stop iterating, as the barrier already exists if
// needed
break 'inserted;
} else if scope.conflicts(&new_scope) {
// if this scope conflicts with a previous one, we need
// to insert a barrier before the current command index;
// we can stop iterating, as we can no longer fold into
// any scopes before this conflict
break 'outer;
}
}
}
// if we couldn't fold this scope with any previous one, add it as a new entry
self.0
.map
.entry((id, self.1))
.and_modify(|entry| entry.push(new_scope))
.or_insert_with(|| new_scope.into());
}
} }
pub fn reborrow(&mut self) -> SideEffectMap<'_> { pub fn reborrow(&mut self) -> SideEffectMap<'_> {
@ -219,9 +247,9 @@ impl<'cmd> CommandList<'cmd> {
pub fn begin_rendering( pub fn begin_rendering(
&mut self, &mut self,
color_attachments: Vec<TextureRegion>, color_attachments: Vec<RenderAttachment>,
depth_attachment: Option<TextureRegion>, depth_attachment: Option<RenderAttachment>,
stencil_attachment: Option<TextureRegion>, stencil_attachment: Option<RenderAttachment>,
area: (u32, u32), area: (u32, u32),
layers: u32, layers: u32,
) -> RenderPass<'cmd, '_> { ) -> RenderPass<'cmd, '_> {

View file

@ -6,7 +6,7 @@ use crate::{images::MipRange, render_graph::recorder::SideEffectMap2};
pub trait Resource: Sized { pub trait Resource: Sized {
fn id(&self) -> ResourceId; fn id(&self) -> ResourceId;
fn side_effect(&self, map: SideEffectMap2); fn full_range(&self) -> Subresource;
} }
mod sealed { mod sealed {
@ -28,7 +28,27 @@ pub use sealed::{Buffer as AsBuffer, Texture as AsTexture};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Subresource { pub enum Subresource {
Buffer(BufferRange), Buffer(BufferRange),
Texture(TextureRange), Texture(vk::ImageSubresourceRange),
}
impl Subresource {
pub fn full_buffer() -> Self {
Self::Buffer(BufferRange {
offset: 0,
size: vk::WHOLE_SIZE,
})
}
pub fn full_texture(format: vk::Format) -> Self {
use ash_formats::FormatExt;
Self::Texture(vk::ImageSubresourceRange {
aspect_mask: format.aspect_flags(),
base_mip_level: 0,
level_count: vk::REMAINING_MIP_LEVELS,
base_array_layer: 0,
layer_count: vk::REMAINING_ARRAY_LAYERS,
})
}
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -44,7 +64,7 @@ pub enum SubresourceScopeInner {
subresource: BufferRange, subresource: BufferRange,
}, },
Texture { Texture {
subresource: TextureRange, subresource: vk::ImageSubresourceRange,
layout: vk::ImageLayout, layout: vk::ImageLayout,
}, },
} }
@ -94,18 +114,18 @@ impl SubresourceScope {
// think), however: if a previous access requires a less general // think), however: if a previous access requires a less general
// barrier, then is it better to split? // barrier, then is it better to split?
let overlaps = lhs.aspect.intersects(rhs.aspect) let overlaps = lhs.aspect_mask.intersects(rhs.aspect_mask)
&& lhs.mip_levels.intersects(rhs.mip_levels) && lhs.mip_levels().intersects(rhs.mip_levels())
&& lhs.array_layers.intersects(rhs.array_layers); && lhs.layers().intersects(rhs.layers());
// non-overlapping sub-resources shouldn't be merged. // non-overlapping sub-resources shouldn't be merged.
if !overlaps { if !overlaps {
return false; return false;
} }
let lhs_contains_rhs = lhs.aspect.contains(rhs.aspect) let lhs_contains_rhs = lhs.aspect_mask.contains(rhs.aspect_mask)
&& lhs.mip_levels.contains(rhs.mip_levels) && lhs.mip_levels().contains(rhs.mip_levels())
&& lhs.array_layers.contains(rhs.array_layers); && lhs.layers().contains(rhs.layers());
// other is not a subresource of self, so we can't merge them. // other is not a subresource of self, so we can't merge them.
if !lhs_contains_rhs { if !lhs_contains_rhs {
@ -146,9 +166,9 @@ impl SubresourceScope {
) => { ) => {
// image subresource ranges overlap if they share mip levels and // image subresource ranges overlap if they share mip levels and
// array layers with the same aspects. // array layers with the same aspects.
let overlaps = lhs.aspect.intersects(rhs.aspect) let overlaps = lhs.aspect_mask.intersects(rhs.aspect_mask)
&& lhs.mip_levels.intersects(rhs.mip_levels) && lhs.mip_levels().intersects(rhs.mip_levels())
&& lhs.array_layers.intersects(rhs.array_layers); && lhs.layers().intersects(rhs.layers());
if !overlaps { if !overlaps {
return false; return false;
@ -174,8 +194,6 @@ mod impls {
use super::*; use super::*;
impl sealed::Texture for Texture {} impl sealed::Texture for Texture {}
impl sealed::Texture for TextureRegion {}
impl sealed::Texture for TextureView {}
impl sealed::Buffer for Buffer {} impl sealed::Buffer for Buffer {}
impl sealed::Buffer for BufferSlice {} impl sealed::Buffer for BufferSlice {}
@ -185,130 +203,25 @@ mod impls {
self.0 self.0
} }
fn side_effect(&self, mut map: SideEffectMap2) { fn full_range(&self) -> Subresource {
map.insert_range(self.id(), BufferRange::full()); Subresource::full_buffer()
} }
} }
impl Resource for BufferSlice { impl Resource for BufferSlice {
fn id(&self) -> ResourceId { fn id(&self) -> ResourceId {
self.buffer.id() self.buffer.id()
} }
fn side_effect(&self, mut map: SideEffectMap2) { fn full_range(&self) -> Subresource {
map.insert_range(self.id(), self.range); self.buffer.full_range()
} }
} }
impl Resource for BufferSlices {
fn id(&self) -> ResourceId {
self.buffer.id()
}
fn side_effect(&self, mut map: SideEffectMap2) {
for range in &self.ranges {
map.insert_range(self.id(), *range);
}
}
}
// TODO: the rows are not in bytes, so this is plain wrong. A BufferRowSlice needs to be generic over Buffer/BufferSlice, or commands taking a BufferRowSlice need to take the row parameters separately.
impl Resource for BufferRowSlice {
fn id(&self) -> ResourceId {
self.buffer.id()
}
fn side_effect(&self, mut map: SideEffectMap2) {
map.insert_range(
self.id(),
BufferRange {
offset: self.row.offset,
size: vk::WHOLE_SIZE,
},
);
}
}
impl Resource for BufferRowSlices {
fn id(&self) -> ResourceId {
self.buffer.id()
}
fn side_effect(&self, mut map: SideEffectMap2) {
for row in &self.rows {
map.insert_range(
self.id(),
BufferRange {
offset: row.offset,
size: vk::WHOLE_SIZE,
},
);
}
}
}
impl Resource for Texture { impl Resource for Texture {
fn id(&self) -> ResourceId { fn id(&self) -> ResourceId {
self.0 self.0
} }
fn full_range(&self) -> Subresource {
fn side_effect(&self, mut map: SideEffectMap2) { Subresource::full_texture(vk::Format::UNDEFINED)
map.insert_range(self.id(), TextureRange::full());
}
}
impl Resource for TextureRegion {
fn id(&self) -> ResourceId {
self.texture.id()
}
fn side_effect(&self, mut map: SideEffectMap2) {
map.insert_range(self.id(), self.range);
}
}
impl Resource for TextureRegions {
fn id(&self) -> ResourceId {
self.texture.id()
}
fn side_effect(&self, mut map: SideEffectMap2) {
for range in &self.ranges {
map.insert_range(self.id(), range.0);
}
}
}
impl Resource for TextureView {
fn id(&self) -> ResourceId {
self.texture.id()
}
fn side_effect(&self, mut map: SideEffectMap2) {
map.insert_range(self.id(), self.range);
}
}
impl<T: Resource> Resource for Read<T> {
fn id(&self) -> ResourceId {
self.0.id()
}
fn side_effect(&self, map: SideEffectMap2) {
self.0.side_effect(map);
}
}
impl<T: Resource> Resource for Write<T> {
fn id(&self) -> ResourceId {
self.0.id()
}
fn side_effect(&self, map: SideEffectMap2) {
self.0.side_effect(map);
}
}
impl<T: Resource> Resource for ReadWrite<T> {
fn id(&self) -> ResourceId {
self.0.id()
}
fn side_effect(&self, map: SideEffectMap2) {
self.0.side_effect(map);
} }
} }
} }
@ -368,32 +281,16 @@ pub struct BufferRows {
pub row_size: u32, pub row_size: u32,
} }
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct TextureRange {
pub aspect: vk::ImageAspectFlags,
pub mip_levels: MipRange,
pub array_layers: MipRange,
}
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct TextureLayers {
pub aspect: vk::ImageAspectFlags,
pub mip_level: u32,
pub array_layers: MipRange,
}
pub trait IntoImageSubresourceLayers { pub trait IntoImageSubresourceLayers {
fn into_layers(self) -> vk::ImageSubresourceLayers; fn into_layers(&self) -> vk::ImageSubresourceLayers;
} }
pub trait IntoImageSubresourceRange { pub trait IntoImageSubresourceRange {
fn into_range(self) -> vk::ImageSubresourceRange; fn into_range(&self) -> vk::ImageSubresourceRange;
} }
impl IntoImageSubresourceLayers for vk::ImageSubresource { impl IntoImageSubresourceLayers for vk::ImageSubresource {
fn into_layers(self) -> vk::ImageSubresourceLayers { fn into_layers(&self) -> vk::ImageSubresourceLayers {
vk::ImageSubresourceLayers { vk::ImageSubresourceLayers {
aspect_mask: self.aspect_mask, aspect_mask: self.aspect_mask,
mip_level: self.mip_level, mip_level: self.mip_level,
@ -403,20 +300,17 @@ impl IntoImageSubresourceLayers for vk::ImageSubresource {
} }
} }
impl IntoImageSubresourceRange for vk::ImageSubresource { impl<T> IntoImageSubresourceRange for T
fn into_range(self) -> vk::ImageSubresourceRange { where
vk::ImageSubresourceRange { T: IntoImageSubresourceLayers,
aspect_mask: self.aspect_mask, {
base_mip_level: self.mip_level, fn into_range(&self) -> vk::ImageSubresourceRange {
level_count: 1, self.into_layers().into_range()
base_array_layer: self.array_layer,
layer_count: 1,
}
} }
} }
impl IntoImageSubresourceRange for vk::ImageSubresourceLayers { impl IntoImageSubresourceRange for vk::ImageSubresourceLayers {
fn into_range(self) -> vk::ImageSubresourceRange { fn into_range(&self) -> vk::ImageSubresourceRange {
vk::ImageSubresourceRange { vk::ImageSubresourceRange {
aspect_mask: self.aspect_mask, aspect_mask: self.aspect_mask,
base_mip_level: self.mip_level, base_mip_level: self.mip_level,
@ -427,6 +321,12 @@ impl IntoImageSubresourceRange for vk::ImageSubresourceLayers {
} }
} }
impl IntoImageSubresourceRange for vk::ImageSubresourceRange {
fn into_range(&self) -> vk::ImageSubresourceRange {
*self
}
}
pub trait ImageSubresourceExt { pub trait ImageSubresourceExt {
fn aspects(self) -> vk::ImageAspectFlags; fn aspects(self) -> vk::ImageAspectFlags;
fn layers(self) -> MipRange; fn layers(self) -> MipRange;
@ -478,63 +378,8 @@ impl ImageSubresourceExt for vk::ImageSubresource {
} }
} }
impl From<TextureLayers> for vk::ImageSubresourceLayers { impl From<vk::ImageSubresourceRange> for Subresource {
fn from(value: TextureLayers) -> Self { fn from(value: vk::ImageSubresourceRange) -> Self {
vk::ImageSubresourceLayers {
aspect_mask: value.aspect,
mip_level: value.mip_level,
base_array_layer: value.array_layers.start,
layer_count: value.array_layers.end - value.array_layers.start,
}
}
}
impl From<TextureLayers> for vk::ImageSubresourceRange {
fn from(value: TextureLayers) -> Self {
vk::ImageSubresourceRange {
aspect_mask: value.aspect,
base_mip_level: value.mip_level,
level_count: 1,
base_array_layer: value.array_layers.start,
layer_count: value.array_layers.end - value.array_layers.start,
}
}
}
impl From<TextureRange> for vk::ImageSubresourceRange {
fn from(value: TextureRange) -> Self {
vk::ImageSubresourceRange {
aspect_mask: value.aspect,
base_mip_level: value.mip_levels.start,
level_count: value.mip_levels.end - value.mip_levels.start,
base_array_layer: value.array_layers.start,
layer_count: value.array_layers.end - value.array_layers.start,
}
}
}
impl From<TextureLayers> for TextureRange {
fn from(value: TextureLayers) -> Self {
Self {
aspect: value.aspect,
mip_levels: MipRange::single(value.mip_level),
array_layers: value.array_layers,
}
}
}
impl From<TextureLayers> for Subresource {
fn from(value: TextureLayers) -> Self {
Subresource::Texture(TextureRange {
aspect: value.aspect,
mip_levels: MipRange::single(value.mip_level),
array_layers: value.array_layers,
})
}
}
impl From<TextureRange> for Subresource {
fn from(value: TextureRange) -> Self {
Subresource::Texture(value) Subresource::Texture(value)
} }
} }
@ -548,17 +393,6 @@ impl From<(BufferRange, vk::ImageLayout)> for ResourceRange {
} }
} }
impl From<(TextureRange, vk::ImageLayout)> for ResourceRange {
fn from((value, layout): (TextureRange, vk::ImageLayout)) -> Self {
ResourceRange::Texture {
aspect: value.aspect,
mip_level: value.mip_levels,
array_layers: value.array_layers,
layout,
}
}
}
impl From<BufferRange> for ResourceRange { impl From<BufferRange> for ResourceRange {
fn from(value: BufferRange) -> Self { fn from(value: BufferRange) -> Self {
ResourceRange::Buffer { ResourceRange::Buffer {
@ -568,18 +402,6 @@ impl From<BufferRange> for ResourceRange {
} }
} }
impl TextureRange {
pub fn full() -> Self {
Self {
aspect: vk::ImageAspectFlags::COLOR
| vk::ImageAspectFlags::DEPTH
| vk::ImageAspectFlags::STENCIL,
mip_levels: MipRange::default(),
array_layers: MipRange::default(),
}
}
}
pub struct Buffer(pub ResourceId); pub struct Buffer(pub ResourceId);
impl Buffer { impl Buffer {
@ -616,19 +438,12 @@ pub struct BufferRowSlices {
pub rows: Vec<BufferRows>, pub rows: Vec<BufferRows>,
} }
pub struct TextureRegion { pub struct TextureRegion<T: IntoImageSubresourceRange = vk::ImageSubresourceRange> {
pub range: TextureLayers, pub range: T,
pub offset: vk::Offset3D, pub offset: vk::Offset3D,
pub extent: vk::Extent3D, pub extent: vk::Extent3D,
} }
pub struct TextureView {
pub texture: Texture,
pub format: vk::Format,
pub mapping: vk::ComponentMapping,
pub range: TextureRange,
}
pub struct Read<T>(pub T); pub struct Read<T>(pub T);
pub struct Write<T>(pub T); pub struct Write<T>(pub T);
pub struct ReadWrite<T>(pub T); pub struct ReadWrite<T>(pub T);