我是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()'时开始完全失败
任何建议都很棒。
答案 0 :(得分:1)
调试任何Direct3D 11程序的前两个步骤是:
HRESULT
是否成功(SUCCEEDED
宏)或失败(FAILED
宏)。如果在运行时可以安全地忽略返回值,则该函数返回void
。参见ThrowIfFailed。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代码。
您不会在这里提及您的msCount
或msQuality
值。我分别假设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);