如果调用 RSSetScissorRects,事件上的 WaitForSingleObject 会导致访问冲突

WaitForSingleObject on a event causes access violation if RSSetScissorRects is called

WaitForSingleObject函数导致如下错误

在 DrawTexturedCube.exe 中的 0x00007FFA02794AD0 (d3d12warp.dll) 抛出异常:0xC0000005:访问冲突读取位置 0x0000000000000000

等待上一帧完成。该代码取自 MSDN DirectX12 示例代码 (https://msdn.microsoft.com/en-us/library/windows/desktop/dn899189%28v=vs.85%29.aspx)。

void D3D12RenderSystem::waitForPreviousFrame() {
    const UINT fence = fenceValue_;
    ThrowIfFailed(commandQueue_->Signal(fence.Get(), fence));
    fenceValue_++;

    if (fence_->GetCompletedValue() < fence) {
        ThrowIfFailed(fence_->SetEventOnCompletion(fence, fenceEvent_));
        WaitForSingleObject(fenceEvent_, INFINITE);
    }
    frameIndex_ = swapChain_->GetCurrentBackBufferIndex();
}

此错误只发生在 4 个测试用例中的 1 个中。如果我从 paintEvent 循环中删除对以下函数的调用,访问冲突就会消失(但渲染到视口的图像也会消失),其结构如下所述 (https://msdn.microsoft.com/de-de/library/windows/desktop/dn903899%28v=vs.85%29.aspx).

void D3D12CommandList::setScissorRect(const int width, const int height) {
    D3D12_RECT rectScissor = { 0.0f, //top
                               0.0f, //left
                               static_cast<LONG>(width), //right
                               static_cast<LONG>(height)}; //bottom
    commandList_->RSSetScissorRects(1, &rectScissor);
}

我使用的是 VS2015,调试器没有在所有测试用例中将 fenceEvent_ 变量显示为 NULL,反汇编显示 ?? ??对于所有测试用例中句柄指向的内存。我的着色器不使用几何着色器。

所以现在我有两个问题:

  1. WaitForSingleObject 函数如何导致 4 个几乎相同的测试用例中只有 1 个出现访问冲突?
  2. RSSetScissorRects 函数和 WaitForSingleObject 函数之间有什么关系?

好的,现在我找到了错误并修复了它。这是由于不小心用常量缓冲区的描述符堆覆盖了纹理缓冲区的描述符堆。所以绘图命令试图访问纹理缓冲区,这当然比常量缓冲区大得多,因此导致了分段错误。通过不设置剪刀矩形,也没有执行绘制调用,因此没有错误。