如何解决DXGI_FORMAT兼容性问题



我想使用计算着色器进行后期处理。因此,我们的想法是将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,R8G8B8_UNORM(无效;资源已使用完全限定的格式创建,该格式不可转换(0x57,B8G8R8A8_UNORM(。

问题是我不在乎格式是什么,因为它可以在计算着色器中固定!

有办法绕过这个吗?或者可能不使用无人机进行CS输出?

加载/存储只支持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(,则此工作稳定。不幸的是,并非所有设备都支持此功能。

请参阅ResourceUpload.cpp中DX12基于CS的mipmap生成代码GenerateMips_TexturePathBGR的DirectX工具包。

简而言之,如果设备不支持D3D12_FEATURE_DATA_D3D12_OPTIONS.StandardSwizzle64KBSupported,由于UAV不支持BGRA,我无法为以下格式生成mipmap:DXGI_FORMAT_B8G8R8A8_UNORMDXGI_FORMAT_B8G8R8X8_UNORMDXGI_FORMAT_B8G8R8A8_UNORM_SRGBDXGI_FORMAT_B8G8R8X8_UNORM_SRGB

在Xbox上,这是一个UMA架构,我知道RGBA/BGRA在内存中的布局方式相同,因此验证不会阻止该平台上的别名。一些较旧的PC驱动程序可以让您在D3D12_TEXTURE_LAYOUT_UNKNOWN上轻松完成此操作,但现代版本的验证层阻止在运行时执行此操作。

对于一些有限的场景,您可以尝试使用D3D12_TEXTURE_LAYOUT_ROW_MAJOR,但它非常慢,并且有很多限制,这使得它对DX12的DirectX工具包没有用处。

相关内容

最新更新