簡體   English   中英

DirectX:使用計算着色器寫入紋理

[英]DirectX : Write to texture with Compute Shader

我正在嘗試在 HLSL 中使用計算着色器編寫紋理。

紋理的創建:

D3D11_TEXTURE2D_DESC textureDesc;
ZeroMemory(&textureDesc, sizeof(textureDesc));
textureDesc.Width = 512;
textureDesc.Height = 512;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = 0;
m_tex = 0;
hr = device->CreateTexture2D(&textureDesc, 0, &m_tex);

無人機的創建:

D3D11_UNORDERED_ACCESS_VIEW_DESC descUAV;
ZeroMemory(&descUAV, sizeof(descUAV));
descUAV.Format = DXGI_FORMAT_UNKNOWN;
descUAV.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
descUAV.Texture2D.MipSlice = 0;
hr = device->CreateUnorderedAccessView(m_tex, &descUAV, &m_uavAccess);

創建 SRV(查看紋理):`

D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = textureDesc.Format;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
hr = device->CreateShaderResourceView(m_tex, &srvDesc, &m_srvTexOutput);

着色器:

RWTexture2D<float4> gOutput : register(u0);

[numthreads(16, 16, 1)]
void main(int3 dispatchThreadID : SV_DispatchThreadID) // Thread ID
{
    gOutput[dispatchThreadID.xy] = float4(0.0f, 1.0f, 0.0f, 1.0f);
}

問題是紋理總是黑色的(計算着色器不寫入紋理)。

感謝您的幫助! :D

問題是我在同一個紋理上綁定了一個 UAV 和一個 SRV。

我解決了創建兩個紋理的問題:一個綁定到無人機,另一個綁定到 SRV。

計算着色器在 UAV 上寫入,並且在每一幀中,我使用deviceContext->CopyResource(m_texSRV, m_texUAV);復制 SRV 上的數據deviceContext->CopyResource(m_texSRV, m_texUAV);

現在的問題是性能, CopyResource是一個代價高昂的操作。 它有其他更便宜的解決方案嗎?

感謝您的幫助! :D

問題是您需要先讓 GPU 刷新表面,然后才能將其用作不同着色器調用(繪制/PS)中的輸入。 您可以通過將空資源綁定到前一個着色器階段來實現此目的。

    ID3D11UnorderedAccessView *NullUav = nullptr;
    m_DeviceContext->CSSetUnorderedAccessViews(0, 1, &NullUav, nullptr);

這應該足以告訴圖形驅動程序刷新或將資源從寫入資源轉換為讀取資源。

如果您使用 D3D12 或 vulkan,則在從寫入到讀取時需要一個資源屏障。

示例渲染循環:

    // Run compute kernel output to UAV.
    m_DeviceContext->CSSetShader(m_ComputeShader, NULL, 0);
    m_DeviceContext->CSSetUnorderedAccessViews(0, 1, &m_UAV, nullptr);
    m_DeviceContext->Dispatch(DispatchX, DispatchY, DispatchZ);

    // Run the raster pipeline to present the UAV values to screen.
    ID3D11UnorderedAccessView *NullUav = nullptr;
    ID3D11ShaderResourceView* NullSrv = nullptr;
    ID3D11DepthStencilView *NullDsv = nullptr;
    m_DeviceContext->PSSetShader(m_PixelShader, NULL, 0);
    m_DeviceContext->VSSetShader(m_VertexShader, NULL, 0);
    m_DeviceContext->CSSetUnorderedAccessViews(0, 1, &NullUav, nullptr);
    m_DeviceContext->PSSetShaderResources(0, 1, &m_SRV);
    m_DeviceContext->IASetIndexBuffer(m_IndexBuffer, DXGI_FORMAT_R32_UINT, 0);
    m_DeviceContext->PSSetSamplers(0, 1, &m_SamplerState);
    m_DeviceContext->OMSetRenderTargets(1, &m_RenderTarget, NullDsv);
    m_ViewPort.Width = (float)RTWidth;
    m_ViewPort.Height = (float)RTHeight;
    m_ViewPort.MaxDepth = 1.0f;
    m_DeviceContext->RSSetViewports(1, &m_ViewPort);
    m_DeviceContext->DrawIndexed(4, 0, 0);

    //  Present the final result.
    int Result = m_SwapChain->Present(1, 0);
    if (Result == DXGI_ERROR_DEVICE_REMOVED || Result == DXGI_ERROR_DEVICE_RESET) {
        // Reinitialize the renderer..
    }

    // Unset the SRV
    m_DeviceContext->PSSetShaderResources(0, 1, &NullSrv);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM