【问题标题】:Why is it necessary to call the OMSetRenderTargets DirectX method for every frame为什么需要为每一帧调用 OMSetRenderTargets DirectX 方法
【发布时间】:2018-07-19 11:41:02
【问题描述】:

我正在开发一个 Windows UWP 应用,该应用包含一个用 C++ 实现的 DirectX 11 视图(从 Windows::UI::Xaml::Controls::SwapChainPanel 继承)。在优化最终渲染框架的方法时,我遇到了一个我不完全理解的微妙之处,并且在我的一生中找不到任何有用的文档(无论是书籍还是在线资源)来解释它。

所以,我的渲染方法目前如下所示

void Renderer::RenderFrame()
{
  _d3dContext->OMSetRenderTargets(1, &_renderTargetView, _depthStencilView);
  _d3dContext->ClearRenderTargetView(_renderTargetView, reinterpret_cast<const float*>(&_backgroundColor));
  _d3dContext->ClearDepthStencilView(_depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
  _d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
  _d3dContext->DrawIndexed(_model->GetIndicesCount(), 0, 0);
}

到目前为止一切正常,模型正确渲染,一切看起来都符合预期。在优化代码时,我认为不必为每一帧设置渲染目标,即不必为每一帧调用 OMSetRenderTargets。

我的思考过程基本上是这样的: 视图实例化渲染器并将渲染器指针传递给 ID3D11RenderTargetView 和 ID3D11DepthStencilView。只要视图存在,这些对象就会一直存在,我认为使用 OMSetRenderTargets 方法我基本上是在告诉系统“嘿,这是你必须使用的渲染目标视图和模板视图”。为什么我需要每帧都告诉它?不应该只是“嘿,使用这个渲染目标视图和模板视图,直到我告诉你使用别的东西”。

我认为告诉它一次就足够了,这就是为什么我将对 OMSetRenderTargets 的调用移到视图调用的方法中,以设置 ID3D11RenderTargetView 和 ID3D11DepthStencilView,然后看起来如下:

void Renderer::SetRenderTargetView(ID3D11RenderTargetView* renderTargetView, ID3D11DepthStencilView* depthStencilView)
{
  _renderTargetView = renderTargetView;
  _depthStencilView = depthStencilView;

  _d3dContext->OMSetRenderTargets(1, &_renderTargetView, _depthStencilView);
}

RenderFrame 方法如下所示:

void Renderer::RenderFrame()
{
  _d3dContext->ClearRenderTargetView(_renderTargetView, reinterpret_cast<const float*>(&_backgroundColor));
  _d3dContext->ClearDepthStencilView(_depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
  _d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
  _d3dContext->DrawIndexed(_model->GetIndicesCount(), 0, 0);
}

但是,这显然是不够的,因为如果我这样做,则不会再渲染任何内容(可能除了第一帧,但那都是白色的,所以我不完全确定)。

我确信它不再正确渲染的事实是由该方法调用的移动引起的,因为这就是我在这里更改的全部内容。

有人知道为什么需要为每一帧调用 OMSetRenderTargets 吗?通过调用该方法,我还能指示系统做什么?有人可以指出我提供一些见解的文档吗?

【问题讨论】:

  • 请注意,在使用交换链移动到翻转模型时,我也注意到了问题,直到我每帧重新绑定它。这篇文章说这是使用翻转模型时的要求,如果您确实正在使用它:devblogs.microsoft.com/directx/dxgi-flip-model

标签: c++ uwp directx


【解决方案1】:

有多种原因会导致 Rendertarget 设置为 null。我发现的主要原因是在文档中,如果您尝试从设置为写入的资源中读取(如在渲染目标中)。在不知道其余设置的情况下,如果您使用的是复制资源或解析子资源,那么这可能会解除这些纹理与渲染目标的绑定。

Direct X 11 - OMSetRenderTargetrs

当您使用 UWP 时,我会假设您正在使用其中一种。因此,您将在那时解除约束。如果您想检查当前渲染目标在 OM 中是否存在,可以使用 GetRenderTargets 调用。

【讨论】:

    猜你喜欢
    • 2015-04-30
    • 2015-08-09
    • 2013-04-10
    • 2018-07-09
    • 2017-08-10
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 2013-05-02
    相关资源
    最近更新 更多