尝试在 2D 纹理上创建无序访问视图

Trying to create Unordered Access View on a 2D texture

我正在尝试使用 GPU 在 2D 数组上做一些数学运算,我将其作为简单的 2d 纹理(在 R32_FLOAT 中)提供给计算着色器,没有 mipmap,与着色器资源视图相关联。它们工作,它们被传递到着色器,并且是可寻址的。

但是我在尝试在类似的 2d 纹理上创建无序访问视图时遇到了困难。 CreateUnorderedAccessView(...) returns E_INVALIDARG,但我不知道如何将其扩展到更多细节。每当我使用 D3D_BIND_UNORDERED_ACCESS 标志时,CreateTexture2D(...) 都会发生同样的问题。

我的电脑支持D3D11_0和cs_5_0。这是我的代码:

HRESULT Create_Simple_Texture_2D(ID3D11Device* device, ID3D11Texture2D** texture, UINT width, UINT height, void* initdata, UINT initsize)
{
    *texture = nullptr; 
    
    UINT elementsize = sizeof(float);
    
    DXGI_FORMAT format = DXGI_FORMAT_R32_FLOAT;

    D3D11_TEXTURE2D_DESC desc = {};
    {

// this works
//        desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;    // input to GPU
//        desc.Usage = D3D11_USAGE_DEFAULT;               // GPU read&write
//        desc.CPUAccessFlags = 0;                        // no CPU access

// this works too
//        desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;  // input to GPU
//        desc.Usage = D3D11_USAGE_DYNAMIC;             // CPU write -> GPU read
//        desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // CPU write

// and this
//        desc.BindFlags = 0;                             // 
//        desc.Usage = D3D11_USAGE_STAGING;               //
//        desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;    // CPU read

// BUT NOT THIS:
        desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
        desc.Usage = D3D11_USAGE_DEFAULT;               // GPU read&write
        desc.CPUAccessFlags = 0;                        // no CPU access, except at creation


        desc.Width = width;
        desc.Height = height;
        desc.Format = format;                           // see above
        desc.ArraySize = 1;                             // single texture
        desc.MipLevels = 1;                             // no other mipmaps
        desc.MiscFlags = 0;
        {
            desc.SampleDesc.Count = 1;
            desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
        }
    }

    const UINT expected = desc.Width * desc.Height * desc.ArraySize * elementsize;

    if (initdata && (initsize != expected)) wcprintf("\n\tWARNING: declared array size mismatch in Create_Simple_Texture_2D(...)\n\n");

    D3D11_SUBRESOURCE_DATA sub = {};
    {
        sub.pSysMem = (void*)(new char[expected]);
        sub.SysMemPitch = desc.Width * elementsize;
        sub.SysMemSlicePitch = 0;
        const UINT copysize = min(expected, initsize);
        if (sub.pSysMem && initdata && copysize) memcpy((void*)sub.pSysMem, initdata, copysize);
    }

    HRESULT result = device->CreateTexture2D(&desc, &sub, texture);
    
    if (sub.pSysMem) delete[] sub.pSysMem;

    return result;
}

TL;DR: 启用 Direct3D debug device. See also this blog post.

这里的问题是您使用 desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;

启用时的 Direct3D 调试层会告诉您:

D3D11 ERROR: ID3D11Device::CreateTexture2D: Multisampling is not supported with the D3D11_BIND_UNORDERED_ACCESS BindFlag.
SampleDesc.Count must be 1 and SampleDesc.Quality must be 0.
[ STATE_CREATION ERROR #99: CREATETEXTURE2D_INVALIDBINDFLAGS]

您通常用它来表示“无 MSAA”

desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;

由于您已经开始使用带有 D3D11_TEXTURE2D_DESC desc = {}; 的零填充结构,只需完全删除 desc.SampleDesc.Quality 集就可以了。

D3D11_TEXTURE2D_DESC desc = {};
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.Width = width;
desc.Height = height;
desc.Format = DXGI_FORMAT_R32_FLOAT;
desc.ArraySize = desc.MipLevels = desc.SampleDesc.Count = 1;