简体   繁体   English

DirectX12 命令列表执行错误

[英]DirectX12 commandList execution error

I've started to learn DirectX12 and i try to make some kind of simple engine.我已经开始学习 DirectX12 并尝试制作某种简单的引擎。 I follow the Frank D. Luna "Introduction to 3D programming with DirectX12" and i have got some problems.我遵循 Frank D. Luna “DirectX12 3D 编程简介”,但遇到了一些问题。 First during creating swapChain, filling description like this:首先在创建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()
));

I recive "bad parameter" error.我收到“错误参数”错误。 I've already found solution on MSDN but i want to know what i'am doing wrong.我已经在 MSDN 上找到了解决方案,但我想知道我做错了什么。

Second question is why have i:第二个问题是为什么我:

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]

Durning execution of this clearing screen code fragment:在此清除屏幕代码片段的执行期间:

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();
}

To not making big mess in this post, i won't place all code here, but if you would like to look how does it look like, or it would be important in this case, my whole repository is here: repository为了不把这篇文章弄得一团糟,我不会把所有的代码都放在这里,但是如果你想看看它的样子,或者在这种情况下很重要,我的整个存储库都在这里:存储库

It's very small and simlple, almost all code is placed in Core class.它非常小而简单,几乎所有代码都放在Core类中。

Thank you in advance!先感谢您!

Edit: I found solution to second question.编辑:我找到了第二个问题的解决方案。 Problem was in this loop:问题出在这个循环中:

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);
}

} }

I did only one move to made this code look like this:我只做了一个动作就让这段代码看起来像这样:

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);
}

} }

After that.在那之后。 When the commandList closing gone right, i've got AccessViolationException in D3D12.dll on:当 commandList 正确关闭时,我在 D3D12.dll 中遇到了 AccessViolationException:

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

Which after few hours of internet research i fixed by forcing WARP on this application using "dxcpl.exe".经过几个小时的互联网研究,我通过使用“dxcpl.exe”在此应用程序上强制 WARP 进行了修复。 I assume that was because i work on laptop with HD4000 and Nvidia as second card, but i'm not sure.我认为那是因为我使用 HD4000 和 Nvidia 作为第二张卡的笔记本电脑,但我不确定。

This will not help you to fix the problem at once, but will give you much more information.这不会帮助您立即解决问题,但会为您提供更多信息。 DirectX12 wants you to push all commands into commandlists and it will only report an error when you call Close() on it. DirectX12 希望你将所有命令推送到命令列表中,它只会在你调用Close()时报告错误。 Note that you can not "resurrect" the commandlist that failed on Close() by resetting it, the best thing you can do is to delete it and then create a new commandlist.请注意,您无法通过重置Close()来“恢复”失败的命令列表,您可以做的最好的事情是删除它,然后创建一个新的命令列表。 In this case you however may not update referenced resources.但是,在这种情况下,您可能无法更新引用的资源。 Don't really recommend you doing that.真的不建议你这样做。

What you indeed can do is to use the ID3D12InfoQueue interface to make your program break on D3D12 errors if the debugger is attached.如果附加了调试器,您确实可以做的是使用ID3D12InfoQueue接口使您的程序因 D3D12 错误而中断。

Get it from your device :从您的device获取它:

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

Enable "break on severity":启用“中断严重性”:

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

And let it go:放手吧:

InfoQueue->Release();

You can also set your InfoQueue to whitelist or blacklist sets of D3D12 error ids.您还可以将 InfoQueue 设置为 D3D12 错误 ID 的白名单或黑名单集。 Your error ID is D3D12_MESSAGE_ID_COMMAND_LIST_MULTIPLE_SWAPCHAIN_BUFFER_REFERENCES (code 904).您的错误 ID 是D3D12_MESSAGE_ID_COMMAND_LIST_MULTIPLE_SWAPCHAIN_BUFFER_REFERENCES (代码 904)。

Hope that this will help someone to deal with this graphics API.希望这会帮助某人处理这个图形 API。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM