gpt4 book ai didi

c++ - DirectX:渲染到 Texture2DArray,并在计算着色器中从中加载

转载 作者:行者123 更新时间:2023-11-30 02:30:18 25 4
gpt4 key购买 nike

我想将多个图像渲染到 Texture2DArray,并在计算着色器中访问生成的图像。但是,计算着色器中的 Load 方法返回 [0.0, 0.0, 0.0, 0.0] 而不是图像数据。

目前,我正在做以下事情:

1。设置

我首先通过使用 CreateTexture2DtexArrayDesc.ArraySize = numRenderSlots 创建一个 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);

然后我为这个纹理数组创建一个 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);

对于 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);
}

2。用法

然后,我通过将关联的渲染槽设置为渲染目标来渲染一组不同的图像。请注意,背景颜色不是 [0,0,0,0]。代码简化:

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();
}

然后,我使用 StructuredBuffer 设置计算着色器,用于着色器输出以及关联的 UnorderedAccessView。我将其与渲染槽 Texture2DArray 的 SRV 一起传递到着色器中。我最终调度了着色器,以 32x32 大小的 block 对图像进行操作。

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);

然后我尝试访问计算着色器中的渲染图像数据。 但是,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);
}

我知道渲染槽正在工作,因为我可以通过将 CopySubresourceRegion 执行到临时纹理中来访问每个渲染槽以查看字节数据。但是,这种 GPU->CPU 传输是我要避免的。

另外,我知道计算着色器输出正在工作,因为我可以映射输出缓冲区并检查一些基本测试数据。


我做错了什么?提前致谢。

最佳答案

解决了。我创建了启用调试的 D3D 设备并注意到:

D3D11 WARNING: ID3D11DeviceContext::CSSetShaderResources:
Resource being set to CS shader resource slot 0 is still bound on output!

所以问题是我的 Texture2DArray 仍然绑定(bind)为渲染目标,因为我试图将它设置为计算着色器中的资源。

像这样解除绑定(bind)渲染目标很容易修复:

deviceContext->OMSetRenderTargets(0, NULL, NULL);

在使用 CSSSetShaderResources() 之前。

我希望这对遇到类似问题的任何人有所帮助。

关于c++ - DirectX:渲染到 Texture2DArray,并在计算着色器中从中加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38752215/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com