使用动态格式创建二维纹理时出错
error when creating 2d texture with dynamic format
我是 directx 的新手。
我在处理资源方面遇到了困难。
好的,首先,我创建了可以在 GPU 中 read/write 的纹理,并且效果很好。
现在,您可以查看我的代码,我也想在 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()'
时开始失败
任何建议都会很棒。
调试任何 Direct3D 11 程序的前两个步骤是:
- 确保检查每个
HRESULT
是否成功(SUCCEEDED
宏)或失败(FAILED
宏)。如果在运行时忽略 return 值是安全的,那么函数 returns void
。参见 ThrowIfFailed。
- 启用 Direct3D 调试设备并查找调试输出(a.k.a。在调试配置中使用
D3D11_CREATE_DEVICE_DEBUG
)。
如果您启用 Direct3D debug device,您将获得有关 API return 为什么在许多情况下出现故障代码的详细信息。
如果这样做,您会看到以下代码的错误:
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 code from 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]
为了从 cpu(读取模式)访问纹理,您需要创建一个单独的暂存纹理,然后将您的纹理复制到其中。
这些是仅 gpu 纹理的标志(请注意我将样本数强制设置为 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
readTexDesc.SampleDesc.Count = 1;
readTexDesc.SampleDesc.Quality = 0;
readTexDesc.Usage = D3D11_USAGE_STAGING; //need staging flag for read
readTexDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
readTexDesc.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);
我是 directx 的新手。 我在处理资源方面遇到了困难。
好的,首先,我创建了可以在 GPU 中 read/write 的纹理,并且效果很好。 现在,您可以查看我的代码,我也想在 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()'
时开始失败任何建议都会很棒。
调试任何 Direct3D 11 程序的前两个步骤是:
- 确保检查每个
HRESULT
是否成功(SUCCEEDED
宏)或失败(FAILED
宏)。如果在运行时忽略 return 值是安全的,那么函数 returnsvoid
。参见 ThrowIfFailed。 - 启用 Direct3D 调试设备并查找调试输出(a.k.a。在调试配置中使用
D3D11_CREATE_DEVICE_DEBUG
)。
如果您启用 Direct3D debug device,您将获得有关 API return 为什么在许多情况下出现故障代码的详细信息。
如果这样做,您会看到以下代码的错误:
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 code from 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]
为了从 cpu(读取模式)访问纹理,您需要创建一个单独的暂存纹理,然后将您的纹理复制到其中。
这些是仅 gpu 纹理的标志(请注意我将样本数强制设置为 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
readTexDesc.SampleDesc.Count = 1;
readTexDesc.SampleDesc.Quality = 0;
readTexDesc.Usage = D3D11_USAGE_STAGING; //need staging flag for read
readTexDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
readTexDesc.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);