GPUDevice: Improve pipeline error reporting

This commit is contained in:
Stenzek
2024-07-22 15:35:28 +10:00
parent deed0c9713
commit ba6b65401d
24 changed files with 227 additions and 163 deletions

View File

@ -81,7 +81,7 @@ D3D12Device::~D3D12Device()
Assert(s_pipeline_cache_data.empty());
}
D3D12Device::ComPtr<ID3DBlob> D3D12Device::SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc)
D3D12Device::ComPtr<ID3DBlob> D3D12Device::SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc, Error* error)
{
ComPtr<ID3DBlob> blob;
ComPtr<ID3DBlob> error_blob;
@ -89,7 +89,7 @@ D3D12Device::ComPtr<ID3DBlob> D3D12Device::SerializeRootSignature(const D3D12_RO
D3D12SerializeRootSignature(desc, D3D_ROOT_SIGNATURE_VERSION_1, blob.GetAddressOf(), error_blob.GetAddressOf());
if (FAILED(hr)) [[unlikely]]
{
ERROR_LOG("D3D12SerializeRootSignature() failed: {:08X}", static_cast<unsigned>(hr));
Error::SetHResult(error, "D3D12SerializeRootSignature() failed: ", hr);
if (error_blob)
ERROR_LOG(static_cast<const char*>(error_blob->GetBufferPointer()));
@ -99,9 +99,10 @@ D3D12Device::ComPtr<ID3DBlob> D3D12Device::SerializeRootSignature(const D3D12_RO
return blob;
}
D3D12Device::ComPtr<ID3D12RootSignature> D3D12Device::CreateRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc)
D3D12Device::ComPtr<ID3D12RootSignature> D3D12Device::CreateRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc,
Error* error)
{
ComPtr<ID3DBlob> blob = SerializeRootSignature(desc);
ComPtr<ID3DBlob> blob = SerializeRootSignature(desc, error);
if (!blob)
return {};
@ -110,7 +111,7 @@ D3D12Device::ComPtr<ID3D12RootSignature> D3D12Device::CreateRootSignature(const
m_device->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(rs.GetAddressOf()));
if (FAILED(hr)) [[unlikely]]
{
ERROR_LOG("CreateRootSignature() failed: {:08X}", static_cast<unsigned>(hr));
Error::SetHResult(error, "CreateRootSignature() failed: ", hr);
return {};
}
@ -228,23 +229,14 @@ bool D3D12Device::CreateDevice(std::string_view adapter, bool threaded_presentat
SetFeatures(disabled_features);
if (!CreateCommandLists() || !CreateDescriptorHeaps())
{
Error::SetStringView(error, "Failed to create command lists/descriptor heaps.");
if (!CreateCommandLists(error) || !CreateDescriptorHeaps(error))
return false;
}
if (!m_window_info.IsSurfaceless() && !CreateSwapChain())
{
Error::SetStringView(error, "Failed to create swap chain.");
if (!m_window_info.IsSurfaceless() && !CreateSwapChain(error))
return false;
}
if (!CreateRootSignatures() || !CreateBuffers())
{
Error::SetStringView(error, "Failed to create root signature/buffers.");
if (!CreateRootSignatures(error) || !CreateBuffers(error))
return false;
}
CreateTimestampQuery();
return true;
@ -349,7 +341,7 @@ bool D3D12Device::GetPipelineCacheData(DynamicHeapArray<u8>* data)
return true;
}
bool D3D12Device::CreateCommandLists()
bool D3D12Device::CreateCommandLists(Error* error)
{
for (u32 i = 0; i < NUM_COMMAND_LISTS; i++)
{
@ -362,7 +354,7 @@ bool D3D12Device::CreateCommandLists()
IID_PPV_ARGS(res.command_allocators[j].GetAddressOf()));
if (FAILED(hr))
{
ERROR_LOG("CreateCommandAllocator() failed: {:08X}", static_cast<unsigned>(hr));
Error::SetHResult(error, "CreateCommandAllocator() failed: ", hr);
return false;
}
@ -370,7 +362,7 @@ bool D3D12Device::CreateCommandLists()
IID_PPV_ARGS(res.command_lists[j].GetAddressOf()));
if (FAILED(hr))
{
ERROR_LOG("CreateCommandList() failed: {:08X}", static_cast<unsigned>(hr));
Error::SetHResult(error, "CreateCommandList() failed: ", hr);
return false;
}
@ -378,21 +370,21 @@ bool D3D12Device::CreateCommandLists()
hr = res.command_lists[j]->Close();
if (FAILED(hr))
{
ERROR_LOG("Close() failed: {:08X}", static_cast<unsigned>(hr));
Error::SetHResult(error, "Close() for new command list failed: ", hr);
return false;
}
}
if (!res.descriptor_allocator.Create(m_device.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
MAX_DESCRIPTORS_PER_FRAME))
MAX_DESCRIPTORS_PER_FRAME, error))
{
ERROR_LOG("Failed to create per frame descriptor allocator");
Error::AddPrefix(error, "Failed to create per frame descriptor allocator: ");
return false;
}
if (!res.sampler_allocator.Create(m_device.Get(), MAX_SAMPLERS_PER_FRAME))
if (!res.sampler_allocator.Create(m_device.Get(), MAX_SAMPLERS_PER_FRAME, error))
{
ERROR_LOG("Failed to create per frame sampler allocator");
Error::AddPrefix(error, "Failed to create per frame sampler allocator: ");
return false;
}
}
@ -472,14 +464,14 @@ void D3D12Device::DestroyCommandLists()
}
}
bool D3D12Device::CreateDescriptorHeaps()
bool D3D12Device::CreateDescriptorHeaps(Error* error)
{
if (!m_descriptor_heap_manager.Create(m_device.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
MAX_PERSISTENT_DESCRIPTORS, false) ||
!m_rtv_heap_manager.Create(m_device.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_RTV, MAX_PERSISTENT_RTVS, false) ||
!m_dsv_heap_manager.Create(m_device.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_DSV, MAX_PERSISTENT_DSVS, false) ||
!m_sampler_heap_manager.Create(m_device.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, MAX_PERSISTENT_SAMPLERS,
false))
MAX_PERSISTENT_DESCRIPTORS, false, error) ||
!m_rtv_heap_manager.Create(m_device.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_RTV, MAX_PERSISTENT_RTVS, false, error) ||
!m_dsv_heap_manager.Create(m_device.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_DSV, MAX_PERSISTENT_DSVS, false, error) ||
!m_sampler_heap_manager.Create(m_device.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, MAX_PERSISTENT_SAMPLERS, false,
error))
{
return false;
}
@ -490,7 +482,7 @@ bool D3D12Device::CreateDescriptorHeaps()
if (!m_descriptor_heap_manager.Allocate(&m_null_srv_descriptor))
{
ERROR_LOG("Failed to allocate null descriptor");
Error::SetStringView(error, "Failed to allocate null SRV descriptor");
return false;
}
@ -774,10 +766,13 @@ u32 D3D12Device::GetSwapChainBufferCount() const
return (m_vsync_mode == GPUVSyncMode::Mailbox) ? 3 : 2;
}
bool D3D12Device::CreateSwapChain()
bool D3D12Device::CreateSwapChain(Error* error)
{
if (m_window_info.type != WindowInfo::Type::Win32)
{
Error::SetStringView(error, "D3D12 expects a Win32 window.");
return false;
}
const D3DCommon::DXGIFormatMapping& fm = D3DCommon::GetFormatMapping(s_swap_chain_format);
@ -853,13 +848,18 @@ bool D3D12Device::CreateSwapChain()
VERBOSE_LOG("Creating a {}x{} windowed swap chain", swap_chain_desc.Width, swap_chain_desc.Height);
hr = m_dxgi_factory->CreateSwapChainForHwnd(m_command_queue.Get(), window_hwnd, &swap_chain_desc, nullptr, nullptr,
m_swap_chain.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
Error::SetHResult(error, "CreateSwapChainForHwnd() failed: ", hr);
return false;
}
}
hr = m_dxgi_factory->MakeWindowAssociation(window_hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
if (FAILED(hr))
WARNING_LOG("MakeWindowAssociation() to disable ALT+ENTER failed");
if (!CreateSwapChainRTV())
if (!CreateSwapChainRTV(error))
{
DestroySwapChain();
return false;
@ -870,12 +870,15 @@ bool D3D12Device::CreateSwapChain()
return true;
}
bool D3D12Device::CreateSwapChainRTV()
bool D3D12Device::CreateSwapChainRTV(Error* error)
{
DXGI_SWAP_CHAIN_DESC swap_chain_desc;
HRESULT hr = m_swap_chain->GetDesc(&swap_chain_desc);
if (FAILED(hr))
{
Error::SetHResult(error, "GetDesc() for swap chain failed: ", hr);
return false;
}
const D3D12_RENDER_TARGET_VIEW_DESC rtv_desc = {swap_chain_desc.BufferDesc.Format, D3D12_RTV_DIMENSION_TEXTURE2D, {}};
@ -885,7 +888,7 @@ bool D3D12Device::CreateSwapChainRTV()
hr = m_swap_chain->GetBuffer(i, IID_PPV_ARGS(backbuffer.GetAddressOf()));
if (FAILED(hr))
{
ERROR_LOG("GetBuffer for RTV failed: 0x{:08X}", static_cast<unsigned>(hr));
Error::SetHResult(error, "GetBuffer for RTV failed: ", hr);
DestroySwapChainRTVs();
return false;
}
@ -895,7 +898,7 @@ bool D3D12Device::CreateSwapChainRTV()
D3D12DescriptorHandle rtv;
if (!m_rtv_heap_manager.Allocate(&rtv))
{
ERROR_LOG("Failed to allocate RTV handle");
Error::SetStringView(error, "Failed to allocate RTV handle.");
DestroySwapChainRTVs();
return false;
}
@ -985,9 +988,10 @@ bool D3D12Device::UpdateWindow()
if (m_window_info.IsSurfaceless())
return true;
if (!CreateSwapChain())
Error error;
if (!CreateSwapChain(&error))
{
ERROR_LOG("Failed to create swap chain on updated window");
ERROR_LOG("Failed to create swap chain on updated window: {}", error.GetDescription());
return false;
}
@ -1015,8 +1019,12 @@ void D3D12Device::ResizeWindow(s32 new_window_width, s32 new_window_height, floa
if (FAILED(hr))
ERROR_LOG("ResizeBuffers() failed: 0x{:08X}", static_cast<unsigned>(hr));
if (!CreateSwapChainRTV())
Error error;
if (!CreateSwapChainRTV(&error))
{
ERROR_LOG("Failed to recreate swap chain RTV after resize", error.GetDescription());
Panic("Failed to recreate swap chain RTV after resize");
}
}
void D3D12Device::DestroySurface()
@ -1083,8 +1091,13 @@ void D3D12Device::SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle)
if (GetSwapChainBufferCount() != old_buffer_count)
{
DestroySwapChain();
if (!CreateSwapChain())
Error error;
if (!CreateSwapChain(&error))
{
ERROR_LOG("Failed to recreate swap chain after vsync change: {}", error.GetDescription());
Panic("Failed to recreate swap chain after vsync change.");
}
}
}
@ -1382,27 +1395,27 @@ void D3D12Device::InvalidateRenderTarget(GPUTexture* t)
EndRenderPass();
}
bool D3D12Device::CreateBuffers()
bool D3D12Device::CreateBuffers(Error* error)
{
if (!m_vertex_buffer.Create(VERTEX_BUFFER_SIZE))
if (!m_vertex_buffer.Create(VERTEX_BUFFER_SIZE, error))
{
ERROR_LOG("Failed to allocate vertex buffer");
return false;
}
if (!m_index_buffer.Create(INDEX_BUFFER_SIZE))
if (!m_index_buffer.Create(INDEX_BUFFER_SIZE, error))
{
ERROR_LOG("Failed to allocate index buffer");
return false;
}
if (!m_uniform_buffer.Create(VERTEX_UNIFORM_BUFFER_SIZE))
if (!m_uniform_buffer.Create(VERTEX_UNIFORM_BUFFER_SIZE, error))
{
ERROR_LOG("Failed to allocate uniform buffer");
return false;
}
if (!m_texture_upload_buffer.Create(TEXTURE_BUFFER_SIZE))
if (!m_texture_upload_buffer.Create(TEXTURE_BUFFER_SIZE, error))
{
ERROR_LOG("Failed to allocate texture upload buffer");
return false;
@ -1509,7 +1522,7 @@ void D3D12Device::UnmapUniformBuffer(u32 size)
m_dirty_flags |= DIRTY_FLAG_CONSTANT_BUFFER;
}
bool D3D12Device::CreateRootSignatures()
bool D3D12Device::CreateRootSignatures(Error* error)
{
D3D12::RootSignatureBuilder rsb;
@ -1520,7 +1533,7 @@ bool D3D12Device::CreateRootSignatures()
rsb.AddDescriptorTable(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1, D3D12_SHADER_VISIBILITY_PIXEL);
rsb.AddDescriptorTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 0, 1, D3D12_SHADER_VISIBILITY_PIXEL);
rsb.AddCBVParameter(0, D3D12_SHADER_VISIBILITY_ALL);
if (!(rs = rsb.Create()))
if (!(rs = rsb.Create(error, true)))
return false;
D3D12::SetObjectName(rs.Get(), "Single Texture + UBO Pipeline Layout");
}
@ -1532,7 +1545,7 @@ bool D3D12Device::CreateRootSignatures()
rsb.AddDescriptorTable(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1, D3D12_SHADER_VISIBILITY_PIXEL);
rsb.AddDescriptorTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 0, 1, D3D12_SHADER_VISIBILITY_PIXEL);
rsb.Add32BitConstants(0, UNIFORM_PUSH_CONSTANTS_SIZE / sizeof(u32), D3D12_SHADER_VISIBILITY_ALL);
if (!(rs = rsb.Create()))
if (!(rs = rsb.Create(error, true)))
return false;
D3D12::SetObjectName(rs.Get(), "Single Texture Pipeline Layout");
}
@ -1543,7 +1556,7 @@ bool D3D12Device::CreateRootSignatures()
rsb.SetInputAssemblerFlag();
rsb.AddDescriptorTable(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1, D3D12_SHADER_VISIBILITY_PIXEL);
rsb.Add32BitConstants(0, UNIFORM_PUSH_CONSTANTS_SIZE / sizeof(u32), D3D12_SHADER_VISIBILITY_ALL);
if (!(rs = rsb.Create()))
if (!(rs = rsb.Create(error, true)))
return false;
D3D12::SetObjectName(rs.Get(), "Single Texture Buffer + UBO Pipeline Layout");
}
@ -1555,7 +1568,7 @@ bool D3D12Device::CreateRootSignatures()
rsb.AddDescriptorTable(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, MAX_TEXTURE_SAMPLERS, D3D12_SHADER_VISIBILITY_PIXEL);
rsb.AddDescriptorTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 0, MAX_TEXTURE_SAMPLERS, D3D12_SHADER_VISIBILITY_PIXEL);
rsb.AddCBVParameter(0, D3D12_SHADER_VISIBILITY_ALL);
if (!(rs = rsb.Create()))
if (!(rs = rsb.Create(error, true)))
return false;
D3D12::SetObjectName(rs.Get(), "Multi Texture + UBO Pipeline Layout");
}
@ -1567,7 +1580,7 @@ bool D3D12Device::CreateRootSignatures()
rsb.AddDescriptorTable(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, MAX_TEXTURE_SAMPLERS, D3D12_SHADER_VISIBILITY_PIXEL);
rsb.AddDescriptorTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 0, MAX_TEXTURE_SAMPLERS, D3D12_SHADER_VISIBILITY_PIXEL);
rsb.Add32BitConstants(0, UNIFORM_PUSH_CONSTANTS_SIZE / sizeof(u32), D3D12_SHADER_VISIBILITY_ALL);
if (!(rs = rsb.Create()))
if (!(rs = rsb.Create(error, true)))
return false;
D3D12::SetObjectName(rs.Get(), "Multi Texture Pipeline Layout");
}