尝试在 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;
我正在尝试使用 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;