如何解决DXGI_FORMAT兼容性问题?

时间:2020-11-03 12:52:13

标签: c++ directx directx-11

我想使用计算着色器进行后期处理。因此,其想法是将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输出?

1 个答案:

答案 0 :(得分:2)

仅支持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),则此 only 可以正常运行。不幸的是,并非所有设备都支持此功能。

请参见ResourceUpload.cpp中的 DirectX Toolkit for DX12 的基于CS的mipmap生成代码GenerateMips_TexturePathBGR

简而言之,,如果设备不支持D3D12_FEATURE_DATA_D3D12_OPTIONS.StandardSwizzle64KBSupported,则无法生成以下格式的mipmap:DXGI_FORMAT_B8G8R8A8_UNORMDXGI_FORMAT_B8G8R8X8_UNORM,{{ 1}},DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,因为UAV不支持BGRA。

在Xbox上,它是UMA体系结构,我知道RGBA / BGRA在内存中的布局方式相同,因此验证不会阻止该平台上的别名。某些较旧的PC驱动程序可以让您DXGI_FORMAT_B8G8R8X8_UNORM_SRGB正常工作,但是现代版本的验证层会阻止在运行时执行此操作。

在某些有限的情况下,您可以尝试使用D3D12_TEXTURE_LAYOUT_UNKNOWN,但是它非常慢并且有很多limitations,这对于用于DX12的DirectX工具包来说没什么用。 >。