0
\$\begingroup\$

Is it possible to bind a texture with a different format as render target and as shader resource view?

Specifically with a different _SRGB suffix. My goal is to render a shader into an R8G8B8A8_UNORM texture but read the render target in another shader as R8G8B8A8_UNORM_SRGB, or the other way around. Basically controlling on the read and write side whether automatic sRGB conversion should happen. There is no window or swap chain involved.

So far, I get an invalid args exception when I try to create a texture view with a different format. I am using the Stride game engine set to Directx 11 graphics API, which uses SharpDX.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Try making the resource R8G8B8A8_TYPELESS and then create your RTV/SRV with the desired formats. \$\endgroup\$ Apr 29 at 8:13
  • \$\begingroup\$ @ChuckWalbourn yes, that was the solution! If you want to add that as a reply, I'll mark it as the solution. \$\endgroup\$
    – thalm
    Apr 29 at 13:45
1
\$\begingroup\$

Direct3D supports 'type re-casting' within limits.

You typically have to first create the resource as 'typeless' which in this case would be DXGI_FORMAT_R8G8B8A8_TYPELESS:

CD3D11_TEXTURE2D_DESC desc(
        DXGI_FORMAT_R8G8B8A8_TYPELESS,
        width, height,
        1, // The render target view has only one texture.
        1, // Use a single mipmap level.
        D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
        D3D11_USAGE_DEFAULT,
        0,
        1
    );

DX::ThrowIfFailed(device->CreateTexture2D(
    &desc,
    nullptr,
    &m_renderTarget));

Create the RTV as DXGI_FORMAT_R8G8B8A8_UNORM:

CD3D11_RENDER_TARGET_VIEW_DESC rtvDesc(
    D3D11_RTV_DIMENSION_TEXTURE2D,
    DXGI_FORMAT_R8G8B8A8_UNORM);

DX::ThrowIfFailed(device->CreateRenderTargetView(
        m_renderTarget.Get(),
        &rtvDesc,
        &m_renderTargetView));

Then create the SRV as DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:

CD3D11_SHADER_RESOURCE_VIEW_DESC srvDesc(
    D3D11_SRV_DIMENSION_TEXTURE2D,
    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);

DX::ThrowIfFailed(device->CreateShaderResourceView(
    m_renderTarget.Get(),
    &srvDesc,
    &m_shaderResourceView));

Note that there are some special conditions when using SRGB for backbuffers. See this blog post series.

\$\endgroup\$
1
  • \$\begingroup\$ Excellent, this works perfectly, thanks! \$\endgroup\$
    – thalm
    Apr 30 at 11:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.