1

What exactly should I expect to happen when using DiscardResource?

What's the difference between discard and destroying/deleting a resource.

When is a good time/use-case to discard a resource?

Unfortunately Microsoft doesn't seem to say much about it other than it "discards a resource".

Tony Clifton
  • 467
  • 3
  • 10

1 Answers1

4

TL;DR: Is a rarely used function that provides a driver hint related to handling clear compression structures. You are unlikely to use it except based on specific performance advice.

DiscardResource is the DirectX 12 version of the Direct3D 11.1 method. See Microsoft Docs

The primary use of these methods it to optimize the performance of tiled-based deferred rasterizer graphics parts by discarding the render target after present. This is a hint to the driver that the contents of the render target are no longer relevant to the operation of the program, so it can avoid some internal clearing operations on the next use.

For DirectX 11, this is in the DirectX 11 App template to use DiscardView because it makes use of DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL:

void DX::DeviceResources::Present() 
{
    // The first argument instructs DXGI to block until VSync, putting the application
    // to sleep until the next VSync. This ensures we don't waste any cycles rendering
    // frames that will never be displayed to the screen.
    DXGI_PRESENT_PARAMETERS parameters = { 0 };
    HRESULT hr = m_swapChain->Present1(1, 0, &parameters);

    // Discard the contents of the render target.
    // This is a valid operation only when the existing contents will be entirely
    // overwritten. If dirty or scroll rects are used, this call should be removed.
    m_d3dContext->DiscardView1(m_d3dRenderTargetView.Get(), nullptr, 0);

    // Discard the contents of the depth stencil.
    m_d3dContext->DiscardView1(m_d3dDepthStencilView.Get(), nullptr, 0);

    // If the device was removed either by a disconnection or a driver upgrade, we 
    // must recreate all device resources.
    if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
    {
        HandleDeviceLost();
    }
    else
    {
        DX::ThrowIfFailed(hr);
    }
}

The DirectX 12 App template doesn't need those explicit calls because it uses DXGI_SWAP_EFFECT_FLIP_DISCARD.

If you are wondering why the DirectX 11 app doesn't just use DXGI_SWAP_EFFECT_FLIP_DISCARD, it probably should. The DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL swap effect was the only one supported by Windows 8.x for Windows Store apps, which is when DiscardView was introduced. For Windows 10 / DirectX 12 / UWP, it's probably better to always use DXGI_SWAP_EFFECT_FLIP_DISCARD unless you specifically don't want the backbuffer discarded.

It is also useful for multi-GPU SLI / Crossfire configurations since the clearing operation can require synchronization between the GPUs. See this GDC 2015 talk

There are also other scenario-specific usages. For example, if doing deferred rendering for the G-buffer where you know every single pixel will be overwritten, you can use DiscardResource instead of doing ClearRenderTargetView / ClearDepthStencilView.

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81
  • Thank you for the response. On a slightly related note, does it ever make sense for the [D3D12_DISCARD_REGION](https://learn.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_discard_region) argument to have `pRects` set as NULL but still specify subresources to discard? I am having trouble understanding the relationship between the rects and the subresources. – Tony Clifton Jun 10 '19 at 14:59
  • You can supply subresource indices without a rects. – Chuck Walbourn Jun 10 '19 at 16:09
  • I'm pretty sure this optimization is not only for tiled-based GPUs but also for desktop GPUs. – Peng DU Dec 11 '19 at 04:57