我如何解决 DXGI_FORMAT 兼容性问题?
How can i resolve DXGI_FORMAT compatibility issues?
我想使用计算着色器进行 post 处理。所以想法是将CS输出设置到后台缓冲区。据我所知,这意味着使用无人机。但是后台缓冲区使用 BGRA。所以这个:
Microsoft::WRL::ComPtr<ID3D11Texture2D> pBackBuffer;
pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &pBackBuffer);
D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc;
uav_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;// BGRA!
uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
uav_desc.Texture2D.MipSlice = 0;
Microsoft::WRL::ComPtr<ID3D11UnorderedAccessView> pUnorderedAccessView;
pDevice->CreateUnorderedAccessView(
pBackBuffer.Get(),
&uav_desc,
&pUnorderedAccessView);
生成错误:格式 (0x57,B8G8R8A8_UNORM) 不能用于类型化无序访问视图。
如果我尝试将格式更改为符合 MDOCS 的兼容格式:
...
uav_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;// RGBA!
...
生成错误:创建视图时,格式 (0x1c, R8G8B8A8_UNORM) 无效;资源已经使用完全限定的格式创建,该格式不可转换(0x57,B8G8R8A8_UNORM)。
问题是我不关心格式是什么,因为它可以在计算着色器中修复!
有没有办法绕过这个?或者不使用无人机进行CS输出?
loading/storing 仅支持 UAV 格式的子集,这就是 BGRA 格式失败的原因。
逻辑编码在此辅助函数中:
// typedUAVLoadAdditionalFormats is the value obtained from D3D12_FEATURE_DATA_D3D12_OPTIONS.TypedUAVLoadAdditionalFormats
bool FormatIsUAVCompatible(_In_ ID3D12Device* device, bool typedUAVLoadAdditionalFormats, DXGI_FORMAT format) noexcept
{
switch (format)
{
case DXGI_FORMAT_R32_FLOAT:
case DXGI_FORMAT_R32_UINT:
case DXGI_FORMAT_R32_SINT:
// Unconditionally supported.
return true;
case DXGI_FORMAT_R32G32B32A32_FLOAT:
case DXGI_FORMAT_R32G32B32A32_UINT:
case DXGI_FORMAT_R32G32B32A32_SINT:
case DXGI_FORMAT_R16G16B16A16_FLOAT:
case DXGI_FORMAT_R16G16B16A16_UINT:
case DXGI_FORMAT_R16G16B16A16_SINT:
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UINT:
case DXGI_FORMAT_R8G8B8A8_SINT:
case DXGI_FORMAT_R16_FLOAT:
case DXGI_FORMAT_R16_UINT:
case DXGI_FORMAT_R16_SINT:
case DXGI_FORMAT_R8_UNORM:
case DXGI_FORMAT_R8_UINT:
case DXGI_FORMAT_R8_SINT:
// All these are supported if this optional feature is set.
return typedUAVLoadAdditionalFormats;
case DXGI_FORMAT_R16G16B16A16_UNORM:
case DXGI_FORMAT_R16G16B16A16_SNORM:
case DXGI_FORMAT_R32G32_FLOAT:
case DXGI_FORMAT_R32G32_UINT:
case DXGI_FORMAT_R32G32_SINT:
case DXGI_FORMAT_R10G10B10A2_UNORM:
case DXGI_FORMAT_R10G10B10A2_UINT:
case DXGI_FORMAT_R11G11B10_FLOAT:
case DXGI_FORMAT_R8G8B8A8_SNORM:
case DXGI_FORMAT_R16G16_FLOAT:
case DXGI_FORMAT_R16G16_UNORM:
case DXGI_FORMAT_R16G16_UINT:
case DXGI_FORMAT_R16G16_SNORM:
case DXGI_FORMAT_R16G16_SINT:
case DXGI_FORMAT_R8G8_UNORM:
case DXGI_FORMAT_R8G8_UINT:
case DXGI_FORMAT_R8G8_SNORM:
case DXGI_FORMAT_R8G8_SINT:
case DXGI_FORMAT_R16_UNORM:
case DXGI_FORMAT_R16_SNORM:
case DXGI_FORMAT_R8_SNORM:
case DXGI_FORMAT_A8_UNORM:
case DXGI_FORMAT_B5G6R5_UNORM:
case DXGI_FORMAT_B5G5R5A1_UNORM:
case DXGI_FORMAT_B4G4R4A4_UNORM:
// Conditionally supported by specific devices.
if (typedUAVLoadAdditionalFormats)
{
D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupport = { format, D3D12_FORMAT_SUPPORT1_NONE, D3D12_FORMAT_SUPPORT2_NONE };
if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &formatSupport, sizeof(formatSupport))))
{
const DWORD mask = D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE;
return ((formatSupport.Support2 & mask) == mask);
}
}
return false;
default:
return false;
}
}
除了 16pp 格式(没有 RGB 版本)之外,该列表中没有 BGRA 格式。
为了支持 BGRA,您在与 RGBA UAV 相同的内存位置使用别名纹理,以便您可以重新解释数据。如果设备支持 D3D12_TEXTURE_LAYOUT_64KB_STANDARD_SWIZZLE
(即您必须检查 D3D12_FEATURE_DATA_D3D12_OPTIONS.StandardSwizzle64KBSupported
),此 仅 有效。不幸的是,并非所有设备都支持此功能。
请参阅 DirectX Tool Kit for DX12 的 CS-based mipmap 生成代码 GenerateMips_TexturePathBGR
in ResourceUpload.cpp。
简而言之, 如果设备不支持 D3D12_FEATURE_DATA_D3D12_OPTIONS.StandardSwizzle64KBSupported
,我无法为这些格式生成 mipmap:DXGI_FORMAT_B8G8R8A8_UNORM
,DXGI_FORMAT_B8G8R8X8_UNORM
, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
因为无人机不支持BGRA.
On Xbox it's a UMA architecture and I know for a fact that RGBA/BGRA are laid out the same way in memory, therefore the validation doesn't prevent the alias on that platform. Some older PC drivers let you do it without a problem with D3D12_TEXTURE_LAYOUT_UNKNOWN
, but the modern versions of the validation layer prevent doing this at runtime.
For some limited scenarios, you could try using D3D12_TEXTURE_LAYOUT_ROW_MAJOR
, but it is very slow and has a lot of limitations which made it not useful for DirectX Tool Kit for DX12.
我想使用计算着色器进行 post 处理。所以想法是将CS输出设置到后台缓冲区。据我所知,这意味着使用无人机。但是后台缓冲区使用 BGRA。所以这个:
Microsoft::WRL::ComPtr<ID3D11Texture2D> pBackBuffer;
pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &pBackBuffer);
D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc;
uav_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;// BGRA!
uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
uav_desc.Texture2D.MipSlice = 0;
Microsoft::WRL::ComPtr<ID3D11UnorderedAccessView> pUnorderedAccessView;
pDevice->CreateUnorderedAccessView(
pBackBuffer.Get(),
&uav_desc,
&pUnorderedAccessView);
生成错误:格式 (0x57,B8G8R8A8_UNORM) 不能用于类型化无序访问视图。
如果我尝试将格式更改为符合 MDOCS 的兼容格式:
...
uav_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;// RGBA!
...
生成错误:创建视图时,格式 (0x1c, R8G8B8A8_UNORM) 无效;资源已经使用完全限定的格式创建,该格式不可转换(0x57,B8G8R8A8_UNORM)。
问题是我不关心格式是什么,因为它可以在计算着色器中修复!
有没有办法绕过这个?或者不使用无人机进行CS输出?
loading/storing 仅支持 UAV 格式的子集,这就是 BGRA 格式失败的原因。
逻辑编码在此辅助函数中:
// typedUAVLoadAdditionalFormats is the value obtained from D3D12_FEATURE_DATA_D3D12_OPTIONS.TypedUAVLoadAdditionalFormats
bool FormatIsUAVCompatible(_In_ ID3D12Device* device, bool typedUAVLoadAdditionalFormats, DXGI_FORMAT format) noexcept
{
switch (format)
{
case DXGI_FORMAT_R32_FLOAT:
case DXGI_FORMAT_R32_UINT:
case DXGI_FORMAT_R32_SINT:
// Unconditionally supported.
return true;
case DXGI_FORMAT_R32G32B32A32_FLOAT:
case DXGI_FORMAT_R32G32B32A32_UINT:
case DXGI_FORMAT_R32G32B32A32_SINT:
case DXGI_FORMAT_R16G16B16A16_FLOAT:
case DXGI_FORMAT_R16G16B16A16_UINT:
case DXGI_FORMAT_R16G16B16A16_SINT:
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UINT:
case DXGI_FORMAT_R8G8B8A8_SINT:
case DXGI_FORMAT_R16_FLOAT:
case DXGI_FORMAT_R16_UINT:
case DXGI_FORMAT_R16_SINT:
case DXGI_FORMAT_R8_UNORM:
case DXGI_FORMAT_R8_UINT:
case DXGI_FORMAT_R8_SINT:
// All these are supported if this optional feature is set.
return typedUAVLoadAdditionalFormats;
case DXGI_FORMAT_R16G16B16A16_UNORM:
case DXGI_FORMAT_R16G16B16A16_SNORM:
case DXGI_FORMAT_R32G32_FLOAT:
case DXGI_FORMAT_R32G32_UINT:
case DXGI_FORMAT_R32G32_SINT:
case DXGI_FORMAT_R10G10B10A2_UNORM:
case DXGI_FORMAT_R10G10B10A2_UINT:
case DXGI_FORMAT_R11G11B10_FLOAT:
case DXGI_FORMAT_R8G8B8A8_SNORM:
case DXGI_FORMAT_R16G16_FLOAT:
case DXGI_FORMAT_R16G16_UNORM:
case DXGI_FORMAT_R16G16_UINT:
case DXGI_FORMAT_R16G16_SNORM:
case DXGI_FORMAT_R16G16_SINT:
case DXGI_FORMAT_R8G8_UNORM:
case DXGI_FORMAT_R8G8_UINT:
case DXGI_FORMAT_R8G8_SNORM:
case DXGI_FORMAT_R8G8_SINT:
case DXGI_FORMAT_R16_UNORM:
case DXGI_FORMAT_R16_SNORM:
case DXGI_FORMAT_R8_SNORM:
case DXGI_FORMAT_A8_UNORM:
case DXGI_FORMAT_B5G6R5_UNORM:
case DXGI_FORMAT_B5G5R5A1_UNORM:
case DXGI_FORMAT_B4G4R4A4_UNORM:
// Conditionally supported by specific devices.
if (typedUAVLoadAdditionalFormats)
{
D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupport = { format, D3D12_FORMAT_SUPPORT1_NONE, D3D12_FORMAT_SUPPORT2_NONE };
if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &formatSupport, sizeof(formatSupport))))
{
const DWORD mask = D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE;
return ((formatSupport.Support2 & mask) == mask);
}
}
return false;
default:
return false;
}
}
除了 16pp 格式(没有 RGB 版本)之外,该列表中没有 BGRA 格式。
为了支持 BGRA,您在与 RGBA UAV 相同的内存位置使用别名纹理,以便您可以重新解释数据。如果设备支持 D3D12_TEXTURE_LAYOUT_64KB_STANDARD_SWIZZLE
(即您必须检查 D3D12_FEATURE_DATA_D3D12_OPTIONS.StandardSwizzle64KBSupported
),此 仅 有效。不幸的是,并非所有设备都支持此功能。
请参阅 DirectX Tool Kit for DX12 的 CS-based mipmap 生成代码 GenerateMips_TexturePathBGR
in ResourceUpload.cpp。
简而言之, 如果设备不支持 D3D12_FEATURE_DATA_D3D12_OPTIONS.StandardSwizzle64KBSupported
,我无法为这些格式生成 mipmap:DXGI_FORMAT_B8G8R8A8_UNORM
,DXGI_FORMAT_B8G8R8X8_UNORM
, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
因为无人机不支持BGRA.
On Xbox it's a UMA architecture and I know for a fact that RGBA/BGRA are laid out the same way in memory, therefore the validation doesn't prevent the alias on that platform. Some older PC drivers let you do it without a problem with
D3D12_TEXTURE_LAYOUT_UNKNOWN
, but the modern versions of the validation layer prevent doing this at runtime.
For some limited scenarios, you could try using
D3D12_TEXTURE_LAYOUT_ROW_MAJOR
, but it is very slow and has a lot of limitations which made it not useful for DirectX Tool Kit for DX12.