Skip to content

Commit 7b79268

Browse files
hzqstTheMostDiligent
authored andcommitted
Vulkan: Map RGB10A2 formats to A2B10G10R10
TEX_FORMAT_RGB10A2_* stores red in bits 0-9, like DXGI_FORMAT_R10G10B10A2 and GL_RGB10_A2, which is VK_FORMAT_A2B10G10R10_*_PACK32. The A2R10G10B10 formats used before swap red and blue, do not match the SPIR-V Rgb10A2/Rgb10a2ui image formats and have no guaranteed storage image support, so RGB10A2 UAVs were unavailable on devices such as the RTX 5060. Add ClearRenderTargetTest.RGB10A2BitLayout, which checks the raw bits of a red clear on every backend.
1 parent e92840a commit 7b79268

2 files changed

Lines changed: 72 additions & 7 deletions

File tree

‎Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,11 @@ class TexFormatToVkFormatMapper
7474
m_FmtToVkFmtMap[TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS] = VK_FORMAT_D32_SFLOAT_S8_UINT;
7575
m_FmtToVkFmtMap[TEX_FORMAT_X32_TYPELESS_G8X24_UINT] = VK_FORMAT_UNDEFINED;
7676

77-
m_FmtToVkFmtMap[TEX_FORMAT_RGB10A2_TYPELESS] = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
78-
m_FmtToVkFmtMap[TEX_FORMAT_RGB10A2_UNORM] = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
79-
m_FmtToVkFmtMap[TEX_FORMAT_RGB10A2_UINT] = VK_FORMAT_A2R10G10B10_UINT_PACK32;
77+
// RGB10A2 stores R in the low bits (DXGI_FORMAT_R10G10B10A2, GL_RGB10_A2), which is A2B10G10R10 in Vulkan.
78+
// It is also the format of the SPIR-V Rgb10A2/Rgb10a2ui image formats and the one with guaranteed storage support.
79+
m_FmtToVkFmtMap[TEX_FORMAT_RGB10A2_TYPELESS] = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
80+
m_FmtToVkFmtMap[TEX_FORMAT_RGB10A2_UNORM] = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
81+
m_FmtToVkFmtMap[TEX_FORMAT_RGB10A2_UINT] = VK_FORMAT_A2B10G10R10_UINT_PACK32;
8082
m_FmtToVkFmtMap[TEX_FORMAT_R11G11B10_FLOAT] = VK_FORMAT_B10G11R11_UFLOAT_PACK32;
8183

8284
m_FmtToVkFmtMap[TEX_FORMAT_RGBA8_TYPELESS] = VK_FORMAT_R8G8B8A8_UNORM;
@@ -263,18 +265,18 @@ class VkFormatToTexFormatMapper
263265
m_VkFmtToTexFmtMap[VK_FORMAT_A8B8G8R8_SINT_PACK32] = TEX_FORMAT_UNKNOWN;
264266
m_VkFmtToTexFmtMap[VK_FORMAT_A8B8G8R8_SRGB_PACK32] = TEX_FORMAT_UNKNOWN;
265267

266-
m_VkFmtToTexFmtMap[VK_FORMAT_A2R10G10B10_UNORM_PACK32] = TEX_FORMAT_RGB10A2_UNORM;
268+
m_VkFmtToTexFmtMap[VK_FORMAT_A2R10G10B10_UNORM_PACK32] = TEX_FORMAT_UNKNOWN;
267269
m_VkFmtToTexFmtMap[VK_FORMAT_A2R10G10B10_SNORM_PACK32] = TEX_FORMAT_UNKNOWN;
268270
m_VkFmtToTexFmtMap[VK_FORMAT_A2R10G10B10_USCALED_PACK32] = TEX_FORMAT_UNKNOWN;
269271
m_VkFmtToTexFmtMap[VK_FORMAT_A2R10G10B10_SSCALED_PACK32] = TEX_FORMAT_UNKNOWN;
270-
m_VkFmtToTexFmtMap[VK_FORMAT_A2R10G10B10_UINT_PACK32] = TEX_FORMAT_RGB10A2_UINT;
272+
m_VkFmtToTexFmtMap[VK_FORMAT_A2R10G10B10_UINT_PACK32] = TEX_FORMAT_UNKNOWN;
271273
m_VkFmtToTexFmtMap[VK_FORMAT_A2R10G10B10_SINT_PACK32] = TEX_FORMAT_UNKNOWN;
272274

273-
m_VkFmtToTexFmtMap[VK_FORMAT_A2B10G10R10_UNORM_PACK32] = TEX_FORMAT_UNKNOWN;
275+
m_VkFmtToTexFmtMap[VK_FORMAT_A2B10G10R10_UNORM_PACK32] = TEX_FORMAT_RGB10A2_UNORM;
274276
m_VkFmtToTexFmtMap[VK_FORMAT_A2B10G10R10_SNORM_PACK32] = TEX_FORMAT_UNKNOWN;
275277
m_VkFmtToTexFmtMap[VK_FORMAT_A2B10G10R10_USCALED_PACK32] = TEX_FORMAT_UNKNOWN;
276278
m_VkFmtToTexFmtMap[VK_FORMAT_A2B10G10R10_SSCALED_PACK32] = TEX_FORMAT_UNKNOWN;
277-
m_VkFmtToTexFmtMap[VK_FORMAT_A2B10G10R10_UINT_PACK32] = TEX_FORMAT_UNKNOWN;
279+
m_VkFmtToTexFmtMap[VK_FORMAT_A2B10G10R10_UINT_PACK32] = TEX_FORMAT_RGB10A2_UINT;
278280
m_VkFmtToTexFmtMap[VK_FORMAT_A2B10G10R10_SINT_PACK32] = TEX_FORMAT_UNKNOWN;
279281

280282
m_VkFmtToTexFmtMap[VK_FORMAT_R16_UNORM] = TEX_FORMAT_R16_UNORM;

‎Tests/DiligentCoreAPITest/src/ClearRenderTargetTest.cpp‎

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,4 +491,67 @@ TEST(ClearRenderTargetTest, LoadOpClear2)
491491
TestClearWithLoadOp({0.375f, 0.75, 0.125, 1.0f}, 2);
492492
}
493493

494+
// TEX_FORMAT_RGB10A2_UNORM has the layout of DXGI_FORMAT_R10G10B10A2_UNORM and GL_RGB10_A2: red in the low 10 bits
495+
// and alpha in the high 2 bits. Every backend must store a red clear with this layout.
496+
TEST(ClearRenderTargetTest, RGB10A2BitLayout)
497+
{
498+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
499+
IRenderDevice* pDevice = pEnv->GetDevice();
500+
IDeviceContext* pContext = pEnv->GetDeviceContext();
501+
502+
if ((pDevice->GetTextureFormatInfoExt(TEX_FORMAT_RGB10A2_UNORM).BindFlags & BIND_RENDER_TARGET) == 0)
503+
{
504+
GTEST_SKIP() << "RGB10A2 render targets are not supported by this device";
505+
}
506+
507+
GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
508+
509+
TextureDesc TexDesc;
510+
TexDesc.Name = "ClearRenderTargetTest.RGB10A2BitLayout";
511+
TexDesc.Type = RESOURCE_DIM_TEX_2D;
512+
TexDesc.Width = 4;
513+
TexDesc.Height = 4;
514+
TexDesc.Format = TEX_FORMAT_RGB10A2_UNORM;
515+
TexDesc.BindFlags = BIND_RENDER_TARGET;
516+
RefCntAutoPtr<ITexture> pTex;
517+
pDevice->CreateTexture(TexDesc, nullptr, &pTex);
518+
ASSERT_NE(pTex, nullptr);
519+
520+
TexDesc.Name = "ClearRenderTargetTest.RGB10A2BitLayout staging";
521+
TexDesc.Usage = USAGE_STAGING;
522+
TexDesc.BindFlags = BIND_NONE;
523+
TexDesc.CPUAccessFlags = CPU_ACCESS_READ;
524+
RefCntAutoPtr<ITexture> pStagingTex;
525+
pDevice->CreateTexture(TexDesc, nullptr, &pStagingTex);
526+
ASSERT_NE(pStagingTex, nullptr);
527+
528+
ITextureView* pRTVs[] = {pTex->GetDefaultView(TEXTURE_VIEW_RENDER_TARGET)};
529+
pContext->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
530+
constexpr float Red[] = {1, 0, 0, 1};
531+
pContext->ClearRenderTarget(pRTVs[0], Red, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
532+
pContext->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_NONE);
533+
534+
pContext->CopyTexture(CopyTextureAttribs{pTex, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, pStagingTex, RESOURCE_STATE_TRANSITION_MODE_TRANSITION});
535+
pContext->WaitForIdle();
536+
537+
// Some Intel D3D11 drivers return null with DO_NOT_WAIT even after WaitForIdle().
538+
const MAP_FLAGS MapFlags = pDevice->GetDeviceInfo().Type == RENDER_DEVICE_TYPE_D3D11 ? MAP_FLAG_NONE : MAP_FLAG_DO_NOT_WAIT;
539+
MappedTextureSubresource MappedData;
540+
pContext->MapTextureSubresource(pStagingTex, 0, 0, MAP_READ, MapFlags, nullptr, MappedData);
541+
ASSERT_NE(MappedData.pData, nullptr);
542+
543+
constexpr Uint32 RedTexel = (3u << 30) | 0x3FFu;
544+
for (Uint32 Row = 0; Row < TexDesc.Height; ++Row)
545+
{
546+
const Uint8* pRow = static_cast<const Uint8*>(MappedData.pData) + Row * MappedData.Stride;
547+
for (Uint32 Col = 0; Col < TexDesc.Width; ++Col)
548+
{
549+
Uint32 Texel = 0;
550+
memcpy(&Texel, pRow + Col * sizeof(Texel), sizeof(Texel));
551+
EXPECT_EQ(Texel, RedTexel) << "Texel (" << Col << ", " << Row << "): expected red in bits 0-9 and alpha in bits 30-31";
552+
}
553+
}
554+
pContext->UnmapTextureSubresource(pStagingTex, 0, 0);
555+
}
556+
494557
} // namespace

0 commit comments

Comments
 (0)