DirectX: рендеринг в Texture2DArray и загрузка из него в вычислительный шейдер

Я хочу визуализировать несколько изображений в Texture2DArray и получить доступ к полученным изображениям в вычислительном шейдере. Тем не менее Load метод в вычислении возвращает шейдер [0.0, 0.0, 0.0, 0.0] а не данные изображения.

В настоящее время я делаю следующее:

1. Настройка

Сначала я готовлю набор «рендеринга слотов», создавая Texture2DArray с помощью CreateTexture2D с texArrayDesc.ArraySize = numRenderSlots:

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. Я передаю это в шейдер вместе с SRV слотов рендеринга Texture2DArray. Наконец, я отправляю шейдер, чтобы обработать изображение кусками размером 32×32.

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 передача это то, что я пытаюсь избежать.

Кроме того, я знаю, что выходные данные вычислительного шейдера работают, так как я могу отобразить выходной буфер и проверить некоторые основные тестовые данные.


Что я делаю неправильно? Заранее спасибо.

0

Решение

Решил это. Я создал устройство 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(),

Я надеюсь, что это помогает любому, у кого есть подобная проблема.

2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector