ソースを参照

Fix ASTC support for non 4x4 blocks

Signed-off-by: Akio Gaule <[email protected]>
Akio Gaule 1 年間 前
コミット
70e9fd96c3

+ 4 - 3
Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/Format.h

@@ -9,6 +9,7 @@
 
 #include <Atom/RHI.Reflect/Base.h>
 #include <Atom/RHI.Reflect/ImageEnums.h>
+#include <Atom/RHI.Reflect/Size.h>
 
 namespace AZ::RHI
 {
@@ -220,10 +221,10 @@ namespace AZ::RHI
     const char* ToString(Format format);
 
     //! @brief Returns the required alignment for width / height of an image for the given format. Block
-    //! compressed formats will return 4. Certain Packed / Planar formats may return 2. This is especially
-    //! important for low level of detail mips in the chain, which will reduce down to the alignment instead
+    //! compressed formats will return the number of blocks (e.g 4x4, 8x8, etc). Certain Packed / Planar formats may return 2.
+    //!  This is especially important for low level of detail mips in the chain, which will reduce down to the alignment instead
     //! of 1x1. The returned value only applies to image width and height. Depth is unaffected.
-    uint32_t GetFormatDimensionAlignment(Format format);
+    RHI::Size GetFormatDimensionAlignment(Format format);
 
     //! @brief Returns the SRGB equivalent to the provided linear format, if it exists. If not, the provided
     //! format is returned unchanged.

+ 17 - 5
Gems/Atom/RHI/Code/Source/RHI.Reflect/Format.cpp

@@ -530,7 +530,7 @@ namespace AZ::RHI
         return "<<Format Value Error>>";
     }
 
-    uint32_t GetFormatDimensionAlignment(Format format)
+    RHI::Size GetFormatDimensionAlignment(Format format)
     {
         switch (format)
         {
@@ -560,34 +560,46 @@ namespace AZ::RHI
         case Format::EAC_R11_SNORM:
         case Format::ASTC_4x4_UNORM:
         case Format::ASTC_4x4_UNORM_SRGB:
+            return RHI::Size(4, 4, 1);
         case Format::ASTC_5x4_UNORM:
         case Format::ASTC_5x4_UNORM_SRGB:
+            return RHI::Size(5, 4, 1);
         case Format::ASTC_5x5_UNORM:
         case Format::ASTC_5x5_UNORM_SRGB:
+            return RHI::Size(5, 5, 1);
         case Format::ASTC_6x5_UNORM:
         case Format::ASTC_6x5_UNORM_SRGB:
+            return RHI::Size(6, 5, 1);
         case Format::ASTC_6x6_UNORM:
         case Format::ASTC_6x6_UNORM_SRGB:
+            return RHI::Size(6, 6, 1);
         case Format::ASTC_8x5_UNORM:
         case Format::ASTC_8x5_UNORM_SRGB:
+            return RHI::Size(8, 5, 1);
         case Format::ASTC_8x6_UNORM:
         case Format::ASTC_8x6_UNORM_SRGB:
+            return RHI::Size(8, 6, 1);
         case Format::ASTC_8x8_UNORM:
         case Format::ASTC_8x8_UNORM_SRGB:
+            return RHI::Size(8, 8, 1);
         case Format::ASTC_10x5_UNORM:
         case Format::ASTC_10x5_UNORM_SRGB:
+            return RHI::Size(10, 5, 1);
         case Format::ASTC_10x6_UNORM:
         case Format::ASTC_10x6_UNORM_SRGB:
+            return RHI::Size(10, 6, 1);
         case Format::ASTC_10x8_UNORM:
         case Format::ASTC_10x8_UNORM_SRGB:
+            return RHI::Size(10, 8, 1);
         case Format::ASTC_10x10_UNORM:
         case Format::ASTC_10x10_UNORM_SRGB:
+            return RHI::Size(10, 10, 1);
         case Format::ASTC_12x10_UNORM:
         case Format::ASTC_12x10_UNORM_SRGB:
+            return RHI::Size(12, 10, 1);
         case Format::ASTC_12x12_UNORM:
         case Format::ASTC_12x12_UNORM_SRGB:
-            return 4;
-
+            return RHI::Size(12, 12, 1);
         case Format::R8G8_B8G8_UNORM:
         case Format::G8R8_G8B8_UNORM:
         case Format::YUY2:
@@ -596,10 +608,10 @@ namespace AZ::RHI
         case Format::NV12:
         case Format::P010:
         case Format::P016:
-            return 2;
+            return RHI::Size(2, 2, 1);
 
         default:
-            return 1;
+            return RHI::Size(1, 1, 1);
         }
     }
 

+ 5 - 3
Gems/Atom/RHI/DX12/Code/Source/RHI/StreamingImagePool.cpp

@@ -439,11 +439,13 @@ namespace AZ
                 if (imageDescriptor.m_arraySize > 1)
                 {
                     // get smallest mip size
-                    uint32_t formatDiemensionAlignment = RHI::GetFormatDimensionAlignment(imageDescriptor.m_format);
+                    RHI::Size formatDimensionAlignment = RHI::GetFormatDimensionAlignment(imageDescriptor.m_format);
                     uint32_t minMipWidth = AZStd::max(imageDescriptor.m_size.m_width >> (imageDescriptor.m_mipLevels-1), 1u);
                     uint32_t minMipHeight = AZStd::max(imageDescriptor.m_size.m_height >> (imageDescriptor.m_mipLevels-1), 1u);
-                    uint32_t minMipSize = AZ::DivideAndRoundUp(minMipWidth, formatDiemensionAlignment) * AZ::DivideAndRoundUp(minMipHeight, formatDiemensionAlignment)
-                        * RHI::GetFormatSize(imageDescriptor.m_format);
+                    uint32_t minMipSize =
+                        AZ::DivideAndRoundUp(minMipWidth, formatDimensionAlignment.m_width) *
+                        AZ::DivideAndRoundUp(minMipHeight, formatDimensionAlignment.m_height) *
+                        RHI::GetFormatSize(imageDescriptor.m_format);
                     if (minMipSize < TileSizeInBytes)
                     {
                         return false;

+ 6 - 5
Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandList.cpp

@@ -127,7 +127,7 @@ namespace AZ
                 const auto* sourceBufferMemoryView = static_cast<const Buffer*>(descriptor.m_sourceBuffer)->GetBufferMemoryView();
                 const auto* destinationImage = static_cast<const Image*>(descriptor.m_destinationImage);
                 const RHI::Format format = destinationImage->GetDescriptor().m_format;
-                uint32_t formatDimensionAlignment = GetFormatDimensionAlignment(format);
+                RHI::Size formatDimensionAlignment = GetFormatDimensionAlignment(format);
 
                 // VkBufferImageCopy::bufferRowLength is specified in texels not in bytes. 
                 // Because of this we need to convert m_sourceBytesPerRow from bytes to pixels to account 
@@ -138,8 +138,8 @@ namespace AZ
 
                 VkBufferImageCopy copy{};
                 copy.bufferOffset = sourceBufferMemoryView->GetOffset() + descriptor.m_sourceOffset;
-                copy.bufferRowLength = descriptor.m_sourceBytesPerRow / GetFormatSize(format) * formatDimensionAlignment;
-                copy.bufferImageHeight = RHI::AlignUp(descriptor.m_sourceSize.m_height, formatDimensionAlignment);
+                copy.bufferRowLength = descriptor.m_sourceBytesPerRow / GetFormatSize(format) * formatDimensionAlignment.m_width;
+                copy.bufferImageHeight = RHI::AlignUp(descriptor.m_sourceSize.m_height, formatDimensionAlignment.m_height);
                 copy.imageSubresource.aspectMask = destinationImage->GetImageAspectFlags();
                 copy.imageSubresource.mipLevel = descriptor.m_destinationSubresource.m_mipSlice;
                 copy.imageSubresource.baseArrayLayer = descriptor.m_destinationSubresource.m_arraySlice;
@@ -201,6 +201,7 @@ namespace AZ
                 const auto* sourceImage = static_cast<const Image*>(descriptor.m_sourceImage);
                 const auto* destinationBufferMemoryView = static_cast<const Buffer*>(descriptor.m_destinationBuffer)->GetBufferMemoryView();
                 const RHI::Format format = descriptor.m_destinationFormat;
+                RHI::Size formatDimensionAlignment = GetFormatDimensionAlignment(format);
 
                 // VkBufferImageCopy::bufferRowLength is specified in texels not in bytes. 
                 // Because of this we need to convert m_sourceBytesPerRow from bytes to pixels to account 
@@ -211,8 +212,8 @@ namespace AZ
 
                 VkBufferImageCopy copy{};
                 copy.bufferOffset = destinationBufferMemoryView->GetOffset() + descriptor.m_destinationOffset;
-                copy.bufferRowLength = descriptor.m_destinationBytesPerRow / GetFormatSize(format) * GetFormatDimensionAlignment(format);
-                copy.bufferImageHeight = descriptor.m_sourceSize.m_height;
+                copy.bufferRowLength = descriptor.m_destinationBytesPerRow / GetFormatSize(format) * formatDimensionAlignment.m_width;
+                copy.bufferImageHeight = RHI::AlignUp(descriptor.m_sourceSize.m_height, formatDimensionAlignment.m_height);
                 copy.imageSubresource.aspectMask = ConvertImageAspect(descriptor.m_sourceSubresource.m_aspect);
                 copy.imageSubresource.mipLevel = descriptor.m_sourceSubresource.m_mipSlice;
                 copy.imageSubresource.baseArrayLayer = descriptor.m_sourceSubresource.m_arraySlice;