简体   繁体   中英

DirectX : Write to texture with Compute Shader

I'm trying to write in a texture with compute shader in HLSL.

Creation of the texture :

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

Creation of the UAV :

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

Creation of the SRV (to see the texture) :`

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

The shader :

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

The problem is that the texture is always black (the compute shader doesn't write to the texture).

Thanks for your help ! :D

The problem is that I bound an UAV and a SRV on the same texture.

I resolved the problem creating two textures : one bound to an UAV and another bound to a SRV.

The compute shader write on the UAV and, each frame, I copy the data on the SRV with deviceContext->CopyResource(m_texSRV, m_texUAV);

The problem now is the performance, CopyResource is a costly operation. Does it have an other solution less expensive ?

Thanks for your help ! :D

The issue is that you need to cause the GPU to flush the surface before using it as an input in a different shader invocation (draw/PS). You do this by binding a null resource to the previous shader stage.

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

This should be enough to tell the graphics driver to flush or transition the resource from a write to a read resource.

If you use D3D12 or vulkan you will need a resource barrier when going from write to read.

Example render loop:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM