Change decompressed type of compressed RGB formats For both VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK and VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, the internal representation was a 24 bit BGR8 format, which isn't supported by the texture sampling code, not is it intended to add support for these formats. These BGR8 formats were changed to BGRA8 formats, with the A8 value cleared to 0xFF. Also fixed 3D compressed textures by taking depth into account. Tests: dEQP-VK.pipeline.image.*etc2_r8g8b8_* Bug b/119620767 Change-Id: I9dd5c34519c9270580170c70b82c2e62fdbba3da Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30709 Presubmit-Ready: Alexis Hétu <sugoi@google.com> Tested-by: Alexis Hétu <sugoi@google.com> Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp index 5138d39..20dadd4 100644 --- a/src/Pipeline/SamplerCore.cpp +++ b/src/Pipeline/SamplerCore.cpp
@@ -247,6 +247,7 @@ case VK_FORMAT_R16G16_UNORM: case VK_FORMAT_R16G16B16A16_UNORM: case VK_FORMAT_B8G8R8A8_UNORM: + case VK_FORMAT_B8G8R8A8_SRGB: case VK_FORMAT_R8G8B8A8_UNORM: case VK_FORMAT_R8G8B8A8_SRGB: case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: @@ -1548,6 +1549,7 @@ switch(state.textureFormat) { case VK_FORMAT_B8G8R8A8_UNORM: + case VK_FORMAT_B8G8R8A8_SRGB: c.z = As<Short4>(UnpackLow(c.x, c.y)); c.x = As<Short4>(UnpackHigh(c.x, c.y)); c.y = c.z;
diff --git a/src/Vulkan/VkFormat.cpp b/src/Vulkan/VkFormat.cpp index 0f6558b..f278c22 100644 --- a/src/Vulkan/VkFormat.cpp +++ b/src/Vulkan/VkFormat.cpp
@@ -359,9 +359,9 @@ switch(format) { case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: - return VK_FORMAT_B8G8R8_UNORM; + return VK_FORMAT_B8G8R8A8_UNORM; case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: - return VK_FORMAT_B8G8R8_SRGB; + return VK_FORMAT_B8G8R8A8_SRGB; case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: return VK_FORMAT_B8G8R8A8_UNORM;
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp index 8db41e8..fbd8b2e 100644 --- a/src/Vulkan/VkImage.cpp +++ b/src/Vulkan/VkImage.cpp
@@ -864,21 +864,41 @@ uint32_t lastLayer = getLastLayerIndex(subresourceRange); uint32_t lastMipLevel = getLastMipLevel(subresourceRange); + int bytes = decompressedImage->format.bytes(); + bool fakeAlpha = (format == VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK) || (format == VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK); + size_t sizeToWrite = 0; + VkImageSubresourceLayers subresourceLayers = { subresourceRange.aspectMask, subresourceRange.baseMipLevel, subresourceRange.baseArrayLayer, 1 }; for(; subresourceLayers.baseArrayLayer <= lastLayer; subresourceLayers.baseArrayLayer++) { for(; subresourceLayers.mipLevel <= lastMipLevel; subresourceLayers.mipLevel++) { - uint8_t* source = static_cast<uint8_t*>(getTexelPointer({ 0, 0, 0 }, subresourceLayers)); - uint8_t* dest = static_cast<uint8_t*>(decompressedImage->getTexelPointer({ 0, 0, 0 }, subresourceLayers)); - VkExtent3D mipLevelExtent = getMipLevelExtent(subresourceLayers.mipLevel); - int bytes = decompressedImage->format.bytes(); int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresourceLayers.mipLevel); - ETC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height, - mipLevelExtent.width, mipLevelExtent.height, pitchB, bytes, inputType); + if(fakeAlpha) + { + // To avoid overflow in case of cube textures, which are offset in memory to account for the border, + // compute the size from the first pixel to the last pixel, excluding any padding or border before + // the first pixel or after the last pixel. + sizeToWrite = ((mipLevelExtent.height - 1) * pitchB) + (mipLevelExtent.width * bytes); + } + + for(int32_t depth = 0; depth < static_cast<int32_t>(mipLevelExtent.depth); depth++) + { + uint8_t* source = static_cast<uint8_t*>(getTexelPointer({ 0, 0, depth }, subresourceLayers)); + uint8_t* dest = static_cast<uint8_t*>(decompressedImage->getTexelPointer({ 0, 0, depth }, subresourceLayers)); + + if(fakeAlpha) + { + ASSERT((dest + sizeToWrite) < decompressedImage->end()); + memset(dest, 0xFF, sizeToWrite); + } + + ETC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height, + mipLevelExtent.width, mipLevelExtent.height, pitchB, bytes, inputType); + } } } }