GPUDevice: Improve pipeline error reporting
This commit is contained in:
parent
deed0c9713
commit
ba6b65401d
|
@ -74,7 +74,7 @@ public:
|
|||
std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShaderStage stage, GPUShaderLanguage language,
|
||||
std::string_view source, const char* entry_point,
|
||||
DynamicHeapArray<u8>* out_binary, Error* error) override;
|
||||
std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config) override;
|
||||
std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error) override;
|
||||
|
||||
void PushDebugGroup(const char* name) override;
|
||||
void PopDebugGroup() override;
|
||||
|
@ -144,10 +144,10 @@ private:
|
|||
|
||||
bool IsRenderTargetBound(const GPUTexture* tex) const;
|
||||
|
||||
ComPtr<ID3D11RasterizerState> GetRasterizationState(const GPUPipeline::RasterizationState& rs);
|
||||
ComPtr<ID3D11DepthStencilState> GetDepthState(const GPUPipeline::DepthState& ds);
|
||||
ComPtr<ID3D11BlendState> GetBlendState(const GPUPipeline::BlendState& bs);
|
||||
ComPtr<ID3D11InputLayout> GetInputLayout(const GPUPipeline::InputLayout& il, const D3D11Shader* vs);
|
||||
ComPtr<ID3D11RasterizerState> GetRasterizationState(const GPUPipeline::RasterizationState& rs, Error* error);
|
||||
ComPtr<ID3D11DepthStencilState> GetDepthState(const GPUPipeline::DepthState& ds, Error* error);
|
||||
ComPtr<ID3D11BlendState> GetBlendState(const GPUPipeline::BlendState& bs, Error* error);
|
||||
ComPtr<ID3D11InputLayout> GetInputLayout(const GPUPipeline::InputLayout& il, const D3D11Shader* vs, Error* error);
|
||||
|
||||
bool CreateTimestampQueries();
|
||||
void DestroyTimestampQueries();
|
||||
|
|
|
@ -6,15 +6,12 @@
|
|||
#include "d3d_common.h"
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/log.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include <array>
|
||||
#include <malloc.h>
|
||||
|
||||
Log_SetChannel(D3D11Device);
|
||||
|
||||
D3D11Shader::D3D11Shader(GPUShaderStage stage, Microsoft::WRL::ComPtr<ID3D11DeviceChild> shader,
|
||||
std::vector<u8> bytecode)
|
||||
: GPUShader(stage), m_shader(std::move(shader)), m_bytecode(std::move(bytecode))
|
||||
|
@ -140,7 +137,8 @@ void D3D11Pipeline::SetDebugName(std::string_view name)
|
|||
// can't label this directly
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11RasterizerState> D3D11Device::GetRasterizationState(const GPUPipeline::RasterizationState& rs)
|
||||
D3D11Device::ComPtr<ID3D11RasterizerState> D3D11Device::GetRasterizationState(const GPUPipeline::RasterizationState& rs,
|
||||
Error* error)
|
||||
{
|
||||
ComPtr<ID3D11RasterizerState> drs;
|
||||
|
||||
|
@ -165,13 +163,14 @@ D3D11Device::ComPtr<ID3D11RasterizerState> D3D11Device::GetRasterizationState(co
|
|||
|
||||
HRESULT hr = m_device->CreateRasterizerState(&desc, drs.GetAddressOf());
|
||||
if (FAILED(hr)) [[unlikely]]
|
||||
ERROR_LOG("Failed to create depth state with {:08X}", static_cast<unsigned>(hr));
|
||||
Error::SetHResult(error, "CreateRasterizerState() failed: ", hr);
|
||||
else
|
||||
m_rasterization_states.emplace(rs.key, drs);
|
||||
|
||||
m_rasterization_states.emplace(rs.key, drs);
|
||||
return drs;
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11DepthStencilState> D3D11Device::GetDepthState(const GPUPipeline::DepthState& ds)
|
||||
D3D11Device::ComPtr<ID3D11DepthStencilState> D3D11Device::GetDepthState(const GPUPipeline::DepthState& ds, Error* error)
|
||||
{
|
||||
ComPtr<ID3D11DepthStencilState> dds;
|
||||
|
||||
|
@ -200,13 +199,14 @@ D3D11Device::ComPtr<ID3D11DepthStencilState> D3D11Device::GetDepthState(const GP
|
|||
|
||||
HRESULT hr = m_device->CreateDepthStencilState(&desc, dds.GetAddressOf());
|
||||
if (FAILED(hr)) [[unlikely]]
|
||||
ERROR_LOG("Failed to create depth state with {:08X}", static_cast<unsigned>(hr));
|
||||
Error::SetHResult(error, "CreateDepthStencilState() failed: ", hr);
|
||||
else
|
||||
m_depth_states.emplace(ds.key, dds);
|
||||
|
||||
m_depth_states.emplace(ds.key, dds);
|
||||
return dds;
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11BlendState> D3D11Device::GetBlendState(const GPUPipeline::BlendState& bs)
|
||||
D3D11Device::ComPtr<ID3D11BlendState> D3D11Device::GetBlendState(const GPUPipeline::BlendState& bs, Error* error)
|
||||
{
|
||||
ComPtr<ID3D11BlendState> dbs;
|
||||
|
||||
|
@ -258,14 +258,15 @@ D3D11Device::ComPtr<ID3D11BlendState> D3D11Device::GetBlendState(const GPUPipeli
|
|||
|
||||
HRESULT hr = m_device->CreateBlendState(&blend_desc, dbs.GetAddressOf());
|
||||
if (FAILED(hr)) [[unlikely]]
|
||||
ERROR_LOG("Failed to create blend state with {:08X}", static_cast<unsigned>(hr));
|
||||
Error::SetHResult(error, "CreateBlendState() failed: ", hr);
|
||||
else
|
||||
m_blend_states.emplace(bs.key, dbs);
|
||||
|
||||
m_blend_states.emplace(bs.key, dbs);
|
||||
return dbs;
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11InputLayout> D3D11Device::GetInputLayout(const GPUPipeline::InputLayout& il,
|
||||
const D3D11Shader* vs)
|
||||
const D3D11Shader* vs, Error* error)
|
||||
{
|
||||
ComPtr<ID3D11InputLayout> dil;
|
||||
const auto it = m_input_layouts.find(il);
|
||||
|
@ -310,17 +311,18 @@ D3D11Device::ComPtr<ID3D11InputLayout> D3D11Device::GetInputLayout(const GPUPipe
|
|||
HRESULT hr = m_device->CreateInputLayout(elems, static_cast<UINT>(il.vertex_attributes.size()),
|
||||
vs->GetBytecode().data(), vs->GetBytecode().size(), dil.GetAddressOf());
|
||||
if (FAILED(hr)) [[unlikely]]
|
||||
ERROR_LOG("Failed to create input layout with {:08X}", static_cast<unsigned>(hr));
|
||||
Error::SetHResult(error, "CreateInputLayout() failed: ", hr);
|
||||
else
|
||||
m_input_layouts.emplace(il, dil);
|
||||
|
||||
m_input_layouts.emplace(il, dil);
|
||||
return dil;
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::GraphicsConfig& config)
|
||||
std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error)
|
||||
{
|
||||
ComPtr<ID3D11RasterizerState> rs = GetRasterizationState(config.rasterization);
|
||||
ComPtr<ID3D11DepthStencilState> ds = GetDepthState(config.depth);
|
||||
ComPtr<ID3D11BlendState> bs = GetBlendState(config.blend);
|
||||
ComPtr<ID3D11RasterizerState> rs = GetRasterizationState(config.rasterization, error);
|
||||
ComPtr<ID3D11DepthStencilState> ds = GetDepthState(config.depth, error);
|
||||
ComPtr<ID3D11BlendState> bs = GetBlendState(config.blend, error);
|
||||
if (!rs || !ds || !bs)
|
||||
return {};
|
||||
|
||||
|
@ -328,7 +330,7 @@ std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::Grap
|
|||
u32 vertex_stride = 0;
|
||||
if (!config.input_layout.vertex_attributes.empty())
|
||||
{
|
||||
il = GetInputLayout(config.input_layout, static_cast<const D3D11Shader*>(config.vertex_shader));
|
||||
il = GetInputLayout(config.input_layout, static_cast<const D3D11Shader*>(config.vertex_shader), error);
|
||||
vertex_stride = config.input_layout.vertex_stride;
|
||||
if (!il)
|
||||
return {};
|
||||
|
|
|
@ -5,14 +5,12 @@
|
|||
#include "d3d12_device.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/log.h"
|
||||
#include "common/error.h"
|
||||
#include "common/string_util.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <limits>
|
||||
|
||||
Log_SetChannel(D3D12Device);
|
||||
|
||||
D3D12::GraphicsPipelineBuilder::GraphicsPipelineBuilder()
|
||||
{
|
||||
Clear();
|
||||
|
@ -27,14 +25,14 @@ void D3D12::GraphicsPipelineBuilder::Clear()
|
|||
m_desc.SampleDesc.Count = 1;
|
||||
}
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12PipelineState> D3D12::GraphicsPipelineBuilder::Create(ID3D12Device* device,
|
||||
bool clear /*= true*/)
|
||||
Microsoft::WRL::ComPtr<ID3D12PipelineState> D3D12::GraphicsPipelineBuilder::Create(ID3D12Device* device, Error* error,
|
||||
bool clear)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<ID3D12PipelineState> ps;
|
||||
HRESULT hr = device->CreateGraphicsPipelineState(&m_desc, IID_PPV_ARGS(ps.GetAddressOf()));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ERROR_LOG("CreateGraphicsPipelineState() failed: {:08X}", static_cast<unsigned>(hr));
|
||||
Error::SetHResult(error, "CreateGraphicsPipelineState() failed: ", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -218,14 +216,14 @@ void D3D12::ComputePipelineBuilder::Clear()
|
|||
std::memset(&m_desc, 0, sizeof(m_desc));
|
||||
}
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12PipelineState> D3D12::ComputePipelineBuilder::Create(ID3D12Device* device,
|
||||
bool clear /*= true*/)
|
||||
Microsoft::WRL::ComPtr<ID3D12PipelineState> D3D12::ComputePipelineBuilder::Create(ID3D12Device* device, Error* error,
|
||||
bool clear)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<ID3D12PipelineState> ps;
|
||||
HRESULT hr = device->CreateComputePipelineState(&m_desc, IID_PPV_ARGS(ps.GetAddressOf()));
|
||||
if (FAILED(hr)) [[unlikely]]
|
||||
{
|
||||
ERROR_LOG("CreateComputePipelineState() failed: {:08X}", static_cast<unsigned>(hr));
|
||||
Error::SetHResult(error, "CreateComputePipelineState() failed: ", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -260,9 +258,9 @@ void D3D12::RootSignatureBuilder::Clear()
|
|||
m_num_descriptor_ranges = 0;
|
||||
}
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12RootSignature> D3D12::RootSignatureBuilder::Create(bool clear /*= true*/)
|
||||
Microsoft::WRL::ComPtr<ID3D12RootSignature> D3D12::RootSignatureBuilder::Create(Error* error, bool clear)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<ID3D12RootSignature> rs = D3D12Device::GetInstance().CreateRootSignature(&m_desc);
|
||||
Microsoft::WRL::ComPtr<ID3D12RootSignature> rs = D3D12Device::GetInstance().CreateRootSignature(&m_desc, error);
|
||||
if (!rs)
|
||||
return {};
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include <string_view>
|
||||
#include <wrl/client.h>
|
||||
|
||||
class Error;
|
||||
|
||||
namespace D3D12 {
|
||||
class RootSignatureBuilder
|
||||
{
|
||||
|
@ -25,7 +27,7 @@ public:
|
|||
|
||||
void Clear();
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12RootSignature> Create(bool clear = true);
|
||||
Microsoft::WRL::ComPtr<ID3D12RootSignature> Create(Error* error, bool clear);
|
||||
|
||||
void SetInputAssemblerFlag();
|
||||
|
||||
|
@ -58,7 +60,7 @@ public:
|
|||
|
||||
void Clear();
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12PipelineState> Create(ID3D12Device* device, bool clear = true);
|
||||
Microsoft::WRL::ComPtr<ID3D12PipelineState> Create(ID3D12Device* device, Error* error, bool clear);
|
||||
|
||||
void SetRootSignature(ID3D12RootSignature* rs);
|
||||
|
||||
|
@ -115,7 +117,7 @@ public:
|
|||
|
||||
void Clear();
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12PipelineState> Create(ID3D12Device* device, bool clear = true);
|
||||
Microsoft::WRL::ComPtr<ID3D12PipelineState> Create(ID3D12Device* device, Error* error, bool clear);
|
||||
|
||||
void SetRootSignature(ID3D12RootSignature* rs);
|
||||
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "d3d12_descriptor_heap_manager.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/log.h"
|
||||
|
||||
Log_SetChannel(D3D12Device);
|
||||
#include "common/error.h"
|
||||
|
||||
D3D12DescriptorHeapManager::D3D12DescriptorHeapManager() = default;
|
||||
D3D12DescriptorHeapManager::~D3D12DescriptorHeapManager() = default;
|
||||
|
||||
bool D3D12DescriptorHeapManager::Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors,
|
||||
bool shader_visible)
|
||||
bool shader_visible, Error* error)
|
||||
{
|
||||
D3D12_DESCRIPTOR_HEAP_DESC desc = {
|
||||
type, static_cast<UINT>(num_descriptors),
|
||||
|
@ -21,7 +19,7 @@ bool D3D12DescriptorHeapManager::Create(ID3D12Device* device, D3D12_DESCRIPTOR_H
|
|||
HRESULT hr = device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(m_descriptor_heap.ReleaseAndGetAddressOf()));
|
||||
if (FAILED(hr)) [[unlikely]]
|
||||
{
|
||||
ERROR_LOG("CreateDescriptorHeap() failed: {:08X}", static_cast<unsigned>(hr));
|
||||
Error::SetHResult(error, "CreateDescriptorHeap() failed: ", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -110,14 +108,14 @@ void D3D12DescriptorHeapManager::Free(D3D12DescriptorHandle* handle)
|
|||
D3D12DescriptorAllocator::D3D12DescriptorAllocator() = default;
|
||||
D3D12DescriptorAllocator::~D3D12DescriptorAllocator() = default;
|
||||
|
||||
bool D3D12DescriptorAllocator::Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors)
|
||||
bool D3D12DescriptorAllocator::Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors, Error* error)
|
||||
{
|
||||
const D3D12_DESCRIPTOR_HEAP_DESC desc = {type, static_cast<UINT>(num_descriptors),
|
||||
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 0u};
|
||||
const HRESULT hr = device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(m_descriptor_heap.ReleaseAndGetAddressOf()));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ERROR_LOG("CreateDescriptorHeap() failed: {:08X}", static_cast<unsigned>(hr));
|
||||
Error::SetHResult(error, "CreateDescriptorHeap() failed: ", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
@ -14,6 +14,8 @@
|
|||
#include <vector>
|
||||
#include <wrl/client.h>
|
||||
|
||||
class Error;
|
||||
|
||||
// This class provides an abstraction for D3D12 descriptor heaps.
|
||||
struct D3D12DescriptorHandle final
|
||||
{
|
||||
|
@ -55,7 +57,8 @@ public:
|
|||
ID3D12DescriptorHeap* GetDescriptorHeap() const { return m_descriptor_heap.Get(); }
|
||||
u32 GetDescriptorIncrementSize() const { return m_descriptor_increment_size; }
|
||||
|
||||
bool Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors, bool shader_visible);
|
||||
bool Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors, bool shader_visible,
|
||||
Error* error);
|
||||
void Destroy();
|
||||
|
||||
bool Allocate(D3D12DescriptorHandle* handle);
|
||||
|
@ -85,7 +88,7 @@ public:
|
|||
ALWAYS_INLINE ID3D12DescriptorHeap* GetDescriptorHeap() const { return m_descriptor_heap.Get(); }
|
||||
ALWAYS_INLINE u32 GetDescriptorIncrementSize() const { return m_descriptor_increment_size; }
|
||||
|
||||
bool Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors);
|
||||
bool Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors, Error* error);
|
||||
void Destroy();
|
||||
|
||||
bool Allocate(u32 num_handles, D3D12DescriptorHandle* out_base_handle);
|
||||
|
@ -130,7 +133,7 @@ public:
|
|||
using D3D12DescriptorAllocator::GetDescriptorHeap;
|
||||
using D3D12DescriptorAllocator::GetDescriptorIncrementSize;
|
||||
|
||||
bool Create(ID3D12Device* device, u32 num_descriptors);
|
||||
bool Create(ID3D12Device* device, u32 num_descriptors, Error* error);
|
||||
void Destroy();
|
||||
|
||||
bool LookupSingle(ID3D12Device* device, D3D12DescriptorHandle* gpu_handle, const D3D12DescriptorHandle& cpu_handle);
|
||||
|
@ -153,9 +156,9 @@ template<u32 NumSamplers>
|
|||
D3D12GroupedSamplerAllocator<NumSamplers>::~D3D12GroupedSamplerAllocator() = default;
|
||||
|
||||
template<u32 NumSamplers>
|
||||
bool D3D12GroupedSamplerAllocator<NumSamplers>::Create(ID3D12Device* device, u32 num_descriptors)
|
||||
bool D3D12GroupedSamplerAllocator<NumSamplers>::Create(ID3D12Device* device, u32 num_descriptors, Error* error)
|
||||
{
|
||||
return D3D12DescriptorAllocator::Create(device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, num_descriptors);
|
||||
return D3D12DescriptorAllocator::Create(device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, num_descriptors, error);
|
||||
}
|
||||
|
||||
template<u32 NumSamplers>
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShaderStage stage, GPUShaderLanguage language,
|
||||
std::string_view source, const char* entry_point,
|
||||
DynamicHeapArray<u8>* out_binary, Error* error) override;
|
||||
std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config) override;
|
||||
std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error) override;
|
||||
|
||||
void PushDebugGroup(const char* name) override;
|
||||
void PopDebugGroup() override;
|
||||
|
@ -155,8 +155,8 @@ public:
|
|||
ID3D12GraphicsCommandList4* GetInitCommandList();
|
||||
|
||||
// Root signature access.
|
||||
ComPtr<ID3DBlob> SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc);
|
||||
ComPtr<ID3D12RootSignature> CreateRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc);
|
||||
ComPtr<ID3DBlob> SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc, Error* error);
|
||||
ComPtr<ID3D12RootSignature> CreateRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc, Error* error);
|
||||
|
||||
/// Fence value for current command list.
|
||||
u64 GetCurrentFenceValue() const { return m_current_fence_value; }
|
||||
|
@ -223,18 +223,18 @@ private:
|
|||
void SetFeatures(FeatureMask disabled_features);
|
||||
|
||||
u32 GetSwapChainBufferCount() const;
|
||||
bool CreateSwapChain();
|
||||
bool CreateSwapChainRTV();
|
||||
bool CreateSwapChain(Error* error);
|
||||
bool CreateSwapChainRTV(Error* error);
|
||||
void DestroySwapChainRTVs();
|
||||
void DestroySwapChain();
|
||||
|
||||
bool CreateCommandLists();
|
||||
bool CreateCommandLists(Error* error);
|
||||
void DestroyCommandLists();
|
||||
bool CreateRootSignatures();
|
||||
bool CreateRootSignatures(Error* error);
|
||||
void DestroyRootSignatures();
|
||||
bool CreateBuffers();
|
||||
bool CreateBuffers(Error* error);
|
||||
void DestroyBuffers();
|
||||
bool CreateDescriptorHeaps();
|
||||
bool CreateDescriptorHeaps(Error* error);
|
||||
void DestroyDescriptorHeaps();
|
||||
bool CreateTimestampQuery();
|
||||
void DestroyTimestampQuery();
|
||||
|
|
|
@ -106,7 +106,7 @@ std::string D3D12Pipeline::GetPipelineName(const GraphicsConfig& config)
|
|||
return SHA1Digest::DigestToString(digest);
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUPipeline> D3D12Device::CreatePipeline(const GPUPipeline::GraphicsConfig& config)
|
||||
std::unique_ptr<GPUPipeline> D3D12Device::CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error)
|
||||
{
|
||||
static constexpr std::array<D3D12_PRIMITIVE_TOPOLOGY, static_cast<u32>(GPUPipeline::Primitive::MaxCount)> primitives =
|
||||
{{
|
||||
|
@ -242,7 +242,7 @@ std::unique_ptr<GPUPipeline> D3D12Device::CreatePipeline(const GPUPipeline::Grap
|
|||
ERROR_LOG("LoadGraphicsPipeline() failed with HRESULT {:08X}", static_cast<unsigned>(hr));
|
||||
|
||||
// Need to create it normally.
|
||||
pipeline = gpb.Create(m_device.Get(), false);
|
||||
pipeline = gpb.Create(m_device.Get(), error, false);
|
||||
|
||||
// Store if it wasn't an OOM or something else.
|
||||
if (pipeline && hr == E_INVALIDARG)
|
||||
|
@ -255,7 +255,7 @@ std::unique_ptr<GPUPipeline> D3D12Device::CreatePipeline(const GPUPipeline::Grap
|
|||
}
|
||||
else
|
||||
{
|
||||
pipeline = gpb.Create(m_device.Get(), false);
|
||||
pipeline = gpb.Create(m_device.Get(), error, false);
|
||||
}
|
||||
|
||||
if (!pipeline)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "d3d12_stream_buffer.h"
|
||||
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "common/align.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/error.h"
|
||||
#include "common/log.h"
|
||||
|
||||
#include "D3D12MemAlloc.h"
|
||||
|
@ -21,7 +22,7 @@ D3D12StreamBuffer::~D3D12StreamBuffer()
|
|||
Destroy();
|
||||
}
|
||||
|
||||
bool D3D12StreamBuffer::Create(u32 size)
|
||||
bool D3D12StreamBuffer::Create(u32 size, Error* error)
|
||||
{
|
||||
const D3D12_RESOURCE_DESC resource_desc = {
|
||||
D3D12_RESOURCE_DIMENSION_BUFFER, 0, size, 1, 1, 1, DXGI_FORMAT_UNKNOWN, {1, 0}, D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
|
@ -38,7 +39,7 @@ bool D3D12StreamBuffer::Create(u32 size)
|
|||
IID_PPV_ARGS(buffer.GetAddressOf()));
|
||||
if (FAILED(hr)) [[unlikely]]
|
||||
{
|
||||
ERROR_LOG("CreateResource() failed: {:08X}", static_cast<unsigned>(hr));
|
||||
Error::SetHResult(error, "CreateResource() for stream buffer failed: ", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -47,7 +48,7 @@ bool D3D12StreamBuffer::Create(u32 size)
|
|||
hr = buffer->Map(0, &read_range, reinterpret_cast<void**>(&host_pointer));
|
||||
if (FAILED(hr)) [[unlikely]]
|
||||
{
|
||||
ERROR_LOG("Map() failed: {:08X}", static_cast<unsigned>(hr));
|
||||
Error::SetHResult(error, "Map() for stream buffer failed: ", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
@ -11,6 +11,8 @@
|
|||
#include <utility>
|
||||
#include <wrl/client.h>
|
||||
|
||||
class Error;
|
||||
|
||||
namespace D3D12MA {
|
||||
class Allocation;
|
||||
}
|
||||
|
@ -21,7 +23,7 @@ public:
|
|||
D3D12StreamBuffer();
|
||||
~D3D12StreamBuffer();
|
||||
|
||||
bool Create(u32 size);
|
||||
bool Create(u32 size, Error* error);
|
||||
|
||||
ALWAYS_INLINE bool IsValid() const { return static_cast<bool>(m_buffer); }
|
||||
ALWAYS_INLINE ID3D12Resource* GetBuffer() const { return m_buffer.Get(); }
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "common/align.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/bitutils.h"
|
||||
#include "common/error.h"
|
||||
#include "common/log.h"
|
||||
#include "common/string_util.h"
|
||||
|
||||
|
@ -763,10 +764,14 @@ bool D3D12TextureBuffer::Create(D3D12Device& dev)
|
|||
DXGI_FORMAT_R16_UINT, // R16UI
|
||||
}};
|
||||
|
||||
if (!m_buffer.Create(GetSizeInBytes()))
|
||||
Error error;
|
||||
if (!m_buffer.Create(GetSizeInBytes(), &error)) [[unlikely]]
|
||||
{
|
||||
ERROR_LOG("Failed to create stream buffer: {}", error.GetDescription());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!dev.GetDescriptorHeapManager().Allocate(&m_descriptor))
|
||||
if (!dev.GetDescriptorHeapManager().Allocate(&m_descriptor)) [[unlikely]]
|
||||
return {};
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC desc = {format_mapping[static_cast<u8>(m_format)],
|
||||
|
|
|
@ -533,7 +533,10 @@ bool GPUDevice::CreateResources(Error* error)
|
|||
std::unique_ptr<GPUShader> imgui_fs =
|
||||
CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), shadergen.GenerateImGuiFragmentShader(), error);
|
||||
if (!imgui_vs || !imgui_fs)
|
||||
{
|
||||
Error::AddPrefix(error, "Failed to compile ImGui shaders: ");
|
||||
return false;
|
||||
}
|
||||
GL_OBJECT_NAME(imgui_vs, "ImGui Vertex Shader");
|
||||
GL_OBJECT_NAME(imgui_fs, "ImGui Fragment Shader");
|
||||
|
||||
|
@ -563,10 +566,10 @@ bool GPUDevice::CreateResources(Error* error)
|
|||
plconfig.geometry_shader = nullptr;
|
||||
plconfig.fragment_shader = imgui_fs.get();
|
||||
|
||||
m_imgui_pipeline = CreatePipeline(plconfig);
|
||||
m_imgui_pipeline = CreatePipeline(plconfig, error);
|
||||
if (!m_imgui_pipeline)
|
||||
{
|
||||
Error::SetStringView(error, "Failed to compile ImGui pipeline.");
|
||||
Error::AddPrefix(error, "Failed to compile ImGui pipeline: ");
|
||||
return false;
|
||||
}
|
||||
GL_OBJECT_NAME(m_imgui_pipeline, "ImGui Pipeline");
|
||||
|
|
|
@ -650,7 +650,8 @@ public:
|
|||
/// Shader abstraction.
|
||||
std::unique_ptr<GPUShader> CreateShader(GPUShaderStage stage, GPUShaderLanguage language, std::string_view source,
|
||||
Error* error = nullptr, const char* entry_point = "main");
|
||||
virtual std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config) = 0;
|
||||
virtual std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config,
|
||||
Error* error = nullptr) = 0;
|
||||
|
||||
/// Debug messaging.
|
||||
virtual void PushDebugGroup(const char* name) = 0;
|
||||
|
|
|
@ -235,7 +235,7 @@ public:
|
|||
std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShaderStage stage, GPUShaderLanguage language,
|
||||
std::string_view source, const char* entry_point,
|
||||
DynamicHeapArray<u8>* out_binary, Error* error) override;
|
||||
std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config) override;
|
||||
std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error) override;
|
||||
|
||||
void PushDebugGroup(const char* name) override;
|
||||
void PopDebugGroup() override;
|
||||
|
|
|
@ -76,6 +76,11 @@ static void LogNSError(NSError* error, std::string_view message)
|
|||
Log::FastWrite("MetalDevice", LOGLEVEL_ERROR, " NSError Description: {}", [error.description UTF8String]);
|
||||
}
|
||||
|
||||
static void NSErrorToErrorObject(Error* errptr, std::string_view message, NSError* error)
|
||||
{
|
||||
Error::SetStringFmt(errptr, "{}NSError Code {}: {}", message, static_cast<u32>(error.code), [error.description UTF8String]);
|
||||
}
|
||||
|
||||
static GPUTexture::Format GetTextureFormatForMTLFormat(MTLPixelFormat fmt)
|
||||
{
|
||||
for (u32 i = 0; i < static_cast<u32>(GPUTexture::Format::MaxCount); i++)
|
||||
|
@ -719,7 +724,7 @@ id<MTLDepthStencilState> MetalDevice::GetDepthState(const GPUPipeline::DepthStat
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUPipeline> MetalDevice::CreatePipeline(const GPUPipeline::GraphicsConfig& config)
|
||||
std::unique_ptr<GPUPipeline> MetalDevice::CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
|
@ -857,11 +862,12 @@ std::unique_ptr<GPUPipeline> MetalDevice::CreatePipeline(const GPUPipeline::Grap
|
|||
if (config.layout == GPUPipeline::Layout::SingleTextureBufferAndPushConstants)
|
||||
desc.fragmentBuffers[1].mutability = MTLMutabilityImmutable;
|
||||
|
||||
NSError* error = nullptr;
|
||||
id<MTLRenderPipelineState> pipeline = [m_device newRenderPipelineStateWithDescriptor:desc error:&error];
|
||||
NSError* nserror = nullptr;
|
||||
id<MTLRenderPipelineState> pipeline = [m_device newRenderPipelineStateWithDescriptor:desc error:&nserror];
|
||||
if (pipeline == nil)
|
||||
{
|
||||
LogNSError(error, "Failed to create render pipeline state");
|
||||
LogNSError(nserror, "Failed to create render pipeline state");
|
||||
NSErrorToErrorObject(error, "newRenderPipelineStateWithDescriptor failed: ", nserror);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "common/align.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/error.h"
|
||||
#include "common/log.h"
|
||||
#include "common/string_util.h"
|
||||
|
||||
|
@ -50,6 +51,11 @@ bool OpenGLDevice::ShouldUsePBOsForDownloads()
|
|||
return !GetInstance().m_disable_pbo && !GetInstance().m_disable_async_download;
|
||||
}
|
||||
|
||||
void OpenGLDevice::SetErrorObject(Error* errptr, std::string_view prefix, GLenum glerr)
|
||||
{
|
||||
Error::SetStringFmt(errptr, "{}GL Error 0x{:04X}", prefix, static_cast<unsigned>(glerr));
|
||||
}
|
||||
|
||||
RenderAPI OpenGLDevice::GetRenderAPI() const
|
||||
{
|
||||
return m_gl_context->IsGLES() ? RenderAPI::OpenGLES : RenderAPI::OpenGL;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
|
||||
class OpenGLPipeline;
|
||||
|
@ -37,6 +38,7 @@ public:
|
|||
ALWAYS_INLINE static bool IsGLES() { return GetInstance().m_gl_context->IsGLES(); }
|
||||
static void BindUpdateTextureUnit();
|
||||
static bool ShouldUsePBOsForDownloads();
|
||||
static void SetErrorObject(Error* errptr, std::string_view prefix, GLenum glerr);
|
||||
|
||||
RenderAPI GetRenderAPI() const override;
|
||||
|
||||
|
@ -75,7 +77,7 @@ public:
|
|||
std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShaderStage stage, GPUShaderLanguage language,
|
||||
std::string_view source, const char* entry_point,
|
||||
DynamicHeapArray<u8>* out_binary, Error* error) override;
|
||||
std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config) override;
|
||||
std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error) override;
|
||||
|
||||
void PushDebugGroup(const char* name) override;
|
||||
void PopDebugGroup() override;
|
||||
|
@ -113,13 +115,13 @@ public:
|
|||
void CommitRTClearInFB(OpenGLTexture* tex, u32 idx);
|
||||
void CommitDSClearInFB(OpenGLTexture* tex);
|
||||
|
||||
GLuint LookupProgramCache(const OpenGLPipeline::ProgramCacheKey& key, const GPUPipeline::GraphicsConfig& plconfig);
|
||||
GLuint CompileProgram(const GPUPipeline::GraphicsConfig& plconfig);
|
||||
GLuint LookupProgramCache(const OpenGLPipeline::ProgramCacheKey& key, const GPUPipeline::GraphicsConfig& plconfig, Error* error);
|
||||
GLuint CompileProgram(const GPUPipeline::GraphicsConfig& plconfig, Error* error);
|
||||
void PostLinkProgram(const GPUPipeline::GraphicsConfig& plconfig, GLuint program_id);
|
||||
void UnrefProgram(const OpenGLPipeline::ProgramCacheKey& key);
|
||||
|
||||
OpenGLPipeline::VertexArrayCache::const_iterator LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key);
|
||||
GLuint CreateVAO(std::span<const GPUPipeline::VertexAttribute> attributes, u32 stride);
|
||||
OpenGLPipeline::VertexArrayCache::const_iterator LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key, Error* error);
|
||||
GLuint CreateVAO(std::span<const GPUPipeline::VertexAttribute> attributes, u32 stride, Error* error);
|
||||
void UnrefVAO(const OpenGLPipeline::VertexArrayCacheKey& key);
|
||||
|
||||
void SetActiveTexture(u32 slot);
|
||||
|
|
|
@ -98,10 +98,18 @@ void OpenGLShader::SetDebugName(std::string_view name)
|
|||
#endif
|
||||
}
|
||||
|
||||
bool OpenGLShader::Compile()
|
||||
bool OpenGLShader::Compile(Error* error)
|
||||
{
|
||||
if (m_compile_tried)
|
||||
return m_id.has_value();
|
||||
{
|
||||
if (!m_id.has_value()) [[unlikely]]
|
||||
{
|
||||
Error::SetStringView(error, "Shader previously failed to compile.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
m_compile_tried = true;
|
||||
|
||||
|
@ -111,6 +119,7 @@ bool OpenGLShader::Compile()
|
|||
if (GLenum err = glGetError(); err != GL_NO_ERROR)
|
||||
{
|
||||
ERROR_LOG("glCreateShader() failed: {}", err);
|
||||
OpenGLDevice::SetErrorObject(error, "glCreateShader() failed: ", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -138,6 +147,7 @@ bool OpenGLShader::Compile()
|
|||
else
|
||||
{
|
||||
ERROR_LOG("Shader failed to compile:\n{}", info_log);
|
||||
Error::SetStringFmt(error, "Shader failed to compile:\n{}", info_log);
|
||||
GPUDevice::DumpBadShader(m_source, info_log);
|
||||
glDeleteShader(shader);
|
||||
return false;
|
||||
|
@ -268,7 +278,7 @@ OpenGLPipeline::ProgramCacheKey OpenGLPipeline::GetProgramCacheKey(const Graphic
|
|||
}
|
||||
|
||||
GLuint OpenGLDevice::LookupProgramCache(const OpenGLPipeline::ProgramCacheKey& key,
|
||||
const GPUPipeline::GraphicsConfig& plconfig)
|
||||
const GPUPipeline::GraphicsConfig& plconfig, Error* error)
|
||||
{
|
||||
auto it = m_program_cache.find(key);
|
||||
if (it != m_program_cache.end() && it->second.program_id == 0 && it->second.file_uncompressed_size > 0)
|
||||
|
@ -291,7 +301,7 @@ GLuint OpenGLDevice::LookupProgramCache(const OpenGLPipeline::ProgramCacheKey& k
|
|||
return it->second.program_id;
|
||||
}
|
||||
|
||||
const GLuint program_id = CompileProgram(plconfig);
|
||||
const GLuint program_id = CompileProgram(plconfig, error);
|
||||
if (program_id == 0)
|
||||
{
|
||||
// Compile failed, don't add to map, it just gets confusing.
|
||||
|
@ -312,23 +322,22 @@ GLuint OpenGLDevice::LookupProgramCache(const OpenGLPipeline::ProgramCacheKey& k
|
|||
return item.program_id;
|
||||
}
|
||||
|
||||
GLuint OpenGLDevice::CompileProgram(const GPUPipeline::GraphicsConfig& plconfig)
|
||||
GLuint OpenGLDevice::CompileProgram(const GPUPipeline::GraphicsConfig& plconfig, Error* error)
|
||||
{
|
||||
OpenGLShader* vertex_shader = static_cast<OpenGLShader*>(plconfig.vertex_shader);
|
||||
OpenGLShader* fragment_shader = static_cast<OpenGLShader*>(plconfig.fragment_shader);
|
||||
OpenGLShader* geometry_shader = static_cast<OpenGLShader*>(plconfig.geometry_shader);
|
||||
if (!vertex_shader || !fragment_shader || !vertex_shader->Compile() || !fragment_shader->Compile() ||
|
||||
(geometry_shader && !geometry_shader->Compile())) [[unlikely]]
|
||||
if (!vertex_shader || !fragment_shader || !vertex_shader->Compile(error) || !fragment_shader->Compile(error) ||
|
||||
(geometry_shader && !geometry_shader->Compile(error))) [[unlikely]]
|
||||
{
|
||||
ERROR_LOG("Failed to compile shaders.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
glGetError();
|
||||
const GLuint program_id = glCreateProgram();
|
||||
if (glGetError() != GL_NO_ERROR) [[unlikely]]
|
||||
if (const GLenum err = glGetError(); err != GL_NO_ERROR) [[unlikely]]
|
||||
{
|
||||
ERROR_LOG("Failed to create program object.");
|
||||
SetErrorObject(error, "glCreateProgram() failed: ", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -412,6 +421,7 @@ GLuint OpenGLDevice::CompileProgram(const GPUPipeline::GraphicsConfig& plconfig)
|
|||
}
|
||||
|
||||
ERROR_LOG("Program failed to link:\n{}", info_log);
|
||||
Error::SetStringFmt(error, "Program failed to link:\n{}", info_log);
|
||||
glDeleteProgram(program_id);
|
||||
return 0;
|
||||
}
|
||||
|
@ -468,7 +478,7 @@ void OpenGLDevice::UnrefProgram(const OpenGLPipeline::ProgramCacheKey& key)
|
|||
}
|
||||
|
||||
OpenGLPipeline::VertexArrayCache::const_iterator
|
||||
OpenGLDevice::LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key)
|
||||
OpenGLDevice::LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key, Error* error)
|
||||
{
|
||||
OpenGLPipeline::VertexArrayCache::iterator it = m_vao_cache.find(key);
|
||||
if (it != m_vao_cache.end())
|
||||
|
@ -480,7 +490,7 @@ OpenGLDevice::LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key)
|
|||
OpenGLPipeline::VertexArrayCacheItem item;
|
||||
item.vao_id =
|
||||
CreateVAO(std::span<const GPUPipeline::VertexAttribute>(key.vertex_attributes, key.num_vertex_attributes),
|
||||
key.vertex_attribute_stride);
|
||||
key.vertex_attribute_stride, error);
|
||||
if (item.vao_id == 0)
|
||||
return m_vao_cache.cend();
|
||||
|
||||
|
@ -488,7 +498,7 @@ OpenGLDevice::LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key)
|
|||
return m_vao_cache.emplace(key, item).first;
|
||||
}
|
||||
|
||||
GLuint OpenGLDevice::CreateVAO(std::span<const GPUPipeline::VertexAttribute> attributes, u32 stride)
|
||||
GLuint OpenGLDevice::CreateVAO(std::span<const GPUPipeline::VertexAttribute> attributes, u32 stride, Error* error)
|
||||
{
|
||||
glGetError();
|
||||
GLuint vao;
|
||||
|
@ -496,6 +506,7 @@ GLuint OpenGLDevice::CreateVAO(std::span<const GPUPipeline::VertexAttribute> att
|
|||
if (const GLenum err = glGetError(); err != GL_NO_ERROR)
|
||||
{
|
||||
ERROR_LOG("Failed to create vertex array object: {}", err);
|
||||
SetErrorObject(error, "glGenVertexArrays() failed: ", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -582,15 +593,15 @@ void OpenGLPipeline::SetDebugName(std::string_view name)
|
|||
#endif
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUPipeline> OpenGLDevice::CreatePipeline(const GPUPipeline::GraphicsConfig& config)
|
||||
std::unique_ptr<GPUPipeline> OpenGLDevice::CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error)
|
||||
{
|
||||
const OpenGLPipeline::ProgramCacheKey pkey = OpenGLPipeline::GetProgramCacheKey(config);
|
||||
|
||||
const GLuint program_id = LookupProgramCache(pkey, config);
|
||||
const GLuint program_id = LookupProgramCache(pkey, config, error);
|
||||
if (program_id == 0)
|
||||
return {};
|
||||
|
||||
const OpenGLPipeline::VertexArrayCache::const_iterator vao = LookupVAOCache(pkey.va_key);
|
||||
const OpenGLPipeline::VertexArrayCache::const_iterator vao = LookupVAOCache(pkey.va_key, error);
|
||||
if (vao == m_vao_cache.cend())
|
||||
{
|
||||
UnrefProgram(pkey);
|
||||
|
|
|
@ -18,7 +18,7 @@ public:
|
|||
|
||||
void SetDebugName(std::string_view name) override;
|
||||
|
||||
bool Compile();
|
||||
bool Compile(Error* error);
|
||||
|
||||
ALWAYS_INLINE GLuint GetGLId() const { return m_id.value(); }
|
||||
ALWAYS_INLINE const GPUShaderCache::CacheIndexKey& GetKey() const { return m_key; }
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "vulkan_builders.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/error.h"
|
||||
#include "common/log.h"
|
||||
|
||||
#include <limits>
|
||||
|
@ -109,6 +110,11 @@ void Vulkan::LogVulkanResult(const char* func_name, VkResult res, std::string_vi
|
|||
VkResultToString(res));
|
||||
}
|
||||
|
||||
void Vulkan::SetErrorObject(Error* errptr, std::string_view prefix, VkResult res)
|
||||
{
|
||||
Error::SetStringFmt(errptr, "{} (0x{:08X}: {})", prefix, static_cast<unsigned>(res), VkResultToString(res));
|
||||
}
|
||||
|
||||
Vulkan::DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder()
|
||||
{
|
||||
Clear();
|
||||
|
@ -277,14 +283,15 @@ void Vulkan::GraphicsPipelineBuilder::Clear()
|
|||
SetMultisamples(VK_SAMPLE_COUNT_1_BIT);
|
||||
}
|
||||
|
||||
VkPipeline Vulkan::GraphicsPipelineBuilder::Create(VkDevice device, VkPipelineCache pipeline_cache,
|
||||
bool clear /* = true */)
|
||||
VkPipeline Vulkan::GraphicsPipelineBuilder::Create(VkDevice device, VkPipelineCache pipeline_cache, bool clear,
|
||||
Error* error)
|
||||
{
|
||||
VkPipeline pipeline;
|
||||
VkResult res = vkCreateGraphicsPipelines(device, pipeline_cache, 1, &m_ci, nullptr, &pipeline);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkCreateGraphicsPipelines() failed: ");
|
||||
SetErrorObject(error, "vkCreateGraphicsPipelines() failed: ", res);
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include <array>
|
||||
#include <string_view>
|
||||
|
||||
class Error;
|
||||
|
||||
#if defined(_DEBUG) && !defined(CPU_ARCH_ARM32) && !defined(CPU_ARCH_X86)
|
||||
#define ENABLE_VULKAN_DEBUG_OBJECTS 1
|
||||
#endif
|
||||
|
@ -24,6 +26,7 @@ void AddPointerToChain(void* head, const void* ptr);
|
|||
|
||||
const char* VkResultToString(VkResult res);
|
||||
void LogVulkanResult(const char* func_name, VkResult res, std::string_view msg);
|
||||
void SetErrorObject(Error* errptr, std::string_view prefix, VkResult res);
|
||||
|
||||
class DescriptorSetLayoutBuilder
|
||||
{
|
||||
|
@ -89,7 +92,7 @@ public:
|
|||
|
||||
void Clear();
|
||||
|
||||
VkPipeline Create(VkDevice device, VkPipelineCache pipeline_cache = VK_NULL_HANDLE, bool clear = true);
|
||||
VkPipeline Create(VkDevice device, VkPipelineCache pipeline_cache, bool clear, Error* error);
|
||||
|
||||
void SetShaderStage(VkShaderStageFlagBits stage, VkShaderModule module, const char* entry_point);
|
||||
void SetVertexShader(VkShaderModule module) { SetShaderStage(VK_SHADER_STAGE_VERTEX_BIT, module, "main"); }
|
||||
|
|
|
@ -104,11 +104,12 @@ public:
|
|||
void ClearDepth(GPUTexture* t, float d) override;
|
||||
void InvalidateRenderTarget(GPUTexture* t) override;
|
||||
|
||||
std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShaderStage stage, std::span<const u8> data, Error* error) override;
|
||||
std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShaderStage stage, std::span<const u8> data,
|
||||
Error* error) override;
|
||||
std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShaderStage stage, GPUShaderLanguage language,
|
||||
std::string_view source, const char* entry_point,
|
||||
DynamicHeapArray<u8>* out_binary, Error* error) override;
|
||||
std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config) override;
|
||||
std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error) override;
|
||||
|
||||
void PushDebugGroup(const char* name) override;
|
||||
void PopDebugGroup() override;
|
||||
|
|
|
@ -88,7 +88,7 @@ void VulkanPipeline::SetDebugName(std::string_view name)
|
|||
Vulkan::SetObjectName(VulkanDevice::GetInstance().GetVulkanDevice(), m_pipeline, name);
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUPipeline> VulkanDevice::CreatePipeline(const GPUPipeline::GraphicsConfig& config)
|
||||
std::unique_ptr<GPUPipeline> VulkanDevice::CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error)
|
||||
{
|
||||
static constexpr std::array<std::pair<VkPrimitiveTopology, u32>, static_cast<u32>(GPUPipeline::Primitive::MaxCount)>
|
||||
primitives = {{
|
||||
|
@ -243,7 +243,7 @@ std::unique_ptr<GPUPipeline> VulkanDevice::CreatePipeline(const GPUPipeline::Gra
|
|||
gpb.SetRenderPass(render_pass, 0);
|
||||
}
|
||||
|
||||
const VkPipeline pipeline = gpb.Create(m_device, m_pipeline_cache, false);
|
||||
const VkPipeline pipeline = gpb.Create(m_device, m_pipeline_cache, false, error);
|
||||
if (!pipeline)
|
||||
return {};
|
||||
|
||||
|
|
Loading…
Reference in New Issue