动态格式创建2D纹理时出现错误

时间:2019-05-07 06:58:39

标签: directx shader gpgpu directx-11 compute-shader

我是DirectX上的新手。 而且我在处理资源方面绊脚石。

好的,首先,我创建了可以在GPU中读取/写入的纹理,并且效果很好。 现在,您可以检查我的代码,我也想在CPU中读取此纹理(从应用程序端读取),因此我将用法从USAGE_DEFAULT修改为USAGE_DYNAMIC。

Microsoft::WRL::ComPtr<ID3D11Texture2D> outputTexture;

D3D11_TEXTURE2D_DESC outputTex_desc;
outputTex_desc.Format = DXGI_FORMAT_R32_FLOAT;
outputTex_desc.Width = 3;
outputTex_desc.Height = 3;
outputTex_desc.MipLevels = 1;
outputTex_desc.ArraySize = 1;
outputTex_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | 
                           D3D11_BIND_SHADER_RESOURCE;
outputTex_desc.SampleDesc.Count = msCount;
outputTex_desc.SampleDesc.Quality = msQuality;
outputTex_desc.Usage = D3D11_USAGE_DYNAMIC;
outputTex_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
outputTex_desc.MiscFlags = 0;

// CREATE 'TEXTURE'
device->CreateTexture2D(      // FAIL HERE !!!
            &outputTex_desc,
            nullptr,
            outputTexture.GetAddressOf());
// CREATE 'SRV'
...
// CREATE 'UAV'
...

,并且在执行'device-> CreateTexture2D()'时开始完全失败

任何建议都很棒。

2 个答案:

答案 0 :(得分:1)

调试任何Direct3D 11程序的前两个步骤是:

  1. 确保检查每个HRESULT是否成功(SUCCEEDED宏)或失败(FAILED宏)。如果在运行时可以安全地忽略返回值,则该函数返回void。参见ThrowIfFailed
  2. 启用Direct3D调试设备并查找调试输出(也可以在Debug配置中使用D3D11_CREATE_DEVICE_DEBUG)。

如果启用Direct3D debug device,您将获得有关API在许多情况下为何返回失败代码的详细信息。

如果这样做,则会看到此代码的错误:

D3D11 ERROR: ID3D11Device::CreateTexture2D: A D3D11_USAGE_DYNAMIC Resource
may only have the D3D11_CPU_ACCESS_WRITE CPUAccessFlags set.
[ STATE_CREATION ERROR #98: CREATETEXTURE2D_INVALIDCPUACCESSFLAGS]

要在CPU上读取,必须首先将其复制到D3D11_USAGE_STAGING资源中。例如,有关此操作的源代码,请参见ScreenGrab中的DirectX Tool Kit代码。

您不会在这里提及您的msCountmsQuality值。我分别假设1和0。如果您使用其他任何值,则会得到:

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]

答案 1 :(得分:0)

要从cpu(读取模式)访问纹理,您需要创建一个单独的暂存纹理,然后将纹理复制到其中。

这些是仅用于gpu的纹理的标志(请注意,由于多采样纹理不允许UAV访问,因此我将样本数强制为1)

D3D11_TEXTURE2D_DESC gpuTexDesc;
gpuTexDesc.Format = DXGI_FORMAT_R32_FLOAT;
gpuTexDesc.Width = 3;
gpuTexDesc.Height = 3;
gpuTexDesc.MipLevels = 1;
gpuTexDesc.ArraySize = 1;
gpuTexDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | 
                       D3D11_BIND_SHADER_RESOURCE;
gpuTexDesc.SampleDesc.Count = 1;
gpuTexDesc.SampleDesc.Quality = 0;
gpuTexDesc.Usage = D3D11_USAGE_DEFAULT;
gpuTexDesc.CPUAccessFlags = D3D11_CPU_ACCESS_NONE;
gpuTexDesc.MiscFlags = 0;

然后创建第二个纹理以供阅读

D3D11_TEXTURE2D_DESC readTexDesc;
readTexDesc.Format = DXGI_FORMAT_R32_FLOAT;
readTexDesc.Width = 3;
readTexDesc.Height = 3;
readTexDesc.MipLevels = 1;
readTexDesc.ArraySize = 1;
readTexDesc.BindFlags = 0; //No bind flags allowed for staging
gpuTexDesc.SampleDesc.Count = 1;
gpuTexDesc.SampleDesc.Quality = 0;
gpuTexDesc.Usage = D3D11_USAGE_STAGING; //need staging flag for read
gpuTexDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
gpuTexDesc.MiscFlags = 0;

然后您可以使用CopyResource

deviceContext->CopyResource(readTex, gpuTex);

完成后,您最终可以使用Map

访问纹理数据以进行读取
D3D11_MAPPED_SUBRESOURCE MappedResource;
deviceContext->Map(readTex, 0, D3D11_MAP_READ, 0, &MappedResource);

MappedResource将使您能够访问cpu中的数据,一旦完成处理,别忘了Unmap资源。

deviceContext->Unmap(readTex, 0);