From 30fc9f9f44d025c0437a7ccbc86b1939c690c5b6 Mon Sep 17 00:00:00 2001 From: janis Date: Fri, 17 Apr 2026 11:27:40 +0200 Subject: [PATCH] copy commands --- crates/renderer/Cargo.toml | 2 + crates/renderer/src/images.rs | 584 +----------------- crates/renderer/src/render_graph/commands.rs | 297 ++++++++- crates/renderer/src/render_graph/recorder.rs | 10 + crates/renderer/src/render_graph/resources.rs | 115 ++++ 5 files changed, 402 insertions(+), 606 deletions(-) diff --git a/crates/renderer/Cargo.toml b/crates/renderer/Cargo.toml index cce3d7b..e9b14e6 100644 --- a/crates/renderer/Cargo.toml +++ b/crates/renderer/Cargo.toml @@ -49,6 +49,8 @@ cosmic-text = "0.12.1" sys-locale = "0.3.2" guillotiere = "0.6.2" +ash-formats = { git = "https://github.com/janis-bhm/ash-formats", branch = "main" } + [dev-dependencies] tracing-test = "0.2.5" image = "0.25.5" diff --git a/crates/renderer/src/images.rs b/crates/renderer/src/images.rs index 5228435..4248692 100644 --- a/crates/renderer/src/images.rs +++ b/crates/renderer/src/images.rs @@ -16,6 +16,7 @@ use crate::{ use super::Device; use ash::vk::{self, Handle}; +use ash_formats::FormatExt; use gpu_allocator::vulkan::{AllocationCreateDesc, AllocationScheme}; use parking_lot::Mutex; @@ -514,8 +515,7 @@ fn validate_image_view_format(image: &ImageDesc, view_format: vk::Format) -> boo let mutable = image.flags.contains(vk::ImageCreateFlags::MUTABLE_FORMAT); if mutable { - image.format == view_format - || FormatClass::from(image.format) == FormatClass::from(view_format) + image.format == view_format || image.format.format_class() == view_format.format_class() } else { image.format == view_format } @@ -1045,583 +1045,3 @@ pub const SUBRESOURCERANGE_COLOR_ALL: vk::ImageSubresourceRange = vk::ImageSubre base_array_layer: 0, layer_count: vk::REMAINING_ARRAY_LAYERS, }; - -// copilot generated from spec: -#[allow(dead_code)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum FormatClass { - Bits8, - Bits16, - Alpha8, - Bits24, - Bits32, - Bits48, - Bits64, - Bits96, - Bits128, - Bits192, - Bits256, - - D16, - D24, - D32, - S8, - D16S8, - D24S8, - D32S8, - - Bc1Rgb, - Bc1Rgba, - Bc2, - Bc3, - Bc4, - Bc5, - Bc6h, - Bc7, - - Etc2Rgb, - Etc2Rgba, - Etc2EacRgba, - EacR, - EacRg, - - Astc4x4, - Astc5x4, - Astc5x5, - Astc6x5, - Astc6x6, - Astc8x5, - Astc8x6, - Astc8x8, - Astc10x5, - Astc10x6, - Astc10x8, - Astc10x10, - Astc12x10, - Astc12x12, - - YuvG8B8G8R8_422, - YuvB8G8R8G8_422, - - YuvG8B8R8Triplane420, - YuvG8B8R8Biplane420, - YuvG8B8R8Triplane422, - YuvG8B8R8Biplane422, - YuvG8B8R8Triplane444, - YuvG10X6B10X6R10X6Triplane420, - YuvG10X6B10X6R10X6Biplane420, - YuvG10X6B10X6R10X6Triplane422, - YuvG10X6B10X6R10X6Biplane422, - YuvG10X6B10X6R10X6Triplane444, - YuvG12X4B12X4R12X4Triplane420, - YuvG12X4B12X4R12X4Biplane420, - YuvG12X4B12X4R12X4Triplane422, - YuvG12X4B12X4R12X4Biplane422, - YuvG12X4B12X4R12X4Triplane444, - YuvG16B16R16Triplane420, - YuvG16B16R16Biplane420, - YuvG16B16R16Triplane422, - YuvG16B16R16Biplane422, - YuvG16B16R16Triplane444, - - YuvG8B8R8Biplane444, - YuvG10X6B10X6R10X6Biplane444, - YuvG12X4B12X4R12X4Biplane444, - YuvG16B16R16Biplane444, - - Bits64R10G10B10A10, - Bits64G10B10G10R10_422, - Bits64B10G10R10G10_422, - Bits64R12G12B12A12, - Bits64G12B12G12R12_422, - Bits64B12G12R12G12_422, - Bits64G16B16G16R16_422, - Bits64B16G16R16G16_422, - Bits64R14G14B14A14, - - Pvrtc1_2bpp, - Pvrtc1_4bpp, - Pvrtc2_2bpp, - Pvrtc2_4bpp, - - Astc3x3x3, - Astc4x3x3, - Astc4x4x3, - Astc4x4x4, - Astc5x4x4, - Astc5x5x4, - Astc5x5x5, - Astc6x5x5, - Astc6x6x5, - Astc6x6x6, - - YuvG14X2B14X2R14X2Biplane420, - YuvG14X2B14X2R14X2Biplane422, -} - -impl FormatClass { - pub fn block_size(self) -> u32 { - use FormatClass::*; - - match self { - S8 | Bits8 | Alpha8 => 1, - D16 | Bits16 => 2, - Bits24 | D24 | D16S8 => 3, - Bits32 | D24S8 => 4, - D32S8 => 5, - Bits48 => 6, - Bits64 | D32 => 8, - Bits96 => 12, - Bits128 => 16, - Bits192 => 24, - Bits256 => 32, - - Bc1Rgb | Bc1Rgba => 8, - Bc2 | Bc3 | Bc6h | Bc7 => 16, - Bc4 => 8, - Bc5 => 16, - - Etc2Rgb | Etc2Rgba | EacR => 8, - Etc2EacRgba | EacRg => 16, - - Astc4x4 | Astc5x4 | Astc5x5 | Astc6x5 | Astc6x6 | Astc8x5 | Astc8x6 | Astc8x8 - | Astc10x5 | Astc10x6 | Astc10x8 | Astc10x10 | Astc12x10 | Astc12x12 => 16, - - YuvG8B8G8R8_422 | YuvB8G8R8G8_422 => 2, - - YuvG8B8R8Triplane420 - | YuvG8B8R8Biplane420 - | YuvG10X6B10X6R10X6Triplane420 - | YuvG10X6B10X6R10X6Biplane420 - | YuvG12X4B12X4R12X4Triplane420 - | YuvG12X4B12X4R12X4Biplane420 - | YuvG16B16R16Triplane420 - | YuvG16B16R16Biplane420 => 1, - YuvG8B8R8Triplane422 => todo!(), - YuvG8B8R8Biplane422 => todo!(), - YuvG8B8R8Triplane444 => todo!(), - YuvG10X6B10X6R10X6Triplane422 => todo!(), - YuvG10X6B10X6R10X6Biplane422 => todo!(), - YuvG10X6B10X6R10X6Triplane444 => todo!(), - YuvG12X4B12X4R12X4Triplane422 => todo!(), - YuvG12X4B12X4R12X4Biplane422 => todo!(), - YuvG12X4B12X4R12X4Triplane444 => todo!(), - YuvG16B16R16Triplane422 => todo!(), - YuvG16B16R16Biplane422 => todo!(), - YuvG16B16R16Triplane444 => todo!(), - YuvG8B8R8Biplane444 => todo!(), - YuvG10X6B10X6R10X6Biplane444 => todo!(), - YuvG12X4B12X4R12X4Biplane444 => todo!(), - YuvG16B16R16Biplane444 => todo!(), - Bits64R10G10B10A10 => todo!(), - Bits64G10B10G10R10_422 => todo!(), - Bits64B10G10R10G10_422 => todo!(), - Bits64R12G12B12A12 => todo!(), - Bits64G12B12G12R12_422 => todo!(), - Bits64B12G12R12G12_422 => todo!(), - Bits64G16B16G16R16_422 => todo!(), - Bits64B16G16R16G16_422 => todo!(), - Bits64R14G14B14A14 => todo!(), - Pvrtc1_2bpp => todo!(), - Pvrtc1_4bpp => todo!(), - Pvrtc2_2bpp => todo!(), - Pvrtc2_4bpp => todo!(), - Astc3x3x3 => todo!(), - Astc4x3x3 => todo!(), - Astc4x4x3 => todo!(), - Astc4x4x4 => todo!(), - Astc5x4x4 => todo!(), - Astc5x5x4 => todo!(), - Astc5x5x5 => todo!(), - Astc6x5x5 => todo!(), - Astc6x6x5 => todo!(), - Astc6x6x6 => todo!(), - YuvG14X2B14X2R14X2Biplane420 => todo!(), - YuvG14X2B14X2R14X2Biplane422 => todo!(), - } - } -} - -impl From for FormatClass { - fn from(format: vk::Format) -> Self { - use vk::Format as F; - match format { - // 8-bit - F::R4G4_UNORM_PACK8 - | F::R8_UNORM - | F::R8_SNORM - | F::R8_USCALED - | F::R8_SSCALED - // | F::R8_BOOL_ARM - // | F::R8_SFLOAT_FPENCODING_FLOAT8E4M3_ARM - // | F::R8_SFLOAT_FPENCODING_FLOAT8E5M2_ARM - | F::R8_UINT - | F::R8_SINT - | F::R8_SRGB => FormatClass::Bits8, - - // 16-bit - F::A1B5G5R5_UNORM_PACK16_KHR - | F::R10X6_UNORM_PACK16 - | F::R12X4_UNORM_PACK16 - | F::A4R4G4B4_UNORM_PACK16 - | F::A4B4G4R4_UNORM_PACK16 - // | F::R10X6_UINT_PACK16_ARM - // | F::R12X4_UINT_PACK16_ARM - // | F::R14X2_UINT_PACK16_ARM - // | F::R14X2_UNORM_PACK16_ARM - // | F::R16_SFLOAT_FPENCODING_BFLOAT16_ARM - | F::R4G4B4A4_UNORM_PACK16 - | F::B4G4R4A4_UNORM_PACK16 - | F::R5G6B5_UNORM_PACK16 - | F::B5G6R5_UNORM_PACK16 - | F::R5G5B5A1_UNORM_PACK16 - | F::B5G5R5A1_UNORM_PACK16 - | F::A1R5G5B5_UNORM_PACK16 - | F::R8G8_UNORM - | F::R8G8_SNORM - | F::R8G8_USCALED - | F::R8G8_SSCALED - | F::R8G8_UINT - | F::R8G8_SINT - | F::R8G8_SRGB - | F::R16_UNORM - | F::R16_SNORM - | F::R16_USCALED - | F::R16_SSCALED - | F::R16_UINT - | F::R16_SINT - | F::R16_SFLOAT => FormatClass::Bits16, - - // 8-bit alpha - F::A8_UNORM_KHR => FormatClass::Alpha8, - - // 24-bit - F::R8G8B8_UNORM - | F::R8G8B8_SNORM - | F::R8G8B8_USCALED - | F::R8G8B8_SSCALED - | F::R8G8B8_UINT - | F::R8G8B8_SINT - | F::R8G8B8_SRGB - | F::B8G8R8_UNORM - | F::B8G8R8_SNORM - | F::B8G8R8_USCALED - | F::B8G8R8_SSCALED - | F::B8G8R8_UINT - | F::B8G8R8_SINT - | F::B8G8R8_SRGB => FormatClass::Bits24, - - // 32-bit - F::R10X6G10X6_UNORM_2PACK16 - | F::R12X4G12X4_UNORM_2PACK16 - // | F::R16G16_SFIXED5_NV - // | F::R10X6G10X6_UINT_2PACK16_ARM - // | F::R12X4G12X4_UINT_2PACK16_ARM - // | F::R14X2G14X2_UINT_2PACK16_ARM - // | F::R14X2G14X2_UNORM_2PACK16_ARM - | F::R8G8B8A8_UNORM - | F::R8G8B8A8_SNORM - | F::R8G8B8A8_USCALED - | F::R8G8B8A8_SSCALED - | F::R8G8B8A8_UINT - | F::R8G8B8A8_SINT - | F::R8G8B8A8_SRGB - | F::B8G8R8A8_UNORM - | F::B8G8R8A8_SNORM - | F::B8G8R8A8_USCALED - | F::B8G8R8A8_SSCALED - | F::B8G8R8A8_UINT - | F::B8G8R8A8_SINT - | F::B8G8R8A8_SRGB - | F::A8B8G8R8_UNORM_PACK32 - | F::A8B8G8R8_SNORM_PACK32 - | F::A8B8G8R8_USCALED_PACK32 - | F::A8B8G8R8_SSCALED_PACK32 - | F::A8B8G8R8_UINT_PACK32 - | F::A8B8G8R8_SINT_PACK32 - | F::A8B8G8R8_SRGB_PACK32 - | F::A2R10G10B10_UNORM_PACK32 - | F::A2R10G10B10_SNORM_PACK32 - | F::A2R10G10B10_USCALED_PACK32 - | F::A2R10G10B10_SSCALED_PACK32 - | F::A2R10G10B10_UINT_PACK32 - | F::A2R10G10B10_SINT_PACK32 - | F::A2B10G10R10_UNORM_PACK32 - | F::A2B10G10R10_SNORM_PACK32 - | F::A2B10G10R10_USCALED_PACK32 - | F::A2B10G10R10_SSCALED_PACK32 - | F::A2B10G10R10_UINT_PACK32 - | F::A2B10G10R10_SINT_PACK32 - | F::R16G16_UNORM - | F::R16G16_SNORM - | F::R16G16_USCALED - | F::R16G16_SSCALED - | F::R16G16_UINT - | F::R16G16_SINT - | F::R16G16_SFLOAT - | F::R32_UINT - | F::R32_SINT - | F::R32_SFLOAT - | F::B10G11R11_UFLOAT_PACK32 - | F::E5B9G9R9_UFLOAT_PACK32 => FormatClass::Bits32, - - // 48-bit - F::R16G16B16_UNORM - | F::R16G16B16_SNORM - | F::R16G16B16_USCALED - | F::R16G16B16_SSCALED - | F::R16G16B16_UINT - | F::R16G16B16_SINT - | F::R16G16B16_SFLOAT => FormatClass::Bits48, - - // 64-bit - F::R16G16B16A16_UNORM - | F::R16G16B16A16_SNORM - | F::R16G16B16A16_USCALED - | F::R16G16B16A16_SSCALED - | F::R16G16B16A16_UINT - | F::R16G16B16A16_SINT - | F::R16G16B16A16_SFLOAT - | F::R32G32_UINT - | F::R32G32_SINT - | F::R32G32_SFLOAT - | F::R64_UINT - | F::R64_SINT - | F::R64_SFLOAT => FormatClass::Bits64, - - // 96-bit - F::R32G32B32_UINT | F::R32G32B32_SINT | F::R32G32B32_SFLOAT => FormatClass::Bits96, - - // 128-bit - F::R32G32B32A32_UINT - | F::R32G32B32A32_SINT - | F::R32G32B32A32_SFLOAT - | F::R64G64_UINT - | F::R64G64_SINT - | F::R64G64_SFLOAT => FormatClass::Bits128, - - // 192-bit - F::R64G64B64_UINT | F::R64G64B64_SINT | F::R64G64B64_SFLOAT => FormatClass::Bits192, - - // 256-bit - F::R64G64B64A64_UINT | F::R64G64B64A64_SINT | F::R64G64B64A64_SFLOAT => { - FormatClass::Bits256 - } - - // Depth / Stencil - F::D16_UNORM => FormatClass::D16, - F::X8_D24_UNORM_PACK32 => FormatClass::D24, - F::D32_SFLOAT => FormatClass::D32, - F::S8_UINT => FormatClass::S8, - F::D16_UNORM_S8_UINT => FormatClass::D16S8, - F::D24_UNORM_S8_UINT => FormatClass::D24S8, - F::D32_SFLOAT_S8_UINT => FormatClass::D32S8, - - // BCn - F::BC1_RGB_UNORM_BLOCK | F::BC1_RGB_SRGB_BLOCK => FormatClass::Bc1Rgb, - F::BC1_RGBA_UNORM_BLOCK | F::BC1_RGBA_SRGB_BLOCK => FormatClass::Bc1Rgba, - F::BC2_UNORM_BLOCK | F::BC2_SRGB_BLOCK => FormatClass::Bc2, - F::BC3_UNORM_BLOCK | F::BC3_SRGB_BLOCK => FormatClass::Bc3, - F::BC4_UNORM_BLOCK | F::BC4_SNORM_BLOCK => FormatClass::Bc4, - F::BC5_UNORM_BLOCK | F::BC5_SNORM_BLOCK => FormatClass::Bc5, - F::BC6H_UFLOAT_BLOCK | F::BC6H_SFLOAT_BLOCK => FormatClass::Bc6h, - F::BC7_UNORM_BLOCK | F::BC7_SRGB_BLOCK => FormatClass::Bc7, - - // ETC2 / EAC - F::ETC2_R8G8B8_UNORM_BLOCK | F::ETC2_R8G8B8_SRGB_BLOCK => FormatClass::Etc2Rgb, - F::ETC2_R8G8B8A1_UNORM_BLOCK | F::ETC2_R8G8B8A1_SRGB_BLOCK => FormatClass::Etc2Rgba, - F::ETC2_R8G8B8A8_UNORM_BLOCK | F::ETC2_R8G8B8A8_SRGB_BLOCK => FormatClass::Etc2EacRgba, - F::EAC_R11_UNORM_BLOCK | F::EAC_R11_SNORM_BLOCK => FormatClass::EacR, - F::EAC_R11G11_UNORM_BLOCK | F::EAC_R11G11_SNORM_BLOCK => FormatClass::EacRg, - - // ASTC 2D - F::ASTC_4X4_SFLOAT_BLOCK | F::ASTC_4X4_UNORM_BLOCK | F::ASTC_4X4_SRGB_BLOCK => { - FormatClass::Astc4x4 - } - F::ASTC_5X4_SFLOAT_BLOCK | F::ASTC_5X4_UNORM_BLOCK | F::ASTC_5X4_SRGB_BLOCK => { - FormatClass::Astc5x4 - } - F::ASTC_5X5_SFLOAT_BLOCK | F::ASTC_5X5_UNORM_BLOCK | F::ASTC_5X5_SRGB_BLOCK => { - FormatClass::Astc5x5 - } - F::ASTC_6X5_SFLOAT_BLOCK | F::ASTC_6X5_UNORM_BLOCK | F::ASTC_6X5_SRGB_BLOCK => { - FormatClass::Astc6x5 - } - F::ASTC_6X6_SFLOAT_BLOCK | F::ASTC_6X6_UNORM_BLOCK | F::ASTC_6X6_SRGB_BLOCK => { - FormatClass::Astc6x6 - } - F::ASTC_8X5_SFLOAT_BLOCK | F::ASTC_8X5_UNORM_BLOCK | F::ASTC_8X5_SRGB_BLOCK => { - FormatClass::Astc8x5 - } - F::ASTC_8X6_SFLOAT_BLOCK | F::ASTC_8X6_UNORM_BLOCK | F::ASTC_8X6_SRGB_BLOCK => { - FormatClass::Astc8x6 - } - F::ASTC_8X8_SFLOAT_BLOCK | F::ASTC_8X8_UNORM_BLOCK | F::ASTC_8X8_SRGB_BLOCK => { - FormatClass::Astc8x8 - } - F::ASTC_10X5_SFLOAT_BLOCK | F::ASTC_10X5_UNORM_BLOCK | F::ASTC_10X5_SRGB_BLOCK => { - FormatClass::Astc10x5 - } - F::ASTC_10X6_SFLOAT_BLOCK | F::ASTC_10X6_UNORM_BLOCK | F::ASTC_10X6_SRGB_BLOCK => { - FormatClass::Astc10x6 - } - F::ASTC_10X8_SFLOAT_BLOCK | F::ASTC_10X8_UNORM_BLOCK | F::ASTC_10X8_SRGB_BLOCK => { - FormatClass::Astc10x8 - } - F::ASTC_10X10_SFLOAT_BLOCK | F::ASTC_10X10_UNORM_BLOCK | F::ASTC_10X10_SRGB_BLOCK => { - FormatClass::Astc10x10 - } - F::ASTC_12X10_SFLOAT_BLOCK | F::ASTC_12X10_UNORM_BLOCK | F::ASTC_12X10_SRGB_BLOCK => { - FormatClass::Astc12x10 - } - F::ASTC_12X12_SFLOAT_BLOCK | F::ASTC_12X12_UNORM_BLOCK | F::ASTC_12X12_SRGB_BLOCK => { - FormatClass::Astc12x12 - } - - // Packed/YCbCr-ish (as listed) - F::G8B8G8R8_422_UNORM => FormatClass::YuvG8B8G8R8_422, - F::B8G8R8G8_422_UNORM => FormatClass::YuvB8G8R8G8_422, - - F::G8_B8_R8_3PLANE_420_UNORM => FormatClass::YuvG8B8R8Triplane420, - F::G8_B8R8_2PLANE_420_UNORM => FormatClass::YuvG8B8R8Biplane420, - F::G8_B8_R8_3PLANE_422_UNORM => FormatClass::YuvG8B8R8Triplane422, - F::G8_B8R8_2PLANE_422_UNORM => FormatClass::YuvG8B8R8Biplane422, - F::G8_B8_R8_3PLANE_444_UNORM => FormatClass::YuvG8B8R8Triplane444, - - F::G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 => { - FormatClass::YuvG10X6B10X6R10X6Triplane420 - } - F::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 => { - FormatClass::YuvG10X6B10X6R10X6Biplane420 - } - F::G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 => { - FormatClass::YuvG10X6B10X6R10X6Triplane422 - } - F::G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 => { - FormatClass::YuvG10X6B10X6R10X6Biplane422 - } - F::G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 => { - FormatClass::YuvG10X6B10X6R10X6Triplane444 - } - - F::G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 => { - FormatClass::YuvG12X4B12X4R12X4Triplane420 - } - F::G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 => { - FormatClass::YuvG12X4B12X4R12X4Biplane420 - } - F::G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 => { - FormatClass::YuvG12X4B12X4R12X4Triplane422 - } - F::G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 => { - FormatClass::YuvG12X4B12X4R12X4Biplane422 - } - F::G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 => { - FormatClass::YuvG12X4B12X4R12X4Triplane444 - } - - F::G16_B16_R16_3PLANE_420_UNORM => FormatClass::YuvG16B16R16Triplane420, - F::G16_B16R16_2PLANE_420_UNORM => FormatClass::YuvG16B16R16Biplane420, - F::G16_B16_R16_3PLANE_422_UNORM => FormatClass::YuvG16B16R16Triplane422, - F::G16_B16R16_2PLANE_422_UNORM => FormatClass::YuvG16B16R16Biplane422, - F::G16_B16_R16_3PLANE_444_UNORM => FormatClass::YuvG16B16R16Triplane444, - - // 2-plane 444 (additional section) - F::G8_B8R8_2PLANE_444_UNORM => FormatClass::YuvG8B8R8Biplane444, - F::G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16 => { - FormatClass::YuvG10X6B10X6R10X6Biplane444 - } - F::G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16 => { - FormatClass::YuvG12X4B12X4R12X4Biplane444 - } - F::G16_B16R16_2PLANE_444_UNORM => FormatClass::YuvG16B16R16Biplane444, - - // 64-bit special grouped headings from the markdown - F::R10X6G10X6B10X6A10X6_UNORM_4PACK16 /* | F::R10X6G10X6B10X6A10X6_UINT_4PACK16_ARM */ - => { - FormatClass::Bits64R10G10B10A10 - } - F::G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 => FormatClass::Bits64G10B10G10R10_422, - F::B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 => FormatClass::Bits64B10G10R10G10_422, - F::R12X4G12X4B12X4A12X4_UNORM_4PACK16 /*| F::R12X4G12X4B12X4A12X4_UINT_4PACK16_ARM */ - => { - FormatClass::Bits64R12G12B12A12 - } - F::G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 => FormatClass::Bits64G12B12G12R12_422, - F::B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 => FormatClass::Bits64B12G12R12G12_422, - F::G16B16G16R16_422_UNORM => FormatClass::Bits64G16B16G16R16_422, - F::B16G16R16G16_422_UNORM => FormatClass::Bits64B16G16R16G16_422, - - // F::R14X2G14X2B14X2A14X2_UINT_4PACK16_ARM - // | F::R14X2G14X2B14X2A14X2_UNORM_4PACK16_ARM => FormatClass::Bits64_R14G14B14A14, - - // PVRTC - F::PVRTC1_2BPP_UNORM_BLOCK_IMG | F::PVRTC1_2BPP_SRGB_BLOCK_IMG => { - FormatClass::Pvrtc1_2bpp - } - F::PVRTC1_4BPP_UNORM_BLOCK_IMG | F::PVRTC1_4BPP_SRGB_BLOCK_IMG => { - FormatClass::Pvrtc1_4bpp - } - F::PVRTC2_2BPP_UNORM_BLOCK_IMG | F::PVRTC2_2BPP_SRGB_BLOCK_IMG => { - FormatClass::Pvrtc2_2bpp - } - F::PVRTC2_4BPP_UNORM_BLOCK_IMG | F::PVRTC2_4BPP_SRGB_BLOCK_IMG => { - FormatClass::Pvrtc2_4bpp - } - - // ASTC 3D (EXT) - // F::ASTC_3X3X3_UNORM_BLOCK_EXT - // | F::ASTC_3X3X3_SRGB_BLOCK_EXT - // | F::ASTC_3X3X3_SFLOAT_BLOCK_EXT => FormatClass::Astc3x3x3, - // F::ASTC_4X3X3_UNORM_BLOCK_EXT - // | F::ASTC_4X3X3_SRGB_BLOCK_EXT - // | F::ASTC_4X3X3_SFLOAT_BLOCK_EXT => FormatClass::Astc4x3x3, - // F::ASTC_4X4X3_UNORM_BLOCK_EXT - // | F::ASTC_4X4X3_SRGB_BLOCK_EXT - // | F::ASTC_4X4X3_SFLOAT_BLOCK_EXT => FormatClass::Astc4x4x3, - // F::ASTC_4X4X4_UNORM_BLOCK_EXT - // | F::ASTC_4X4X4_SRGB_BLOCK_EXT - // | F::ASTC_4X4X4_SFLOAT_BLOCK_EXT => FormatClass::Astc4x4x4, - // F::ASTC_5X4X4_UNORM_BLOCK_EXT - // | F::ASTC_5X4X4_SRGB_BLOCK_EXT - // | F::ASTC_5X4X4_SFLOAT_BLOCK_EXT => FormatClass::Astc5x4x4, - // F::ASTC_5X5X4_UNORM_BLOCK_EXT - // | F::ASTC_5X5X4_SRGB_BLOCK_EXT - // | F::ASTC_5X5X4_SFLOAT_BLOCK_EXT => FormatClass::Astc5x5x4, - // F::ASTC_5X5X5_UNORM_BLOCK_EXT - // | F::ASTC_5X5X5_SRGB_BLOCK_EXT - // | F::ASTC_5X5X5_SFLOAT_BLOCK_EXT => FormatClass::Astc5x5x5, - // F::ASTC_6X5X5_UNORM_BLOCK_EXT - // | F::ASTC_6X5X5_SRGB_BLOCK_EXT - // | F::ASTC_6X5X5_SFLOAT_BLOCK_EXT => FormatClass::Astc6x5x5, - // F::ASTC_6X6X5_UNORM_BLOCK_EXT - // | F::ASTC_6X6X5_SRGB_BLOCK_EXT - // | F::ASTC_6X6X5_SFLOAT_BLOCK_EXT => FormatClass::Astc6x6x5, - // F::ASTC_6X6X6_UNORM_BLOCK_EXT - // | F::ASTC_6X6X6_SRGB_BLOCK_EXT - // | F::ASTC_6X6X6_SFLOAT_BLOCK_EXT => FormatClass::Astc6x6x6, - - // // 14-bit 2-plane - // F::G14X2_B14X2R14X2_2PLANE_420_UNORM_3PACK16_ARM => { - // FormatClass::YuvG14X2_B14X2R14X2_2Plane_420 - // } - // F::G14X2_B14X2R14X2_2PLANE_422_UNORM_3PACK16_ARM => { - // FormatClass::YuvG14X2_B14X2R14X2_2Plane_422 - // } - - _ => todo!(), - } - } -} - -pub fn format_to_aspect_mask(format: vk::Format) -> vk::ImageAspectFlags { - use vk::Format as F; - match format { - F::D16_UNORM | F::X8_D24_UNORM_PACK32 | F::D32_SFLOAT => vk::ImageAspectFlags::DEPTH, - F::D16_UNORM_S8_UINT | F::D24_UNORM_S8_UINT | F::D32_SFLOAT_S8_UINT => { - vk::ImageAspectFlags::DEPTH | vk::ImageAspectFlags::STENCIL - } - F::S8_UINT => vk::ImageAspectFlags::STENCIL, - _ => vk::ImageAspectFlags::COLOR, - } -} diff --git a/crates/renderer/src/render_graph/commands.rs b/crates/renderer/src/render_graph/commands.rs index eb88362..5bec338 100644 --- a/crates/renderer/src/render_graph/commands.rs +++ b/crates/renderer/src/render_graph/commands.rs @@ -111,21 +111,12 @@ pub struct CopyTextureToBuffer(src: &T, dst: &U, mut map: SideEffectMap) +fn copy_side_effects_inner(_src: &T, _dst: &U, _map: SideEffectMap) where T: Resource, U: Resource, { - src.side_effect(map.reborrow().into_side_effect_map2( - vk::PipelineStageFlags2::COPY, - vk::AccessFlags2::TRANSFER_READ, - Some(vk::ImageLayout::TRANSFER_SRC_OPTIMAL), - )); - dst.side_effect(map.reborrow().into_side_effect_map2( - vk::PipelineStageFlags2::COPY, - vk::AccessFlags2::TRANSFER_WRITE, - Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL), - )); + unimplemented!() } impl Command for CopyBufferToTexture @@ -134,15 +125,52 @@ where U: ImageCopyRegion, { fn side_effects(&self, mut map: SideEffectMap) { - let src_map = map.reborrow().into_side_effect_map2( - vk::PipelineStageFlags2::COPY, - vk::AccessFlags2::TRANSFER_READ, - Some(vk::ImageLayout::TRANSFER_SRC_OPTIMAL), - ); + let block_size = self.dst.format().block_size() as u64; + let texels_per_block = self.dst.format().texels_per_block() as u64; let src_id = self.src.id(); - for region in self.src_region.regions() { - src_map.insert_range(src_id); + let dst_id = self.dst.id(); + + for (src_region, dst_region) in self + .src_region + .regions() + .iter() + .zip(self.dst_region.regions()) + { + let texel_count = if src_region.row_size != 0 { + let texel_count = src_region.row_size as u64 * src_region.row_count as u64; + debug_assert!( + texel_count % texels_per_block == 0, + "Buffer copy region must be a multiple of the block size" + ); + texel_count + } else { + dst_region.extent.width as u64 + * dst_region.extent.height as u64 + * dst_region.extent.depth as u64 + }; + + let byte_size = texel_count.div_ceil(texels_per_block) * block_size; + + map.with( + vk::PipelineStageFlags2::COPY, + vk::AccessFlags2::TRANSFER_READ, + Some(vk::ImageLayout::TRANSFER_SRC_OPTIMAL), + ) + .insert_range( + src_id, + BufferRange { + offset: src_region.offset, + size: byte_size, + }, + ); + + map.with( + vk::PipelineStageFlags2::COPY, + vk::AccessFlags2::TRANSFER_WRITE, + Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL), + ) + .insert_range(dst_id, dst_region.range); } } @@ -175,7 +203,7 @@ where let info = vk::CopyBufferToImageInfo2::default() .src_buffer(recorder.get_buffer_handle(self.src.id())) .dst_image(recorder.get_image_handle(self.dst.id())) - .dst_image_layout(recorder.get_image_layout(self.dst.id())) + .dst_image_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL) .regions(®ions); unsafe { @@ -184,21 +212,241 @@ where } } +impl Command for CopyTextureToBuffer +where + T: ImageCopyRegion, + U: BufferImageBufferCopyRegion, +{ + fn side_effects(&self, mut map: SideEffectMap) { + let block_size = self.src.format().block_size() as u64; + let texels_per_block = self.src.format().texels_per_block() as u64; + + let src_id = self.src.id(); + let dst_id = self.dst.id(); + + for (src_region, dst_region) in self + .src_region + .regions() + .iter() + .zip(self.dst_region.regions()) + { + let texel_count = if dst_region.row_size != 0 { + let texel_count = dst_region.row_size as u64 * dst_region.row_count as u64; + debug_assert!( + texel_count % texels_per_block == 0, + "Buffer copy region must be a multiple of the block size" + ); + texel_count + } else { + src_region.extent.width as u64 + * src_region.extent.height as u64 + * src_region.extent.depth as u64 + }; + + let byte_size = texel_count.div_ceil(texels_per_block) * block_size; + + map.with( + vk::PipelineStageFlags2::COPY, + vk::AccessFlags2::TRANSFER_READ, + Some(vk::ImageLayout::TRANSFER_SRC_OPTIMAL), + ) + .insert_range(dst_id, src_region.range); + + map.with( + vk::PipelineStageFlags2::COPY, + vk::AccessFlags2::TRANSFER_WRITE, + Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL), + ) + .insert_range( + src_id, + BufferRange { + offset: dst_region.offset, + size: byte_size, + }, + ); + } + } + + fn apply(self, recorder: &mut CommandRecorder) { + let cmd = recorder.cmd_buffer(); + let dev = &cmd.device().raw; + + let regions = self + .src_region + .regions() + .iter() + .zip(self.dst_region.regions()) + .map(|(src_region, dst_region)| { + vk::BufferImageCopy2::default() + .buffer_offset(dst_region.offset) + .buffer_row_length(dst_region.row_size) + .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()), + ) + }) + .collect::>(); + + let info = vk::CopyImageToBufferInfo2::default() + .dst_buffer(recorder.get_buffer_handle(self.src.id())) + .src_image(recorder.get_image_handle(self.dst.id())) + .src_image_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL) + .regions(®ions); + + unsafe { + dev.cmd_copy_image_to_buffer2(cmd.raw(), &info); + } + } +} + +impl Command for CopyBuffers +where + T: BufferCopyRegion, +{ + fn side_effects(&self, mut map: SideEffectMap) { + for region in self.src_region.regions() { + map.with( + vk::PipelineStageFlags2::COPY, + vk::AccessFlags2::TRANSFER_READ, + None, + ) + .insert_range(self.src.id(), *region); + } + + for region in self.dst_region.regions() { + map.with( + vk::PipelineStageFlags2::COPY, + vk::AccessFlags2::TRANSFER_WRITE, + None, + ) + .insert_range(self.dst.id(), *region); + } + } + + fn apply(self, recorder: &mut CommandRecorder) { + let cmd = recorder.cmd_buffer(); + let dev = &cmd.device().raw; + + let regions = self + .src_region + .regions() + .iter() + .zip(self.dst_region.regions()) + .map(|(src_region, dst_region)| { + vk::BufferCopy2::default() + .src_offset(src_region.offset) + .dst_offset(dst_region.offset) + .size(src_region.size) + }) + .collect::>(); + + let info = vk::CopyBufferInfo2::default() + .dst_buffer(recorder.get_buffer_handle(self.dst.id())) + .src_buffer(recorder.get_buffer_handle(self.src.id())) + .regions(®ions); + + unsafe { + dev.cmd_copy_buffer2(cmd.raw(), &info); + } + } +} + +impl Command for CopyTextures +where + T: ImageCopyRegion, +{ + fn side_effects(&self, mut map: SideEffectMap) { + for region in self.src_region.regions() { + map.with( + vk::PipelineStageFlags2::COPY, + vk::AccessFlags2::TRANSFER_READ, + None, + ) + .insert_range(self.src.id(), region.range); + } + + for region in self.dst_region.regions() { + map.with( + vk::PipelineStageFlags2::COPY, + vk::AccessFlags2::TRANSFER_WRITE, + None, + ) + .insert_range(self.dst.id(), region.range); + } + } + + fn apply(self, recorder: &mut CommandRecorder) { + let cmd = recorder.cmd_buffer(); + let dev = &cmd.device().raw; + + let regions = self + .src_region + .regions() + .iter() + .zip(self.dst_region.regions()) + .map(|(src_region, dst_region)| { + vk::ImageCopy2::default() + .src_offset(src_region.offset) + .src_subresource(src_region.range.into()) + .dst_offset(dst_region.offset) + .dst_subresource(dst_region.range.into()) + .extent(src_region.extent) + }) + .collect::>(); + + let info = vk::CopyImageInfo2::default() + .src_image(recorder.get_image_handle(self.src.id())) + .src_image_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL) + .dst_image(recorder.get_image_handle(self.dst.id())) + .dst_image_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL) + .regions(®ions); + + unsafe { + dev.cmd_copy_image2(cmd.raw(), &info); + } + } +} + pub struct ClearTexture { - pub dst: Write, + pub dst: Texture, + pub dst_region: TextureRegion, pub clear_value: [f32; 4], } impl Command for ClearTexture { fn side_effects(&self, mut map: SideEffectMap) { - self.dst.side_effect(map.reborrow().into_side_effect_map2( - vk::PipelineStageFlags2::TRANSFER, + map.with( + vk::PipelineStageFlags2::CLEAR, vk::AccessFlags2::TRANSFER_WRITE, Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL), - )); + ) + .insert_range(self.dst.id(), self.dst_region.range); } - fn apply(self, _recorder: &mut CommandRecorder) {} + fn apply(self, recorder: &mut CommandRecorder) { + let cmd = recorder.cmd_buffer(); + let dev = &cmd.device().raw; + + let values = vk::ClearColorValue { + float32: self.clear_value, + }; + + unsafe { + dev.cmd_clear_color_image( + cmd.raw(), + recorder.get_image_handle(self.dst.id()), + vk::ImageLayout::TRANSFER_DST_OPTIMAL, + &values, + &[self.dst_region.range.into()], + ); + } + } } pub struct UpdateBuffer { @@ -527,6 +775,7 @@ mod sealed { pub trait OutsideRenderPass {} } use ash::vk; +use ash_formats::FormatExt; pub(super) use sealed::*; impl IsDrawData for DrawData {} diff --git a/crates/renderer/src/render_graph/recorder.rs b/crates/renderer/src/render_graph/recorder.rs index ca14dbb..76fdd3e 100644 --- a/crates/renderer/src/render_graph/recorder.rs +++ b/crates/renderer/src/render_graph/recorder.rs @@ -121,6 +121,16 @@ impl<'a> SideEffectMap<'a> { required_layout, } } + + pub fn with( + &mut self, + stage_flags: vk::PipelineStageFlags2, + access_flags: vk::AccessFlags2, + required_layout: Option, + ) -> SideEffectMap2<'_> { + self.reborrow() + .into_side_effect_map2(stage_flags, access_flags, required_layout) + } } pub struct SideEffectMap2<'a> { diff --git a/crates/renderer/src/render_graph/resources.rs b/crates/renderer/src/render_graph/resources.rs index ef5bf13..4fe0a0e 100644 --- a/crates/renderer/src/render_graph/resources.rs +++ b/crates/renderer/src/render_graph/resources.rs @@ -10,6 +10,8 @@ pub trait Resource: Sized { } mod sealed { + use ash::vk; + pub trait Texture { fn format(&self) -> vk::Format { todo!() @@ -21,6 +23,7 @@ mod sealed { } } } +pub use sealed::{Buffer as AsBuffer, Texture as AsTexture}; #[derive(Debug, Clone, Copy)] pub enum Subresource { @@ -352,6 +355,12 @@ impl BufferRange { } } +impl From for Subresource { + fn from(value: BufferRange) -> Self { + Subresource::Buffer(value) + } +} + #[derive(Debug, Default, Clone, Copy)] pub struct BufferRows { pub offset: u64, @@ -375,6 +384,100 @@ pub struct TextureLayers { pub array_layers: MipRange, } +pub trait IntoImageSubresourceLayers { + fn into_layers(self) -> vk::ImageSubresourceLayers; +} + +pub trait IntoImageSubresourceRange { + fn into_range(self) -> vk::ImageSubresourceRange; +} + +impl IntoImageSubresourceLayers for vk::ImageSubresource { + fn into_layers(self) -> vk::ImageSubresourceLayers { + vk::ImageSubresourceLayers { + aspect_mask: self.aspect_mask, + mip_level: self.mip_level, + base_array_layer: self.array_layer, + layer_count: 1, + } + } +} + +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 vk::ImageSubresourceLayers { + 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.base_array_layer, + layer_count: self.layer_count, + } + } +} + +pub trait ImageSubresourceExt { + fn aspects(self) -> vk::ImageAspectFlags; + fn layers(self) -> MipRange; + fn mip_levels(self) -> MipRange; +} + +impl ImageSubresourceExt for vk::ImageSubresourceLayers { + fn aspects(self) -> vk::ImageAspectFlags { + self.aspect_mask + } + fn layers(self) -> MipRange { + MipRange::new( + self.base_array_layer, + self.base_array_layer + self.layer_count, + ) + } + + fn mip_levels(self) -> MipRange { + MipRange::single(self.mip_level) + } +} + +impl ImageSubresourceExt for vk::ImageSubresourceRange { + fn aspects(self) -> vk::ImageAspectFlags { + self.aspect_mask + } + fn layers(self) -> MipRange { + MipRange::new( + self.base_array_layer, + self.base_array_layer + self.layer_count, + ) + } + + fn mip_levels(self) -> MipRange { + MipRange::new(self.base_mip_level, self.base_mip_level + self.level_count) + } +} + +impl ImageSubresourceExt for vk::ImageSubresource { + fn aspects(self) -> vk::ImageAspectFlags { + self.aspect_mask + } + fn layers(self) -> MipRange { + MipRange::single(self.mip_level) + } + + fn mip_levels(self) -> MipRange { + MipRange::single(self.array_layer) + } +} + impl From for vk::ImageSubresourceLayers { fn from(value: TextureLayers) -> Self { vk::ImageSubresourceLayers { @@ -386,6 +489,18 @@ impl From for vk::ImageSubresourceLayers { } } +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 {