簡體   English   中英

DirectX12 命令列表執行錯誤

[英]DirectX12 commandList execution error

我已經開始學習 DirectX12 並嘗試制作某種簡單的引擎。 我遵循 Frank D. Luna “DirectX12 3D 編程簡介”,但遇到了一些問題。 首先在創建swapChain時,填寫描述如下:

DXGI_SWAP_CHAIN_DESC swapChainDesc;
swapChainDesc.BufferDesc.Width = Core::displayWidth;
swapChainDesc.BufferDesc.Height = Core::displayHeight;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferDesc.Format = Core::pixelDefinitionFormat;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDesc.SampleDesc.Count = Core::multiSamplingLevel ? 4 : 1;
swapChainDesc.SampleDesc.Quality = Core::multiSamplingEnabled ? (Core::multiSamplingLevel - 1) : 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = (INT) Core::buffering;
swapChainDesc.OutputWindow = Core::mainWindow;
swapChainDesc.Windowed = true;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

// Note: Swap chain uses queue to perform flush.
ThrowIfFailed(Core::factory->CreateSwapChain(
    Core::commandQueue.Get(),
    &swapChainDesc,
    Core::swapChain.GetAddressOf()
));

我收到“錯誤參數”錯誤。 我已經在 MSDN 上找到了解決方案,但我想知道我做錯了什么。

第二個問題是為什么我:

D3D12 ERROR: ID3D12GraphicsCommandList::*: A single command list cannot write to multiple buffers within a particular swapchain. [ STATE_SETTING ERROR #904: COMMAND_LIST_MULTIPLE_SWAPCHAIN_BUFFER_REFERENCES]

在此清除屏幕代碼片段的執行期間:

void Renderer::drawSomething() {

// Reuse the memory associated with command recording.
// We can only reset when the associated command lists have finished
// execution on the GPU.
ThrowIfFailed(Core::commandAllocator->Reset());

// A command list can be reset after it has been added to the 
// command queue via ExecuteCommandList. Reusing the command list reuses memory.
ThrowIfFailed(Core::commandList->Reset(Core::commandAllocator.Get(), NULL));

// Set the viewport and scissor rect. This needs to be reset 
// whenever the command list is reset.
Core::commandList->RSSetViewports(1, &Core::viewport);
Core::commandList->RSSetScissorRects(1, &Core::scissorsRectangle);

// Indicate a state transition on the resource usage.
Core::commandList->ResourceBarrier(
    1,
    &CD3DX12_RESOURCE_BARRIER::Transition(
        Core::getCurrentBackBuffer().Get(),
        D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_PRESENT,
        D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_RENDER_TARGET
    )
);



// Specify the buffers we are going to render to.
Core::commandList->OMSetRenderTargets(
    1,
    &Core::getCurrentBackBufferView(),
    true,
    &Core::getDSVHeapStartDescriptorHandle()
);

// Clear the back buffer and depth buffer.
Core::commandList->ClearRenderTargetView(
    Core::getCurrentBackBufferView(),
    DirectX::Colors::LightSteelBlue,
    0,
    NULL
);

Core::commandList->ClearDepthStencilView(
    Core::getDSVHeapStartDescriptorHandle(),
    D3D12_CLEAR_FLAGS::D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAGS::D3D12_CLEAR_FLAG_STENCIL,
    1.0f,
    0,
    0,
    NULL
);


//// Indicate a state transition on the resource usage.
Core::commandList->ResourceBarrier(
    1,
    &CD3DX12_RESOURCE_BARRIER::Transition(
        Core::getCurrentBackBuffer().Get(),
        D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_RENDER_TARGET,
        D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_PRESENT
    )
);

// Done recording commands.
ThrowIfFailed(Core::commandList->Close());

// Add the command list to the queue for execution.
ID3D12CommandList* cmdsLists[] = {Core::commandList.Get()};
Core::commandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);

// swap the back and front buffers
ThrowIfFailed(Core::swapChain->Present(0, 0));
UINT buffering = Core::buffering;
Core::currentBackBuffer = (Core::currentBackBuffer + 1) % buffering;
Core::flushCommandQueue();
}

為了不把這篇文章弄得一團糟,我不會把所有的代碼都放在這里,但是如果你想看看它的樣子,或者在這種情況下很重要,我的整個存儲庫都在這里:存儲庫

它非常小而簡單,幾乎所有代碼都放在Core類中。

先感謝您!

編輯:我找到了第二個問題的解決方案。 問題出在這個循環中:

void Core::createSwapChainBuffersIntoRTVHeap() {
for (UINT i = 0; i < Core::buffering; i++) {
    CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHeapHandle(rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
    ErrorUtils::messageAndExitIfFailed(
        swapChain->GetBuffer(i, IID_PPV_ARGS(&swapChainBackBuffers[i])),
        L"B³¹d pobierania backBuffera!",
        GET_SWAPCHAIN_BACK_BUFFER_ERROR
    );

    device->CreateRenderTargetView(swapChainBackBuffers[i].Get(), NULL, rtvHeapHandle);
    //Zapamiêtuje offset, to jest sterta po prostu zwyk³a
    rtvHeapHandle.Offset(1, rtvDescriptorSize);
}

}

我只做了一個動作就讓這段代碼看起來像這樣:

void Core::createSwapChainBuffersIntoRTVHeap() {
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHeapHandle(rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
for (UINT i = 0; i < Core::buffering; i++) {
    ErrorUtils::messageAndExitIfFailed(
        swapChain->GetBuffer(i, IID_PPV_ARGS(&swapChainBackBuffers[i])),
        L"B³¹d pobierania backBuffera!",
        GET_SWAPCHAIN_BACK_BUFFER_ERROR
    );

    device->CreateRenderTargetView(swapChainBackBuffers[i].Get(), NULL, rtvHeapHandle);
    //Zapamiêtuje offset, to jest sterta po prostu zwyk³a
    rtvHeapHandle.Offset(1, rtvDescriptorSize);
}

}

在那之后。 當 commandList 正確關閉時,我在 D3D12.dll 中遇到了 AccessViolationException:

ThrowIfFailed(Core::swapChain->Present(0, 0));

經過幾個小時的互聯網研究,我通過使用“dxcpl.exe”在此應用程序上強制 WARP 進行了修復。 我認為那是因為我使用 HD4000 和 Nvidia 作為第二張卡的筆記本電腦,但我不確定。

這不會幫助您立即解決問題,但會為您提供更多信息。 DirectX12 希望你將所有命令推送到命令列表中,它只會在你調用Close()時報告錯誤。 請注意,您無法通過重置Close()來“恢復”失敗的命令列表,您可以做的最好的事情是刪除它,然后創建一個新的命令列表。 但是,在這種情況下,您可能無法更新引用的資源。 真的不建議你這樣做。

如果附加了調試器,您確實可以做的是使用ID3D12InfoQueue接口使您的程序因 D3D12 錯誤而中斷。

從您的device獲取它:

ID3D12InfoQueue* InfoQueue = nullptr;
Core::device->QueryInterface(IID_PPV_ARGS(&InfoQueue));

啟用“中斷嚴重性”:

InfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true);
InfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true);
InfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, false);

放手吧:

InfoQueue->Release();

您還可以將 InfoQueue 設置為 D3D12 錯誤 ID 的白名單或黑名單集。 您的錯誤 ID 是D3D12_MESSAGE_ID_COMMAND_LIST_MULTIPLE_SWAPCHAIN_BUFFER_REFERENCES (代碼 904)。

希望這會幫助某人處理這個圖形 API。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM