简体   繁体   English

纹理回读显示 DirectX 11 全为 0

[英]Texture readback showing all 0s for DirectX 11

I am new to working with textures and DirectX and having issues reading back texture data from the GPU.我不熟悉使用纹理和 DirectX,并且在从 GPU 读取纹理数据时遇到问题。

I am interested in reading back only a specific subset of my source texture.我有兴趣只回读我的源纹理的特定子集。 Also, I am trying to read it back at the least detailed miplevel (1x1 texture).此外,我正在尝试以最不详细的 miplevel(1x1 纹理)读回它。 Steps I follow:我遵循的步骤:

  1. Copy subregion of source texture into new texture将源纹理的子区域复制到新纹理中
D3D11_TEXTURE2D_DESC desc = {0}; 
desc.Width = 1;
desc.Height = 1;
desc.MipLevels = 0;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
desc.CPUAccessFlags = 0;
desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;

hr = pD3D11Device->CreateTexture2D(&desc, nullptr, &pSrcTexture);

D3D11_BOX srcRegion = {0};
srcRegion.left = 1000;
srcRegion.right = 1250;
srcRegion.top = 500;
srcRegion.bottom = 750;
srcRegion.front = 0;
srcRegion.back = 1;

pD3D11DeviceContext->CopySubresourceRegion(pSrcTexture, 0, 0, 0, 0, srcResource, 0, &srcRegion);

2. Create shader resource view and generate mipmaps for newly created texture 2.创建着色器资源视图并为新创建的纹理生成mipmaps

D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {0};
srvDesc.Format = desc.Format;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = -1;
srvDesc.Texture2D.MostDetailedMip = 0;

ID3D11ShaderResourceView* pShaderResourceView = nullptr;
hr = pD3D11Device->CreateShaderResourceView(pSrcTexture, &srvDesc, &pShaderResourceView);

pD3D11DeviceContext->GenerateMips(pShaderResourceView);

3. Copy into staging texture to be read back by CPU 3.复制到暂存纹理中由CPU读回

D3D11_TEXTURE2D_DESC desc2 = {0};
desc2.Width = 1;
desc2.Height = 1;
desc2.MipLevels = 1;
desc2.ArraySize = 1;
desc2.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc2.SampleDesc.Count = 1;
desc2.SampleDesc.Quality = 0;
desc2.Usage = D3D11_USAGE_STAGING;
desc2.BindFlags = 0;
desc2.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc2.MiscFlags = 0;

ID3D11Texture2D* pStagingTexture = nullptr;
hr = pD3D11Device->CreateTexture2D(&desc2, nullptr, &pStagingTexture);

pD3D11DeviceContext->CopyResource(pStagingTexture, pSrcTexture);

4. Map the subresource to access the underlying data, unmapping when finished 4. Map 访问底层数据的子资源,完成后取消映射

D3D11_MAPPED_SUBRESOURCE mappedResource = {0};

hr = pD3D11DeviceContext->Map(pStagingTexture, 0, D3D11_MAP_READ, 0, &mappedResource);

FLOAT* pTexels = (FLOAT*)mappedResource.pData;
std::cout << pTextels[0] <<  pTextels[1] << pTextels[2] << pTextels[3] << std::endl; // all zeros here


pD3D11DeviceContext->Unmap(pStagingTexture, 0);

Please note that none of my hr results are failing.请注意,我的 hr 结果都没有失败。 Why is my texture data showing as all zeros?为什么我的纹理数据显示为全零? Any guidance on how to resolve?关于如何解决的任何指导?

CopyResource , CopySubresourceRegion , and GenerateMips do not return a HRESULT , but it may have failed in any of those functions. CopyResourceCopySubresourceRegionGenerateMips不返回HRESULT ,但它可能在这些函数中的任何一个中都失败了。 A good way to determine that is to enable the Direct3D Debug Device to look for debug output. See this blog post and Microsoft Docs .确定这一点的一个好方法是启用 Direct3D 调试设备以查找调试 output。请参阅此博客文章Microsoft Docs

I suspect the problem is that you when called GenerateMips it didn't do anything because you provided a 1x1 texture as the starting place so it doesn't have any mips.我怀疑问题是你在调用GenerateMips时它没有做任何事情,因为你提供了一个 1x1 纹理作为起始位置,所以它没有任何 mips。 I also don't see how you set up srcResource , but you are trying to copy using CopySubresourceRegion from a 250x250 texture region to a 1x1 texture which is going to fail as well.我也没有看到您是如何设置srcResource的,但是您正尝试使用CopySubresourceRegion从 250x250 纹理区域复制到 1x1 纹理,这也会失败。

You should take a look at DirectXTK and the DDSTextureLoader / WICTextureLoader modules in particular which implement auto-mip generation, and ScreenGrab which does read-back.您应该特别查看DirectXTKDDSTextureLoader / WICTextureLoader模块,它们实现自动 mip 生成,以及执行回读的ScreenGrab

One minor note: = {0};一个小音符: = {0}; was a way to zero-fill structs back in VS 2013 or earlier.是一种在 VS 2013 或更早版本中对结构进行零填充的方法。 With C++11 conformant compilers (VS 2015 or later), just use = {};使用 C++11 兼容编译器(VS 2015 或更高版本),只需使用= {}; as that does the zero-fill.就像填零一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM