我如何解决 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_UNORMDXGI_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.