[英]DirectX: rendering to Texture2DArray, and Loading from it in compute shader
I want to render several images to a Texture2DArray, and access the resulting images in a compute shader. 我想将几个图像渲染到Texture2DArray,并在计算着色器中访问生成的图像。 However, the
Load
method in the compute shader returns [0.0, 0.0, 0.0, 0.0]
rather than the image data. 但是,计算着色器中的
Load
方法返回[0.0, 0.0, 0.0, 0.0]
而不是图像数据。
Currently, I am doing the following: 目前,我正在做以下事情:
I first prepare a set of "render slots" by creating a Texture2DArray using CreateTexture2D
with texArrayDesc.ArraySize = numRenderSlots
: 我首先通过使用带有
texArrayDesc.ArraySize = numRenderSlots
CreateTexture2D
创建一个Texture2DArray来准备一组“渲染槽”:
texArrayDesc.Width = width;
texArrayDesc.Height = height;
texArrayDesc.MipLevels = 1;
texArrayDesc.ArraySize = numRenderSlots;
texArrayDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
texArrayDesc.Usage = D3D11_USAGE_DEFAULT;
texArrayDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
texArrayDesc.CPUAccessFlags = 0;
m_device->CreateTexture2D(&texArrayDesc, NULL, &m_renderSlotsTexArray);
I then create a ShaderResourceView for this texture array so I can access it from a compute shader: 然后我为这个纹理数组创建一个ShaderResourceView ,这样我就可以从一个计算着色器中访问它:
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
srvDesc.Texture2DArray.FirstArraySlice = 0;
srvDesc.Texture2DArray.MostDetailedMip = 0;
srvDesc.Texture2DArray.MipLevels = 1;
srvDesc.Texture2DArray.ArraySize = numRenderSlots;
m_device->CreateShaderResourceView(m_renderSlotsTexArray, &srvDesc, &m_renderSlotsSrv);
For each slice in the Texture2DArray, I create a RenderTargetView so I can render to it. 对于Texture2DArray中的每个切片,我创建一个RenderTargetView,以便我可以渲染它。
rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = 0;
rtvDesc.Texture2DArray.ArraySize = 1;
for (int i = 0; i < numRenderSlots; i++) {
// Change slot RTV desc to choose correct slice from array
rtvDesc.Texture2DArray.FirstArraySlice = D3D11CalcSubresource(0, i, 1);
// Create the RTV for the slot in m_renderSlotsTexArray
ID3D11RenderTargetView* slotRtv;
m_device->CreateRenderTargetView(m_renderSlotsTexArray, &rtvDesc, &slotRtv);
// Add the RenderTargetView to a list
m_slotRtvs.push_back(slotRtv);
}
I then render a set of different images by setting the associated render slot as a render target. 然后,我通过将关联的渲染槽设置为渲染目标来渲染一组不同的图像。 Note that the background color is not
[0,0,0,0]
. 请注意,背景颜色不是
[0,0,0,0]
。 Code simplified: 代码简化:
for (int i = 0; i < numRenderSlots; i++) {
setupScene(i);
deviceContext->OMSetRenderTargets(1, &m_slotRtvs[i], depthStencilView);
deviceContext->ClearRenderTargetView(m_slotRtvs[slotIdx], {0.2,0.2,0.2,0.0});
deviceContext->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
render();
}
I then setup a compute shader with a StructuredBuffer for shader output with associated UnorderedAccessView. 然后,我为具有关联的UnorderedAccessView的着色器输出设置了一个带有StructuredBuffer的计算着色器。 I pass this into the shader, along with the SRV of the render slots Texture2DArray.
我将它传递到着色器,以及渲染槽Texture2DArray的SRV。 I finally dispatch the shader, to operate over the image in 32x32 sized chunks.
我最终调度着色器,以32x32大小的块操作图像。
deviceContext->CSSetShader(m_computeShader, NULL, 0);
deviceContext->CSSetShaderResources(0, 1, &renderSlotsSrv);
deviceContext->CSSetUnorderedAccessViews(0, 1, &outputUav, nullptr);
deviceContext->Dispatch(img_width / 32, img_height / 32, numParams);
I then try to access the rendered image data in the compute shader. 然后我尝试在计算着色器中访问渲染的图像数据。 However,
imgs.Load
always seems to return [0.0, 0.0, 0.0, 0.0]
. 但是,
imgs.Load
似乎总是返回[0.0, 0.0, 0.0, 0.0]
imgs.Load
[0.0, 0.0, 0.0, 0.0]
。
Texture2DArray<float4> imgs : register(t0);
RWStructuredBuffer<float3> output : register(u0);
[numthreads(32,32,1)]
void ComputeShaderMain(
uint3 gID : SV_GroupID,
uint3 dtID : SV_DispatchThreadID,
uint3 tID : SV_GroupThreadID,
uint gi : SV_GroupIndex )
{
int idx_x = (gID.x * 32 + tID.x);
int idx_y = (gID.y * 32 + tID.y);
float4 px = imgs.Load(int4(idx_x,idx_y,gID.z,0));
...
output[outIdx] = float3(px.x, px.y, px.z);
}
I know the render slots are working, as I can access each render slot by doing CopySubresourceRegion into a staging texture to view the byte data. 我知道渲染槽正在工作,因为我可以通过将CopySubresourceRegion放入一个分段纹理来查看字节数据来访问每个渲染槽。 However, this
GPU->CPU
transfer is what I'm trying to avoid. 但是,这种
GPU->CPU
传输正是我想要避免的。
Also, I know the compute shader output is working as I can map the output buffer and inspect some basic test data. 此外,我知道计算着色器输出正在工作,因为我可以映射输出缓冲区并检查一些基本的测试数据。
What am I doing wrong? 我究竟做错了什么? Thanks in advance.
提前致谢。
Solved it. 解决了它。 I created the D3D device with debugging enabled and noticed:
我创建了启用调试的D3D设备并注意到:
D3D11 WARNING: ID3D11DeviceContext::CSSetShaderResources:
Resource being set to CS shader resource slot 0 is still bound on output!
So the problem was that my Texture2DArray was still bound as a render target as I tried to set it as a resource in the compute shader. 所以问题是我的Texture2DArray仍被绑定为渲染目标,因为我试图将其设置为计算着色器中的资源。
Easily fixed by unbinding the render targets like so: 通过取消绑定渲染目标轻松修复,如下所示:
deviceContext->OMSetRenderTargets(0, NULL, NULL);
before using CSSetShaderResources()
. 在使用
CSSetShaderResources()
之前。
I hope this helps anyone that has a similar issue. 我希望这有助于任何有类似问题的人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.