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

问题描述

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

但是我在尝试在类似的 2d 纹理上创建无序访问视图时遇到了困难。 CreateUnorderedAccessView(...) 返回 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。另见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;

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...