From c20a4fa1a3c9ceef8a3eea1c59b37de87a6914eb Mon Sep 17 00:00:00 2001 From: janis Date: Fri, 17 Apr 2026 20:35:04 +0200 Subject: [PATCH] iiiiiii dooooooooont know....... --- crates/renderer/src/render_graph/commands.rs | 219 ++++++------- .../src/render_graph/graph_builder.rs | 187 +++++------ crates/renderer/src/render_graph/recorder.rs | 48 ++- crates/renderer/src/render_graph/resources.rs | 301 ++++-------------- 4 files changed, 305 insertions(+), 450 deletions(-) diff --git a/crates/renderer/src/render_graph/commands.rs b/crates/renderer/src/render_graph/commands.rs index 5bec338..c0142b8 100644 --- a/crates/renderer/src/render_graph/commands.rs +++ b/crates/renderer/src/render_graph/commands.rs @@ -12,6 +12,8 @@ //! recorded sequentially, in the order they were inserted into a command //! buffer. During command insertion +use std::marker::PhantomData; + use crate::{ device::DeviceOwned, render_graph::recorder::{CommandRecorder, SideEffectMap}, @@ -21,6 +23,7 @@ use super::resources::*; pub struct ImportResource { pub resource: T, + pub range: Option, pub access: vk::AccessFlags2, pub stage: vk::PipelineStageFlags2, pub layout: Option, @@ -28,12 +31,9 @@ pub struct ImportResource { impl Command for ImportResource { fn side_effects(&self, mut map: SideEffectMap) { - self.resource - .side_effect(map.reborrow().into_side_effect_map2( - self.stage, - self.access, - self.layout, - )); + let range = self.range.unwrap_or_else(|| self.resource.full_range()); + map.with(self.stage, self.access, self.layout) + .insert_range(self.resource.id(), range); } fn apply(self, _recorder: &mut CommandRecorder) { @@ -55,16 +55,16 @@ impl> BufferImageBufferCopyRegion for T { } } -pub trait ImageCopyRegion { - fn regions(&self) -> &[TextureRegion]; +pub trait ImageCopyRegion { + fn regions(&self) -> &[TextureRegion]; } -impl ImageCopyRegion for TextureRegion { - fn regions(&self) -> &[TextureRegion] { +impl ImageCopyRegion for TextureRegion { + fn regions(&self) -> &[TextureRegion] { core::slice::from_ref(self) } } -impl> ImageCopyRegion for T { - fn regions(&self) -> &[TextureRegion] { +impl]>> ImageCopyRegion for T { + fn regions(&self) -> &[TextureRegion] { self.as_ref() } } @@ -90,39 +90,43 @@ pub struct CopyBuffers { pub dst_region: T, } -pub struct CopyTextures { +pub struct CopyTextures, R: IntoImageSubresourceRange> { pub src: Texture, pub src_region: T, pub dst: Texture, pub dst_region: T, + _pd: PhantomData, } -pub struct CopyBufferToTexture { +pub struct CopyBufferToTexture< + T: BufferImageBufferCopyRegion, + U: ImageCopyRegion, + R: IntoImageSubresourceLayers, +> { pub src: Buffer, pub src_region: T, pub dst: Texture, pub dst_region: U, + _pd: PhantomData, } -pub struct CopyTextureToBuffer { +pub struct CopyTextureToBuffer< + T: ImageCopyRegion, + U: BufferImageBufferCopyRegion, + R: IntoImageSubresourceLayers, +> { pub src: Texture, pub src_region: T, pub dst: Buffer, pub dst_region: U, + _pd: PhantomData, } -fn copy_side_effects_inner(_src: &T, _dst: &U, _map: SideEffectMap) -where - T: Resource, - U: Resource, -{ - unimplemented!() -} - -impl Command for CopyBufferToTexture +impl Command for CopyBufferToTexture where T: BufferImageBufferCopyRegion, - U: ImageCopyRegion, + U: ImageCopyRegion, + R: IntoImageSubresourceLayers, { fn side_effects(&self, mut map: SideEffectMap) { let block_size = self.dst.format().block_size() as u64; @@ -170,7 +174,7 @@ where vk::AccessFlags2::TRANSFER_WRITE, 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) .image_offset(dst_region.offset) .image_extent(dst_region.extent) - .image_subresource( - 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()), - ) + .image_subresource(dst_region.range.into_layers()) }) .collect::>(); @@ -212,10 +210,11 @@ where } } -impl Command for CopyTextureToBuffer +impl Command for CopyTextureToBuffer where - T: ImageCopyRegion, + T: ImageCopyRegion, U: BufferImageBufferCopyRegion, + R: IntoImageSubresourceLayers, { fn side_effects(&self, mut map: SideEffectMap) { let block_size = self.src.format().block_size() as u64; @@ -250,7 +249,7 @@ where vk::AccessFlags2::TRANSFER_READ, Some(vk::ImageLayout::TRANSFER_SRC_OPTIMAL), ) - .insert_range(dst_id, src_region.range); + .insert_range(dst_id, src_region.range.into_range()); map.with( vk::PipelineStageFlags2::COPY, @@ -283,13 +282,7 @@ where .buffer_image_height(dst_region.row_count) .image_offset(src_region.offset) .image_extent(src_region.extent) - .image_subresource( - 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()), - ) + .image_subresource(src_region.range.into_layers()) }) .collect::>(); @@ -357,9 +350,10 @@ where } } -impl Command for CopyTextures +impl Command for CopyTextures where - T: ImageCopyRegion, + T: ImageCopyRegion, + R: IntoImageSubresourceLayers, { fn side_effects(&self, mut map: SideEffectMap) { for region in self.src_region.regions() { @@ -368,7 +362,7 @@ where vk::AccessFlags2::TRANSFER_READ, None, ) - .insert_range(self.src.id(), region.range); + .insert_range(self.src.id(), region.range.into_range()); } for region in self.dst_region.regions() { @@ -377,7 +371,7 @@ where vk::AccessFlags2::TRANSFER_WRITE, 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)| { vk::ImageCopy2::default() .src_offset(src_region.offset) - .src_subresource(src_region.range.into()) + .src_subresource(src_region.range.into_layers()) .dst_offset(dst_region.offset) - .dst_subresource(dst_region.range.into()) + .dst_subresource(dst_region.range.into_layers()) .extent(src_region.extent) }) .collect::>(); @@ -413,20 +407,20 @@ where } } -pub struct ClearTexture { +pub struct ClearTexture { pub dst: Texture, - pub dst_region: TextureRegion, + pub dst_region: TextureRegion, pub clear_value: [f32; 4], } -impl Command for ClearTexture { +impl Command for ClearTexture { fn side_effects(&self, mut map: SideEffectMap) { map.with( vk::PipelineStageFlags2::CLEAR, vk::AccessFlags2::TRANSFER_WRITE, 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) { @@ -443,33 +437,43 @@ impl Command for ClearTexture { recorder.get_image_handle(self.dst.id()), vk::ImageLayout::TRANSFER_DST_OPTIMAL, &values, - &[self.dst_region.range.into()], + &[self.dst_region.range.into_range()], ); } } } pub struct UpdateBuffer { - pub dst: Write, + pub dst: Buffer, + pub dst_region: BufferRange, pub data: Vec, } impl Command for UpdateBuffer { fn side_effects(&self, mut map: SideEffectMap) { - self.dst.side_effect(map.reborrow().into_side_effect_map2( + map.with( vk::PipelineStageFlags2::TRANSFER, vk::AccessFlags2::TRANSFER_WRITE, None, - )); + ) + .insert_range(self.dst.id(), self.dst_region); } 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 color_attachments: Vec, - pub depth_attachment: Option, - pub stencil_attachment: Option, + pub color_attachments: Vec, + pub depth_attachment: Option, + pub stencil_attachment: Option, pub area: (u32, u32), pub layers: u32, } @@ -482,26 +486,40 @@ impl Command for BeginRendering { // pass instance referencing framebuffer-local stages must contain // only framebuffer-local stages. - // TODO: consider loadop and storeop? - attachment.side_effect(map.reborrow().into_side_effect_map2( + map.with( vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT, - vk::AccessFlags2::COLOR_ATTACHMENT_READ, - Some(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL), - )); + if attachment.load_op == vk::AttachmentLoadOp::LOAD { + 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 { - depth.side_effect(map.reborrow().into_side_effect_map2( + map.with( vk::PipelineStageFlags2::EARLY_FRAGMENT_TESTS, - vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_READ, - Some(vk::ImageLayout::DEPTH_ATTACHMENT_OPTIMAL), - )); + if depth.load_op == vk::AttachmentLoadOp::LOAD { + 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 { - stencil.side_effect(map.reborrow().into_side_effect_map2( + map.with( vk::PipelineStageFlags2::EARLY_FRAGMENT_TESTS, - vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_READ, - Some(vk::ImageLayout::STENCIL_ATTACHMENT_OPTIMAL), - )); + if stencil.load_op == vk::AttachmentLoadOp::LOAD { + 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 { 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) {} @@ -543,11 +561,12 @@ pub struct BindVertexBuffers { impl Command for BindVertexBuffers { fn side_effects(&self, mut map: SideEffectMap) { for buffer in &self.buffers { - buffer.side_effect(map.reborrow().into_side_effect_map2( + map.with( vk::PipelineStageFlags2::VERTEX_ATTRIBUTE_INPUT, vk::AccessFlags2::VERTEX_ATTRIBUTE_READ, None, - )); + ) + .insert_range(buffer.id(), buffer.range); } } @@ -577,11 +596,12 @@ pub struct BindIndexBuffer(pub BufferSlice, pub IndexFormat); impl Command for BindIndexBuffer { fn side_effects(&self, mut map: SideEffectMap) { - self.0.side_effect(map.reborrow().into_side_effect_map2( + map.with( vk::PipelineStageFlags2::INDEX_INPUT, vk::AccessFlags2::INDEX_READ, None, - )); + ) + .insert_range(self.0.id(), self.0.range); } fn apply(self, recorder: &mut CommandRecorder) { @@ -726,27 +746,11 @@ pub enum IndexFormat { pub struct Draw { pub data: T, - pub vertex_buffers: Vec, - pub index_buffer: Option<(BufferSlice, IndexFormat)>, } impl Command for Draw { fn side_effects(&self, mut map: SideEffectMap) { 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) {} @@ -782,29 +786,28 @@ impl IsDrawData for DrawData {} impl IsDrawData for DrawIndexedData {} impl IsDrawData for DrawIndirectData { fn side_effects(&self, mut map: SideEffectMap) { - self.indirect_buffer - .side_effect(map.reborrow().into_side_effect_map2( - vk::PipelineStageFlags2::DRAW_INDIRECT, - vk::AccessFlags2::INDIRECT_COMMAND_READ, - None, - )); + map.with( + vk::PipelineStageFlags2::DRAW_INDIRECT, + vk::AccessFlags2::INDIRECT_COMMAND_READ, + None, + ) + .insert_range(self.indirect_buffer.id(), self.indirect_buffer.range); } } impl IsDrawData for DrawIndexedIndirectData { fn side_effects(&self, mut map: SideEffectMap) { - self.indirect_buffer - .side_effect(map.reborrow().into_side_effect_map2( - vk::PipelineStageFlags2::DRAW_INDIRECT, - vk::AccessFlags2::INDIRECT_COMMAND_READ, - None, - )); + map.with( + vk::PipelineStageFlags2::DRAW_INDIRECT, + vk::AccessFlags2::INDIRECT_COMMAND_READ, + None, + ) + .insert_range(self.indirect_buffer.id(), self.indirect_buffer.range); } } impl OutsideRenderPass for BeginRendering {} impl InsideRenderPass for EndRendering {} -impl OutsideRenderPass for Copy {} -impl OutsideRenderPass for ClearTexture {} +impl OutsideRenderPass for ClearTexture {} impl OutsideRenderPass for UpdateBuffer {} impl InsideRenderPass for BindPipeline {} diff --git a/crates/renderer/src/render_graph/graph_builder.rs b/crates/renderer/src/render_graph/graph_builder.rs index 6d558c7..d743b9a 100644 --- a/crates/renderer/src/render_graph/graph_builder.rs +++ b/crates/renderer/src/render_graph/graph_builder.rs @@ -80,7 +80,11 @@ impl<'r> GraphBuilder<'r> { mod api_demo { - use crate::{EguiState, pipeline::Pipeline, render_graph::commands}; + use crate::{ + EguiState, + pipeline::Pipeline, + render_graph::{commands, resources::TextureRegion}, + }; use super::*; use ash::vk::{self, BufferUsageFlags}; @@ -180,84 +184,86 @@ mod api_demo { ); 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: 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 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) 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, - }, - }, - }); + // 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 { + vec![commands::RenderAttachment { 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), - }, + region: vk::ImageSubresourceRange::default() + .aspect_mask(vk::ImageAspectFlags::COLOR) + .base_mip_level(0) + .level_count(1) + .base_array_layer(0) + .layer_count(1), + layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL, + load_op: vk::AttachmentLoadOp::LOAD, + store_op: vk::AttachmentStoreOp::STORE, }], None, None, @@ -301,29 +307,32 @@ mod api_demo { &[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::() as u32, - }, - vertex_buffers: vec![resources::BufferSlice { + pass_cmd.push(commands::BindVertexBuffers { + 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, - }, + first_binding: 0, + }); + pass_cmd.push(commands::BindIndexBuffer( + resources::BufferSlice { + buffer: resources::Buffer(index_buffer.id), + 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::() as u32, + }, }); pass_cmd.finalise(); diff --git a/crates/renderer/src/render_graph/recorder.rs b/crates/renderer/src/render_graph/recorder.rs index 76fdd3e..801255a 100644 --- a/crates/renderer/src/render_graph/recorder.rs +++ b/crates/renderer/src/render_graph/recorder.rs @@ -11,7 +11,7 @@ use crate::{ commands::CommandBuffer, images::ImageDesc, render_graph::{ - commands::{Command, InsideRenderPass, OutsideRenderPass}, + commands::{Command, InsideRenderPass, OutsideRenderPass, RenderAttachment}, resources::{ ResourceId, Subresource, SubresourceScope, SubresourceScopeInner, TextureRegion, }, @@ -83,6 +83,12 @@ impl VecOrSingle { VecOrSingle::Single(item) => core::slice::from_ref::(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::(item).iter_mut(), + } + } } #[derive(Default)] @@ -94,13 +100,35 @@ struct SideEffects { pub struct SideEffectMap<'a>(&'a mut SideEffects, u32); 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 - .map - .entry((id, self.1)) - .and_modify(|entry| entry.push(scope)) - .or_insert_with(|| scope.into()); + + 'inserted: { + 'outer: for ((_rid, _cid), scopes) in self.0.map.range_mut((id, 0)..=(id, self.1)).rev() + { + 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<'_> { @@ -219,9 +247,9 @@ impl<'cmd> CommandList<'cmd> { pub fn begin_rendering( &mut self, - color_attachments: Vec, - depth_attachment: Option, - stencil_attachment: Option, + color_attachments: Vec, + depth_attachment: Option, + stencil_attachment: Option, area: (u32, u32), layers: u32, ) -> RenderPass<'cmd, '_> { diff --git a/crates/renderer/src/render_graph/resources.rs b/crates/renderer/src/render_graph/resources.rs index 4fe0a0e..d723719 100644 --- a/crates/renderer/src/render_graph/resources.rs +++ b/crates/renderer/src/render_graph/resources.rs @@ -6,7 +6,7 @@ use crate::{images::MipRange, render_graph::recorder::SideEffectMap2}; pub trait Resource: Sized { fn id(&self) -> ResourceId; - fn side_effect(&self, map: SideEffectMap2); + fn full_range(&self) -> Subresource; } mod sealed { @@ -28,7 +28,27 @@ pub use sealed::{Buffer as AsBuffer, Texture as AsTexture}; #[derive(Debug, Clone, Copy)] pub enum Subresource { 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)] @@ -44,7 +64,7 @@ pub enum SubresourceScopeInner { subresource: BufferRange, }, Texture { - subresource: TextureRange, + subresource: vk::ImageSubresourceRange, layout: vk::ImageLayout, }, } @@ -94,18 +114,18 @@ impl SubresourceScope { // think), however: if a previous access requires a less general // barrier, then is it better to split? - let overlaps = lhs.aspect.intersects(rhs.aspect) - && lhs.mip_levels.intersects(rhs.mip_levels) - && lhs.array_layers.intersects(rhs.array_layers); + let overlaps = lhs.aspect_mask.intersects(rhs.aspect_mask) + && lhs.mip_levels().intersects(rhs.mip_levels()) + && lhs.layers().intersects(rhs.layers()); // non-overlapping sub-resources shouldn't be merged. if !overlaps { return false; } - let lhs_contains_rhs = lhs.aspect.contains(rhs.aspect) - && lhs.mip_levels.contains(rhs.mip_levels) - && lhs.array_layers.contains(rhs.array_layers); + let lhs_contains_rhs = lhs.aspect_mask.contains(rhs.aspect_mask) + && lhs.mip_levels().contains(rhs.mip_levels()) + && lhs.layers().contains(rhs.layers()); // other is not a subresource of self, so we can't merge them. if !lhs_contains_rhs { @@ -146,9 +166,9 @@ impl SubresourceScope { ) => { // image subresource ranges overlap if they share mip levels and // array layers with the same aspects. - let overlaps = lhs.aspect.intersects(rhs.aspect) - && lhs.mip_levels.intersects(rhs.mip_levels) - && lhs.array_layers.intersects(rhs.array_layers); + let overlaps = lhs.aspect_mask.intersects(rhs.aspect_mask) + && lhs.mip_levels().intersects(rhs.mip_levels()) + && lhs.layers().intersects(rhs.layers()); if !overlaps { return false; @@ -174,8 +194,6 @@ mod impls { use super::*; impl sealed::Texture for Texture {} - impl sealed::Texture for TextureRegion {} - impl sealed::Texture for TextureView {} impl sealed::Buffer for Buffer {} impl sealed::Buffer for BufferSlice {} @@ -185,130 +203,25 @@ mod impls { self.0 } - fn side_effect(&self, mut map: SideEffectMap2) { - map.insert_range(self.id(), BufferRange::full()); + fn full_range(&self) -> Subresource { + Subresource::full_buffer() } } - impl Resource for BufferSlice { fn id(&self) -> ResourceId { self.buffer.id() } - fn side_effect(&self, mut map: SideEffectMap2) { - map.insert_range(self.id(), self.range); + fn full_range(&self) -> Subresource { + 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 { fn id(&self) -> ResourceId { self.0 } - - fn side_effect(&self, mut map: SideEffectMap2) { - 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 Resource for Read { - fn id(&self) -> ResourceId { - self.0.id() - } - - fn side_effect(&self, map: SideEffectMap2) { - self.0.side_effect(map); - } - } - impl Resource for Write { - fn id(&self) -> ResourceId { - self.0.id() - } - - fn side_effect(&self, map: SideEffectMap2) { - self.0.side_effect(map); - } - } - impl Resource for ReadWrite { - fn id(&self) -> ResourceId { - self.0.id() - } - - fn side_effect(&self, map: SideEffectMap2) { - self.0.side_effect(map); + fn full_range(&self) -> Subresource { + Subresource::full_texture(vk::Format::UNDEFINED) } } } @@ -368,32 +281,16 @@ pub struct BufferRows { 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 { - fn into_layers(self) -> vk::ImageSubresourceLayers; + fn into_layers(&self) -> vk::ImageSubresourceLayers; } pub trait IntoImageSubresourceRange { - fn into_range(self) -> vk::ImageSubresourceRange; + fn into_range(&self) -> vk::ImageSubresourceRange; } impl IntoImageSubresourceLayers for vk::ImageSubresource { - fn into_layers(self) -> vk::ImageSubresourceLayers { + fn into_layers(&self) -> vk::ImageSubresourceLayers { vk::ImageSubresourceLayers { aspect_mask: self.aspect_mask, mip_level: self.mip_level, @@ -403,20 +300,17 @@ impl IntoImageSubresourceLayers for vk::ImageSubresource { } } -impl IntoImageSubresourceRange for vk::ImageSubresource { - fn into_range(self) -> vk::ImageSubresourceRange { - vk::ImageSubresourceRange { - aspect_mask: self.aspect_mask, - base_mip_level: self.mip_level, - level_count: 1, - base_array_layer: self.array_layer, - layer_count: 1, - } +impl IntoImageSubresourceRange for T +where + T: IntoImageSubresourceLayers, +{ + fn into_range(&self) -> vk::ImageSubresourceRange { + self.into_layers().into_range() } } impl IntoImageSubresourceRange for vk::ImageSubresourceLayers { - fn into_range(self) -> vk::ImageSubresourceRange { + fn into_range(&self) -> vk::ImageSubresourceRange { vk::ImageSubresourceRange { aspect_mask: self.aspect_mask, 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 { fn aspects(self) -> vk::ImageAspectFlags; fn layers(self) -> MipRange; @@ -478,63 +378,8 @@ impl ImageSubresourceExt for vk::ImageSubresource { } } -impl From for vk::ImageSubresourceLayers { - fn from(value: TextureLayers) -> 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 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 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 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 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 for Subresource { - fn from(value: TextureRange) -> Self { +impl From for Subresource { + fn from(value: vk::ImageSubresourceRange) -> Self { 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 for ResourceRange { fn from(value: BufferRange) -> Self { ResourceRange::Buffer { @@ -568,18 +402,6 @@ impl From 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); impl Buffer { @@ -616,19 +438,12 @@ pub struct BufferRowSlices { pub rows: Vec, } -pub struct TextureRegion { - pub range: TextureLayers, +pub struct TextureRegion { + pub range: T, pub offset: vk::Offset3D, pub extent: vk::Extent3D, } -pub struct TextureView { - pub texture: Texture, - pub format: vk::Format, - pub mapping: vk::ComponentMapping, - pub range: TextureRange, -} - pub struct Read(pub T); pub struct Write(pub T); pub struct ReadWrite(pub T);