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, 2021 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, 2021 at 13:45

1 Answer 1

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, 2021 at 11:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .