什么是 ID3D12GraphicsCommandList::DiscardResource?

Ton*_*ton 2 directx direct3d directx-12 direct3d12

使用DiscardResource时我到底应该期望发生什么?

丢弃和销毁/删除资源有什么区别?

什么时候是丢弃资源的好时机/用例?

不幸的是,除了“丢弃资源”之外,微软似乎没有对此说太多。

Chu*_*urn 5

TL;DR:是一个很少使用的函数,它提供与处理清晰压缩结构相关的驱动程序提示。除非基于特定的性能建议,否则您不太可能使用它。

DiscardResource是 Direct3D 11.1 方法的 DirectX 12 版本。请参阅微软文档

这些方法的主要用途是通过在呈现后丢弃渲染目标来优化基于平铺的延迟光栅化图形部件的性能。这是向驱动程序暗示渲染目标的内容不再与程序的运行相关,因此可以避免下次使用时进行一些内部清除操作。

对于 DirectX 11,这是在 DirectX 11 应用程序模板中使用的,DiscardView因为它使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

DirectX 12 应用程序模板不需要这些显式调用,因为它使用DXGI_SWAP_EFFECT_FLIP_DISCARD.

如果您想知道为什么 DirectX 11 应用程序不只使用DXGI_SWAP_EFFECT_FLIP_DISCARD,它可能应该使用。交换DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL效果是 Windows 8.x 对 Windows 应用商店应用程序支持的唯一一种效果,这是在引入时DiscardView引入的。DXGI_SWAP_EFFECT_FLIP_DISCARD对于 Windows 10 / DirectX 12 / UWP,除非您特别不希望丢弃后台缓冲区,否则最好始终使用。

它对于多 GPU SLI/Crossfire 配置也很有用,因为清除操作可能需要 GPU 之间的同步。请参阅GDC 2015 演讲

还有其他特定场景的用法。例如,如果对 G 缓冲区进行延迟渲染,并且您知道每个像素都将被覆盖,则可以使用/DiscardResource代替。ClearRenderTargetViewClearDepthStencilView