[英]DirectX: rendering to Texture2DArray, and Loading from it in compute shader
我想將幾個圖像渲染到Texture2DArray,並在計算着色器中訪問生成的圖像。 但是,計算着色器中的Load
方法返回[0.0, 0.0, 0.0, 0.0]
而不是圖像數據。
目前,我正在做以下事情:
我首先通過使用帶有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);
然后我為這個紋理數組創建一個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);
}
然后,我通過將關聯的渲染槽設置為渲染目標來渲染一組不同的圖像。 請注意,背景顏色不是[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();
}
然后,我為具有關聯的UnorderedAccessView的着色器輸出設置了一個帶有StructuredBuffer的計算着色器。 我將它傳遞到着色器,以及渲染槽Texture2DArray的SRV。 我最終調度着色器,以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);
然后我嘗試在計算着色器中訪問渲染的圖像數據。 但是, 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);
}
我知道渲染槽正在工作,因為我可以通過將CopySubresourceRegion放入一個分段紋理來查看字節數據來訪問每個渲染槽。 但是,這種GPU->CPU
傳輸正是我想要避免的。
此外,我知道計算着色器輸出正在工作,因為我可以映射輸出緩沖區並檢查一些基本的測試數據。
我究竟做錯了什么? 提前致謝。
解決了它。 我創建了啟用調試的D3D設備並注意到:
D3D11 WARNING: ID3D11DeviceContext::CSSetShaderResources:
Resource being set to CS shader resource slot 0 is still bound on output!
所以問題是我的Texture2DArray仍被綁定為渲染目標,因為我試圖將其設置為計算着色器中的資源。
通過取消綁定渲染目標輕松修復,如下所示:
deviceContext->OMSetRenderTargets(0, NULL, NULL);
在使用CSSetShaderResources()
之前。
我希望這有助於任何有類似問題的人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.