GPUDevice: Use Error class for initialization errors
This commit is contained in:
parent
24cb489a32
commit
f66866ed73
|
@ -28,21 +28,26 @@ void Error::Clear()
|
|||
}
|
||||
|
||||
void Error::SetErrno(int err)
|
||||
{
|
||||
SetErrno(std::string_view(), err);
|
||||
}
|
||||
|
||||
void Error::SetErrno(std::string_view prefix, int err)
|
||||
{
|
||||
m_type = Type::Errno;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
char buf[128];
|
||||
if (strerror_s(buf, sizeof(buf), err) == 0)
|
||||
m_description = fmt::format("errno {}: {}", err, buf);
|
||||
m_description = fmt::format("{}errno {}: {}", prefix, err, buf);
|
||||
else
|
||||
m_description = fmt::format("errno {}: <Could not get error message>", err);
|
||||
m_description = fmt::format("{}errno {}: <Could not get error message>", prefix, err);
|
||||
#else
|
||||
const char* buf = std::strerror(err);
|
||||
if (buf)
|
||||
m_description = fmt::format("errno {}: {}", err, buf);
|
||||
m_description = fmt::format("{}errno {}: {}", prefix, err, buf);
|
||||
else
|
||||
m_description = fmt::format("errno {}: <Could not get error message>", err);
|
||||
m_description = fmt::format("{}errno {}: <Could not get error message>", prefix, err);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -52,20 +57,44 @@ void Error::SetErrno(Error* errptr, int err)
|
|||
errptr->SetErrno(err);
|
||||
}
|
||||
|
||||
void Error::SetErrno(Error* errptr, std::string_view prefix, int err)
|
||||
{
|
||||
if (errptr)
|
||||
errptr->SetErrno(prefix, err);
|
||||
}
|
||||
|
||||
void Error::SetString(std::string description)
|
||||
{
|
||||
m_type = Type::User;
|
||||
m_description = std::move(description);
|
||||
}
|
||||
|
||||
void Error::SetStringView(std::string_view description)
|
||||
{
|
||||
m_type = Type::User;
|
||||
m_description = std::string(description);
|
||||
}
|
||||
|
||||
void Error::SetString(Error* errptr, std::string description)
|
||||
{
|
||||
if (errptr)
|
||||
errptr->SetString(std::move(description));
|
||||
}
|
||||
|
||||
void Error::SetStringView(Error* errptr, std::string_view description)
|
||||
{
|
||||
if (errptr)
|
||||
errptr->SetStringView(std::move(description));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void Error::SetWin32(unsigned long err)
|
||||
{
|
||||
SetWin32(std::string_view(), err);
|
||||
}
|
||||
|
||||
void Error::SetWin32(std::string_view prefix, unsigned long err)
|
||||
{
|
||||
m_type = Type::Win32;
|
||||
|
||||
|
@ -75,11 +104,11 @@ void Error::SetWin32(unsigned long err)
|
|||
if (r > 0)
|
||||
{
|
||||
m_description =
|
||||
fmt::format("Win32 Error {}: {}", err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r)));
|
||||
fmt::format("{}Win32 Error {}: {}", prefix, err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r)));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_description = fmt::format("Win32 Error {}: <Could not resolve system error ID>", err);
|
||||
m_description = fmt::format("{}Win32 Error {}: <Could not resolve system error ID>", prefix, err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +118,18 @@ void Error::SetWin32(Error* errptr, unsigned long err)
|
|||
errptr->SetWin32(err);
|
||||
}
|
||||
|
||||
void Error::SetWin32(Error* errptr, std::string_view prefix, unsigned long err)
|
||||
{
|
||||
if (errptr)
|
||||
errptr->SetWin32(prefix, err);
|
||||
}
|
||||
|
||||
void Error::SetHResult(long err)
|
||||
{
|
||||
SetHResult(std::string_view(), err);
|
||||
}
|
||||
|
||||
void Error::SetHResult(std::string_view prefix, long err)
|
||||
{
|
||||
m_type = Type::HResult;
|
||||
|
||||
|
@ -99,11 +139,11 @@ void Error::SetHResult(long err)
|
|||
if (r > 0)
|
||||
{
|
||||
m_description =
|
||||
fmt::format("HRESULT {:08X}: {}", err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r)));
|
||||
fmt::format("{}HRESULT {:08X}: {}", prefix, err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r)));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_description = fmt::format("HRESULT {:08X}: <Could not resolve system error ID>", err);
|
||||
m_description = fmt::format("{}HRESULT {:08X}: <Could not resolve system error ID>", prefix, err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,15 +153,26 @@ void Error::SetHResult(Error* errptr, long err)
|
|||
errptr->SetHResult(err);
|
||||
}
|
||||
|
||||
void Error::SetHResult(Error* errptr, std::string_view prefix, long err)
|
||||
{
|
||||
if (errptr)
|
||||
errptr->SetHResult(prefix, err);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Error::SetSocket(int err)
|
||||
{
|
||||
SetSocket(std::string_view(), err);
|
||||
}
|
||||
|
||||
void Error::SetSocket(std::string_view prefix, int err)
|
||||
{
|
||||
// Socket errors are win32 errors on windows
|
||||
#ifdef _WIN32
|
||||
SetWin32(err);
|
||||
SetWin32(prefix, err);
|
||||
#else
|
||||
SetErrno(err);
|
||||
SetErrno(prefix, err);
|
||||
#endif
|
||||
m_type = Type::Socket;
|
||||
}
|
||||
|
@ -132,6 +183,12 @@ void Error::SetSocket(Error* errptr, int err)
|
|||
errptr->SetSocket(err);
|
||||
}
|
||||
|
||||
void Error::SetSocket(Error* errptr, std::string_view prefix, int err)
|
||||
{
|
||||
if (errptr)
|
||||
errptr->SetSocket(prefix, err);
|
||||
}
|
||||
|
||||
Error Error::CreateNone()
|
||||
{
|
||||
return Error();
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
// 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
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include "fmt/core.h"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
class Error
|
||||
{
|
||||
|
@ -26,26 +29,32 @@ public:
|
|||
};
|
||||
|
||||
ALWAYS_INLINE Type GetType() const { return m_type; }
|
||||
ALWAYS_INLINE bool IsValid() const { return (m_type != Type::None); }
|
||||
ALWAYS_INLINE const std::string& GetDescription() const { return m_description; }
|
||||
|
||||
void Clear();
|
||||
|
||||
/// Error that is set by system functions, such as open().
|
||||
void SetErrno(int err);
|
||||
void SetErrno(std::string_view prefix, int err);
|
||||
|
||||
/// Error that is set by socket functions, such as socket(). On Unix this is the same as errno.
|
||||
void SetSocket(int err);
|
||||
void SetSocket(std::string_view prefix, int err);
|
||||
|
||||
/// Set both description and message.
|
||||
void SetString(std::string description);
|
||||
void SetStringView(std::string_view description);
|
||||
|
||||
#ifdef _WIN32
|
||||
/// Error that is returned by some Win32 functions, such as RegOpenKeyEx. Also used by other APIs through
|
||||
/// GetLastError().
|
||||
void SetWin32(unsigned long err);
|
||||
void SetWin32(std::string_view prefix, unsigned long err);
|
||||
|
||||
/// Error that is returned by Win32 COM methods, e.g. S_OK.
|
||||
void SetHResult(long err);
|
||||
void SetHResult(std::string_view prefix, long err);
|
||||
#endif
|
||||
|
||||
static Error CreateNone();
|
||||
|
@ -59,10 +68,26 @@ public:
|
|||
|
||||
// helpers for setting
|
||||
static void SetErrno(Error* errptr, int err);
|
||||
static void SetErrno(Error* errptr, std::string_view prefix, int err);
|
||||
static void SetSocket(Error* errptr, int err);
|
||||
static void SetSocket(Error* errptr, std::string_view prefix, int err);
|
||||
static void SetString(Error* errptr, std::string description);
|
||||
static void SetStringView(Error* errptr, std::string_view description);
|
||||
|
||||
#ifdef _WIN32
|
||||
static void SetWin32(Error* errptr, unsigned long err);
|
||||
static void SetWin32(Error* errptr, std::string_view prefix, unsigned long err);
|
||||
static void SetHResult(Error* errptr, long err);
|
||||
static void SetHResult(Error* errptr, std::string_view prefix, long err);
|
||||
#endif
|
||||
|
||||
/// Sets a formatted message.
|
||||
template<typename... T>
|
||||
static void SetStringFmt(Error* errptr, fmt::format_string<T...> fmt, T&&... args)
|
||||
{
|
||||
if (errptr)
|
||||
Error::SetString(errptr, fmt::vformat(fmt, fmt::make_format_args(args...)));
|
||||
}
|
||||
|
||||
Error& operator=(const Error& e);
|
||||
Error& operator=(Error&& e);
|
||||
|
|
|
@ -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 "host.h"
|
||||
|
@ -14,6 +14,7 @@
|
|||
#include "util/imgui_manager.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/error.h"
|
||||
#include "common/layered_settings_interface.h"
|
||||
#include "common/log.h"
|
||||
#include "common/string_util.h"
|
||||
|
@ -259,29 +260,30 @@ bool Host::CreateGPUDevice(RenderAPI api)
|
|||
disabled_features |= GPUDevice::FEATURE_MASK_TEXTURE_COPY_TO_SELF;
|
||||
|
||||
// TODO: FSUI should always use vsync..
|
||||
Error error;
|
||||
const bool vsync = System::IsValid() ? System::ShouldUseVSync() : g_settings.video_sync_enabled;
|
||||
if (!g_gpu_device || !g_gpu_device->Create(g_settings.gpu_adapter,
|
||||
g_settings.gpu_disable_shader_cache ? std::string_view() :
|
||||
std::string_view(EmuFolders::Cache),
|
||||
SHADER_CACHE_VERSION, g_settings.gpu_use_debug_device, vsync,
|
||||
g_settings.gpu_threaded_presentation, exclusive_fullscreen_control,
|
||||
static_cast<GPUDevice::FeatureMask>(disabled_features)))
|
||||
static_cast<GPUDevice::FeatureMask>(disabled_features), &error))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create GPU device.");
|
||||
if (g_gpu_device)
|
||||
g_gpu_device->Destroy();
|
||||
g_gpu_device.reset();
|
||||
|
||||
Host::ReportErrorAsync("Error",
|
||||
fmt::format("Failed to create render device. This may be due to your GPU not supporting the "
|
||||
"chosen renderer ({}), or because your graphics drivers need to be updated.",
|
||||
GPUDevice::RenderAPIToString(api)));
|
||||
Host::ReportErrorAsync(
|
||||
"Error", fmt::format("Failed to create render device:\n\n{}\n\nThis may be due to your GPU not supporting the "
|
||||
"chosen renderer ({}), or because your graphics drivers need to be updated.",
|
||||
error.GetDescription(), GPUDevice::RenderAPIToString(api)));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ImGuiManager::Initialize(g_settings.display_osd_scale / 100.0f, g_settings.display_show_osd_messages))
|
||||
if (!ImGuiManager::Initialize(g_settings.display_osd_scale / 100.0f, g_settings.display_show_osd_messages, &error))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to initialize ImGuiManager.");
|
||||
Host::ReportErrorAsync("Error", fmt::format("Failed to initialize ImGuiManager: {}", error.GetDescription()));
|
||||
g_gpu_device->Destroy();
|
||||
g_gpu_device.reset();
|
||||
return false;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "common/align.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/bitutils.h"
|
||||
#include "common/error.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/path.h"
|
||||
|
@ -64,7 +65,8 @@ bool D3D11Device::HasSurface() const
|
|||
}
|
||||
|
||||
bool D3D11Device::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
||||
Error* error)
|
||||
{
|
||||
std::unique_lock lock(s_instance_mutex);
|
||||
|
||||
|
@ -72,7 +74,7 @@ bool D3D11Device::CreateDevice(const std::string_view& adapter, bool threaded_pr
|
|||
if (m_debug_device)
|
||||
create_flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
|
||||
m_dxgi_factory = D3DCommon::CreateFactory(m_debug_device);
|
||||
m_dxgi_factory = D3DCommon::CreateFactory(m_debug_device, error);
|
||||
if (!m_dxgi_factory)
|
||||
return false;
|
||||
|
||||
|
@ -90,12 +92,12 @@ bool D3D11Device::CreateDevice(const std::string_view& adapter, bool threaded_pr
|
|||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create D3D device: 0x%08X", hr);
|
||||
Error::SetHResult(error, "Failed to create D3D device: ", hr);
|
||||
return false;
|
||||
}
|
||||
else if (FAILED(hr = temp_device.As(&m_device)) || FAILED(hr = temp_context.As(&m_context)))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to get D3D11.1 device: 0x%08X", hr);
|
||||
Error::SetHResult(error, "Failed to get D3D11.1 device: ", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -135,10 +137,16 @@ bool D3D11Device::CreateDevice(const std::string_view& adapter, bool threaded_pr
|
|||
SetFeatures(disabled_features);
|
||||
|
||||
if (m_window_info.type != WindowInfo::Type::Surfaceless && !CreateSwapChain())
|
||||
{
|
||||
Error::SetStringView(error, "Failed to create swap chain");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateBuffers())
|
||||
{
|
||||
Error::SetStringView(error, "Failed to create buffers");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -663,7 +671,7 @@ GPUDevice::AdapterAndModeList D3D11Device::StaticGetAdapterAndModeList()
|
|||
}
|
||||
else
|
||||
{
|
||||
ComPtr<IDXGIFactory5> factory = D3DCommon::CreateFactory(false);
|
||||
ComPtr<IDXGIFactory5> factory = D3DCommon::CreateFactory(false, nullptr);
|
||||
if (factory)
|
||||
GetAdapterAndModeList(&ret, factory.Get());
|
||||
}
|
||||
|
|
|
@ -107,7 +107,8 @@ public:
|
|||
|
||||
protected:
|
||||
bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) override;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
||||
Error* error) override;
|
||||
void DestroyDevice() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -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_device.h"
|
||||
|
@ -13,6 +13,7 @@
|
|||
#include "common/align.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/bitutils.h"
|
||||
#include "common/error.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/path.h"
|
||||
|
@ -117,11 +118,11 @@ D3D12Device::ComPtr<ID3D12RootSignature> D3D12Device::CreateRootSignature(const
|
|||
}
|
||||
|
||||
bool D3D12Device::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features, Error* error)
|
||||
{
|
||||
std::unique_lock lock(s_instance_mutex);
|
||||
|
||||
m_dxgi_factory = D3DCommon::CreateFactory(m_debug_device);
|
||||
m_dxgi_factory = D3DCommon::CreateFactory(m_debug_device, error);
|
||||
if (!m_dxgi_factory)
|
||||
return false;
|
||||
|
||||
|
@ -150,7 +151,7 @@ bool D3D12Device::CreateDevice(const std::string_view& adapter, bool threaded_pr
|
|||
hr = D3D12CreateDevice(m_adapter.Get(), m_feature_level, IID_PPV_ARGS(&m_device));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create D3D12 device: %08X", hr);
|
||||
Error::SetHResult(error, "Failed to create D3D12 device: ", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -192,7 +193,7 @@ bool D3D12Device::CreateDevice(const std::string_view& adapter, bool threaded_pr
|
|||
hr = m_device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&m_command_queue));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create command queue: %08X", hr);
|
||||
Error::SetHResult(error, "Failed to create command queue: ", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -206,34 +207,43 @@ bool D3D12Device::CreateDevice(const std::string_view& adapter, bool threaded_pr
|
|||
hr = D3D12MA::CreateAllocator(&allocatorDesc, m_allocator.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("D3D12MA::CreateAllocator() failed with HRESULT %08X", hr);
|
||||
Error::SetHResult(error, "D3D12MA::CreateAllocator() failed: ", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = m_device->CreateFence(m_completed_fence_value, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create fence: %08X", hr);
|
||||
Error::SetHResult(error, "Failed to create fence: ", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_fence_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
if (m_fence_event == NULL)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create fence event: %08X", GetLastError());
|
||||
Error::SetWin32(error, "Failed to create fence event: ", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SetFeatures(disabled_features);
|
||||
|
||||
if (!CreateCommandLists() || !CreateDescriptorHeaps())
|
||||
{
|
||||
Error::SetStringView(error, "Failed to create command lists/descriptor heaps.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_window_info.IsSurfaceless() && !CreateSwapChain())
|
||||
{
|
||||
Error::SetStringView(error, "Failed to create swap chain.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateRootSignatures() || !CreateBuffers())
|
||||
{
|
||||
Error::SetStringView(error, "Failed to create root signature/buffers.");
|
||||
return false;
|
||||
}
|
||||
|
||||
CreateTimestampQuery();
|
||||
return true;
|
||||
|
@ -741,7 +751,7 @@ GPUDevice::AdapterAndModeList D3D12Device::StaticGetAdapterAndModeList()
|
|||
}
|
||||
else
|
||||
{
|
||||
ComPtr<IDXGIFactory5> factory = D3DCommon::CreateFactory(false);
|
||||
ComPtr<IDXGIFactory5> factory = D3DCommon::CreateFactory(false, nullptr);
|
||||
if (factory)
|
||||
GetAdapterAndModeList(&ret, factory.Get());
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -175,7 +175,8 @@ public:
|
|||
|
||||
protected:
|
||||
bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) override;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
||||
Error* error) override;
|
||||
void DestroyDevice() override;
|
||||
|
||||
bool ReadPipelineCache(const std::string& filename) override;
|
||||
|
|
|
@ -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 "d3d_common.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/error.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/rectangle.h"
|
||||
|
@ -54,7 +55,7 @@ const char* D3DCommon::GetFeatureLevelShaderModelString(D3D_FEATURE_LEVEL featur
|
|||
return "unk";
|
||||
}
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGIFactory5> D3DCommon::CreateFactory(bool debug)
|
||||
Microsoft::WRL::ComPtr<IDXGIFactory5> D3DCommon::CreateFactory(bool debug, Error* error)
|
||||
{
|
||||
UINT flags = 0;
|
||||
if (debug)
|
||||
|
@ -63,7 +64,7 @@ Microsoft::WRL::ComPtr<IDXGIFactory5> D3DCommon::CreateFactory(bool debug)
|
|||
Microsoft::WRL::ComPtr<IDXGIFactory5> factory;
|
||||
const HRESULT hr = CreateDXGIFactory2(flags, IID_PPV_ARGS(factory.GetAddressOf()));
|
||||
if (FAILED(hr))
|
||||
Log_ErrorPrintf("Failed to create DXGI factory: %08X", hr);
|
||||
Error::SetHResult(error, "Failed to create DXGI factory: ", hr);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -16,6 +16,8 @@
|
|||
#include <vector>
|
||||
#include <wrl/client.h>
|
||||
|
||||
class Error;
|
||||
|
||||
struct IDXGIFactory5;
|
||||
struct IDXGIAdapter1;
|
||||
struct IDXGIOutput;
|
||||
|
@ -27,7 +29,7 @@ const char* GetFeatureLevelString(D3D_FEATURE_LEVEL feature_level);
|
|||
const char* GetFeatureLevelShaderModelString(D3D_FEATURE_LEVEL feature_level);
|
||||
|
||||
// create a dxgi factory
|
||||
Microsoft::WRL::ComPtr<IDXGIFactory5> CreateFactory(bool debug);
|
||||
Microsoft::WRL::ComPtr<IDXGIFactory5> CreateFactory(bool debug, Error* error);
|
||||
|
||||
// returns a list of all adapter names
|
||||
std::vector<std::string> GetAdapterNames(IDXGIFactory5* factory);
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 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 "context.h"
|
||||
#include "../opengl_loader.h"
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/log.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
@ -65,7 +66,7 @@ static void DisableBrokenExtensions(const char* gl_vendor, const char* gl_render
|
|||
gl_major_version >= 3 && gl_minor_version >= 2 && major_version > 0))
|
||||
{
|
||||
// r32p0 and beyond seem okay.
|
||||
//Log_VerbosePrintf("Keeping copy_image for driver version '%s'", gl_version);
|
||||
// Log_VerbosePrintf("Keeping copy_image for driver version '%s'", gl_version);
|
||||
|
||||
// Framebuffer blits still end up faster.
|
||||
Log_VerbosePrintf("Newer Mali driver detected, disabling GL_{EXT,OES}_copy_image.");
|
||||
|
@ -117,45 +118,60 @@ std::vector<Context::FullscreenModeInfo> Context::EnumerateFullscreenModes()
|
|||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try)
|
||||
std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, Error* error)
|
||||
{
|
||||
static constexpr std::array<Version, 14> vlist = {{{Profile::Core, 4, 6},
|
||||
{Profile::Core, 4, 5},
|
||||
{Profile::Core, 4, 4},
|
||||
{Profile::Core, 4, 3},
|
||||
{Profile::Core, 4, 2},
|
||||
{Profile::Core, 4, 1},
|
||||
{Profile::Core, 4, 0},
|
||||
{Profile::Core, 3, 3},
|
||||
{Profile::Core, 3, 2},
|
||||
{Profile::Core, 3, 1},
|
||||
{Profile::Core, 3, 0},
|
||||
{Profile::ES, 3, 2},
|
||||
{Profile::ES, 3, 1},
|
||||
{Profile::ES, 3, 0}}};
|
||||
|
||||
std::span<const Version> versions_to_try = vlist;
|
||||
if (ShouldPreferESContext())
|
||||
{
|
||||
// move ES versions to the front
|
||||
Version* new_versions_to_try = static_cast<Version*>(alloca(sizeof(Version) * num_versions_to_try));
|
||||
Version* new_versions_to_try = static_cast<Version*>(alloca(sizeof(Version) * versions_to_try.size()));
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i < num_versions_to_try; i++)
|
||||
for (const Version& cv : versions_to_try)
|
||||
{
|
||||
if (versions_to_try[i].profile == Profile::ES)
|
||||
new_versions_to_try[count++] = versions_to_try[i];
|
||||
if (cv.profile == Profile::ES)
|
||||
new_versions_to_try[count++] = cv;
|
||||
}
|
||||
for (size_t i = 0; i < num_versions_to_try; i++)
|
||||
for (const Version& cv : versions_to_try)
|
||||
{
|
||||
if (versions_to_try[i].profile != Profile::ES)
|
||||
new_versions_to_try[count++] = versions_to_try[i];
|
||||
if (cv.profile != Profile::ES)
|
||||
new_versions_to_try[count++] = cv;
|
||||
}
|
||||
versions_to_try = new_versions_to_try;
|
||||
versions_to_try = std::span<const Version>(new_versions_to_try, versions_to_try.size());
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> context;
|
||||
#if defined(_WIN32) && !defined(_M_ARM64)
|
||||
context = ContextWGL::Create(wi, versions_to_try, num_versions_to_try);
|
||||
context = ContextWGL::Create(wi, versions_to_try, error);
|
||||
#elif defined(__APPLE__)
|
||||
context = ContextAGL::Create(wi, versions_to_try, num_versions_to_try);
|
||||
context = ContextAGL::Create(wi, versions_to_try);
|
||||
#elif defined(__ANDROID__)
|
||||
context = ContextEGLAndroid::Create(wi, versions_to_try, num_versions_to_try);
|
||||
context = ContextEGLAndroid::Create(wi, versions_to_try, error);
|
||||
#else
|
||||
#if defined(ENABLE_X11)
|
||||
if (wi.type == WindowInfo::Type::X11)
|
||||
context = ContextEGLX11::Create(wi, versions_to_try, num_versions_to_try);
|
||||
context = ContextEGLX11::Create(wi, versions_to_try, error);
|
||||
#endif
|
||||
#if defined(ENABLE_WAYLAND)
|
||||
if (wi.type == WindowInfo::Type::Wayland)
|
||||
context = ContextEGLWayland::Create(wi, versions_to_try, num_versions_to_try);
|
||||
context = ContextEGLWayland::Create(wi, versions_to_try, error);
|
||||
#endif
|
||||
if (wi.type == WindowInfo::Type::Surfaceless)
|
||||
context = ContextEGL::Create(wi, versions_to_try, num_versions_to_try);
|
||||
context = ContextEGL::Create(wi, versions_to_try, error);
|
||||
#endif
|
||||
|
||||
if (!context)
|
||||
|
@ -172,7 +188,7 @@ std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version
|
|||
{
|
||||
if (!gladLoadGLLoader([](const char* name) { return context_being_created->GetProcAddress(name); }))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to load GL functions for GLAD");
|
||||
Error::SetStringView(error, "Failed to load GL functions for GLAD");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +196,7 @@ std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version
|
|||
{
|
||||
if (!gladLoadGLES2Loader([](const char* name) { return context_being_created->GetProcAddress(name); }))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to load GLES functions for GLAD");
|
||||
Error::SetStringView(error, "Failed to load GLES functions for GLAD");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -199,65 +215,4 @@ std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version
|
|||
return context;
|
||||
}
|
||||
|
||||
const std::array<Context::Version, 11>& Context::GetAllDesktopVersionsList()
|
||||
{
|
||||
static constexpr std::array<Version, 11> vlist = {{{Profile::Core, 4, 6},
|
||||
{Profile::Core, 4, 5},
|
||||
{Profile::Core, 4, 4},
|
||||
{Profile::Core, 4, 3},
|
||||
{Profile::Core, 4, 2},
|
||||
{Profile::Core, 4, 1},
|
||||
{Profile::Core, 4, 0},
|
||||
{Profile::Core, 3, 3},
|
||||
{Profile::Core, 3, 2},
|
||||
{Profile::Core, 3, 1},
|
||||
{Profile::Core, 3, 0}}};
|
||||
return vlist;
|
||||
}
|
||||
|
||||
const std::array<Context::Version, 12>& Context::GetAllDesktopVersionsListWithFallback()
|
||||
{
|
||||
static constexpr std::array<Version, 12> vlist = {{{Profile::Core, 4, 6},
|
||||
{Profile::Core, 4, 5},
|
||||
{Profile::Core, 4, 4},
|
||||
{Profile::Core, 4, 3},
|
||||
{Profile::Core, 4, 2},
|
||||
{Profile::Core, 4, 1},
|
||||
{Profile::Core, 4, 0},
|
||||
{Profile::Core, 3, 3},
|
||||
{Profile::Core, 3, 2},
|
||||
{Profile::Core, 3, 1},
|
||||
{Profile::Core, 3, 0},
|
||||
{Profile::NoProfile, 0, 0}}};
|
||||
return vlist;
|
||||
}
|
||||
|
||||
const std::array<Context::Version, 4>& Context::GetAllESVersionsList()
|
||||
{
|
||||
static constexpr std::array<Version, 4> vlist = {
|
||||
{{Profile::ES, 3, 2}, {Profile::ES, 3, 1}, {Profile::ES, 3, 0}, {Profile::ES, 2, 0}}};
|
||||
return vlist;
|
||||
}
|
||||
|
||||
const std::array<Context::Version, 16>& Context::GetAllVersionsList()
|
||||
{
|
||||
static constexpr std::array<Version, 16> vlist = {{{Profile::Core, 4, 6},
|
||||
{Profile::Core, 4, 5},
|
||||
{Profile::Core, 4, 4},
|
||||
{Profile::Core, 4, 3},
|
||||
{Profile::Core, 4, 2},
|
||||
{Profile::Core, 4, 1},
|
||||
{Profile::Core, 4, 0},
|
||||
{Profile::Core, 3, 3},
|
||||
{Profile::Core, 3, 2},
|
||||
{Profile::Core, 3, 1},
|
||||
{Profile::Core, 3, 0},
|
||||
{Profile::ES, 3, 2},
|
||||
{Profile::ES, 3, 1},
|
||||
{Profile::ES, 3, 0},
|
||||
{Profile::ES, 2, 0},
|
||||
{Profile::NoProfile, 0, 0}}};
|
||||
return vlist;
|
||||
}
|
||||
|
||||
} // namespace GL
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 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
|
||||
|
@ -7,10 +7,12 @@
|
|||
|
||||
#include "common/types.h"
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
class Error;
|
||||
|
||||
namespace GL {
|
||||
class Context
|
||||
{
|
||||
|
@ -57,26 +59,9 @@ public:
|
|||
|
||||
virtual std::vector<FullscreenModeInfo> EnumerateFullscreenModes();
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try);
|
||||
|
||||
template<size_t N>
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, const std::array<Version, N>& versions_to_try)
|
||||
{
|
||||
return Create(wi, versions_to_try.data(), versions_to_try.size());
|
||||
}
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi) { return Create(wi, GetAllVersionsList()); }
|
||||
|
||||
static const std::array<Version, 11>& GetAllDesktopVersionsList();
|
||||
static const std::array<Version, 12>& GetAllDesktopVersionsListWithFallback();
|
||||
static const std::array<Version, 4>& GetAllESVersionsList();
|
||||
static const std::array<Version, 16>& GetAllVersionsList();
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, Error* error);
|
||||
|
||||
protected:
|
||||
#ifdef _WIN32
|
||||
#endif
|
||||
|
||||
WindowInfo m_wi;
|
||||
Version m_version = {};
|
||||
};
|
||||
|
|
|
@ -22,8 +22,7 @@ public:
|
|||
ContextAGL(const WindowInfo& wi);
|
||||
~ContextAGL() override;
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try);
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, std::span<const Version> versions_to_try);
|
||||
|
||||
void* GetProcAddress(const char* name) override;
|
||||
bool ChangeSurface(const WindowInfo& new_wi) override;
|
||||
|
@ -38,7 +37,7 @@ public:
|
|||
private:
|
||||
ALWAYS_INLINE NSView* GetView() const { return static_cast<NSView*>((__bridge NSView*)m_wi.window_handle); }
|
||||
|
||||
bool Initialize(const Version* versions_to_try, size_t num_versions_to_try);
|
||||
bool Initialize(std::span<const Version> versions_to_try);
|
||||
bool CreateContext(NSOpenGLContext* share_context, int profile, bool make_current);
|
||||
void BindContextToView();
|
||||
|
||||
|
|
|
@ -30,21 +30,19 @@ ContextAGL::~ContextAGL()
|
|||
dlclose(m_opengl_module_handle);
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextAGL::Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try)
|
||||
std::unique_ptr<Context> ContextAGL::Create(const WindowInfo& wi, std::span<const Version> versions_to_try)
|
||||
{
|
||||
std::unique_ptr<ContextAGL> context = std::make_unique<ContextAGL>(wi);
|
||||
if (!context->Initialize(versions_to_try, num_versions_to_try))
|
||||
if (!context->Initialize(versions_to_try))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
bool ContextAGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try)
|
||||
bool ContextAGL::Initialize(const std::span<const Version> versions_to_try)
|
||||
{
|
||||
for (size_t i = 0; i < num_versions_to_try; i++)
|
||||
for (const Version& cv : versions_to_try)
|
||||
{
|
||||
const Version& cv = versions_to_try[i];
|
||||
if (cv.profile == Profile::NoProfile && CreateContext(nullptr, NSOpenGLProfileVersionLegacy, true))
|
||||
{
|
||||
// we already have the dummy context, so just use that
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
// 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 "context_egl.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/log.h"
|
||||
#include "common/error.h"
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
@ -22,21 +23,21 @@ ContextEGL::~ContextEGL()
|
|||
DestroyContext();
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextEGL::Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try)
|
||||
std::unique_ptr<Context> ContextEGL::Create(const WindowInfo& wi, std::span<const Version> versions_to_try, Error* error)
|
||||
{
|
||||
std::unique_ptr<ContextEGL> context = std::make_unique<ContextEGL>(wi);
|
||||
if (!context->Initialize(versions_to_try, num_versions_to_try))
|
||||
if (!context->Initialize(versions_to_try, error))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
bool ContextEGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try)
|
||||
bool ContextEGL::Initialize(std::span<const Version> versions_to_try, Error* error)
|
||||
{
|
||||
if (!gladLoadEGL())
|
||||
{
|
||||
Log_ErrorPrintf("Loading GLAD EGL functions failed");
|
||||
Log_ErrorPrint("Loading GLAD EGL functions failed");
|
||||
Error::SetStringView(error, "Loading GLAD EGL functions failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -46,7 +47,9 @@ bool ContextEGL::Initialize(const Version* versions_to_try, size_t num_versions_
|
|||
int egl_major, egl_minor;
|
||||
if (!eglInitialize(m_display, &egl_major, &egl_minor))
|
||||
{
|
||||
Log_ErrorPrintf("eglInitialize() failed: %d", eglGetError());
|
||||
const int gerror = static_cast<int>(eglGetError());
|
||||
Log_ErrorFmt("eglInitialize() failed: {} (0x{:X})", gerror, gerror);
|
||||
Error::SetStringFmt(error, "eglInitialize() failed: {} (0x{:X})", gerror, gerror);
|
||||
return false;
|
||||
}
|
||||
Log_InfoPrintf("EGL Version: %d.%d", egl_major, egl_minor);
|
||||
|
@ -60,12 +63,13 @@ bool ContextEGL::Initialize(const Version* versions_to_try, size_t num_versions_
|
|||
if (!m_supports_surfaceless)
|
||||
Log_WarningPrint("EGL implementation does not support surfaceless contexts, emulating with pbuffers");
|
||||
|
||||
for (size_t i = 0; i < num_versions_to_try; i++)
|
||||
for (const Version& cv : versions_to_try)
|
||||
{
|
||||
if (CreateContextAndSurface(versions_to_try[i], nullptr, true))
|
||||
if (CreateContextAndSurface(cv, nullptr, true))
|
||||
return true;
|
||||
}
|
||||
|
||||
Error::SetStringView(error, "Failed to create any context versions");
|
||||
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
|
||||
|
@ -15,8 +15,7 @@ public:
|
|||
ContextEGL(const WindowInfo& wi);
|
||||
~ContextEGL() override;
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try);
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, std::span<const Version> versions_to_try, Error* error);
|
||||
|
||||
void* GetProcAddress(const char* name) override;
|
||||
virtual bool ChangeSurface(const WindowInfo& new_wi) override;
|
||||
|
@ -32,7 +31,7 @@ protected:
|
|||
virtual bool SetDisplay();
|
||||
virtual EGLNativeWindowType GetNativeWindow(EGLConfig config);
|
||||
|
||||
bool Initialize(const Version* versions_to_try, size_t num_versions_to_try);
|
||||
bool Initialize(std::span<const Version> versions_to_try, Error* error);
|
||||
bool CreateDisplay();
|
||||
bool CreateContext(const Version& version, EGLContext share_context);
|
||||
bool CreateContextAndSurface(const Version& version, EGLContext share_context, bool make_current);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 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 "context_egl_wayland.h"
|
||||
|
@ -12,7 +12,9 @@ Log_SetChannel(ContextEGL);
|
|||
namespace GL {
|
||||
static const char* WAYLAND_EGL_MODNAME = "libwayland-egl.so.1";
|
||||
|
||||
ContextEGLWayland::ContextEGLWayland(const WindowInfo& wi) : ContextEGL(wi) {}
|
||||
ContextEGLWayland::ContextEGLWayland(const WindowInfo& wi) : ContextEGL(wi)
|
||||
{
|
||||
}
|
||||
ContextEGLWayland::~ContextEGLWayland()
|
||||
{
|
||||
if (m_wl_window)
|
||||
|
@ -21,11 +23,11 @@ ContextEGLWayland::~ContextEGLWayland()
|
|||
dlclose(m_wl_module);
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextEGLWayland::Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try)
|
||||
std::unique_ptr<Context> ContextEGLWayland::Create(const WindowInfo& wi, std::span<const Version> versions_to_try,
|
||||
Error* error)
|
||||
{
|
||||
std::unique_ptr<ContextEGLWayland> context = std::make_unique<ContextEGLWayland>(wi);
|
||||
if (!context->LoadModule() || !context->Initialize(versions_to_try, num_versions_to_try))
|
||||
if (!context->LoadModule() || !context->Initialize(versions_to_try, error))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 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
|
||||
|
@ -13,8 +13,7 @@ public:
|
|||
ContextEGLWayland(const WindowInfo& wi);
|
||||
~ContextEGLWayland() override;
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try);
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, std::span<const Version> versions_to_try, Error* error);
|
||||
|
||||
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
|
||||
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 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 "context_egl_x11.h"
|
||||
|
||||
namespace GL {
|
||||
ContextEGLX11::ContextEGLX11(const WindowInfo& wi) : ContextEGL(wi) {}
|
||||
ContextEGLX11::ContextEGLX11(const WindowInfo& wi) : ContextEGL(wi)
|
||||
{
|
||||
}
|
||||
ContextEGLX11::~ContextEGLX11() = default;
|
||||
|
||||
std::unique_ptr<Context> ContextEGLX11::Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try)
|
||||
std::unique_ptr<Context> ContextEGLX11::Create(const WindowInfo& wi, std::span<const Version> versions_to_try,
|
||||
Error* error)
|
||||
{
|
||||
std::unique_ptr<ContextEGLX11> context = std::make_unique<ContextEGLX11>(wi);
|
||||
if (!context->Initialize(versions_to_try, num_versions_to_try))
|
||||
if (!context->Initialize(versions_to_try, error))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 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
|
||||
|
@ -12,8 +12,7 @@ public:
|
|||
ContextEGLX11(const WindowInfo& wi);
|
||||
~ContextEGLX11() override;
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try);
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, std::span<const Version> versions_to_try, Error* error);
|
||||
|
||||
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
|
||||
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
// 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 "context_wgl.h"
|
||||
#include "../opengl_loader.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/error.h"
|
||||
#include "common/log.h"
|
||||
#include "common/scoped_guard.h"
|
||||
|
||||
|
@ -51,36 +52,44 @@ ContextWGL::~ContextWGL()
|
|||
ReleaseDC();
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextWGL::Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try)
|
||||
std::unique_ptr<Context> ContextWGL::Create(const WindowInfo& wi, std::span<const Version> versions_to_try,
|
||||
Error* error)
|
||||
{
|
||||
std::unique_ptr<ContextWGL> context = std::make_unique<ContextWGL>(wi);
|
||||
if (!context->Initialize(versions_to_try, num_versions_to_try))
|
||||
if (!context->Initialize(versions_to_try, error))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
bool ContextWGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try)
|
||||
bool ContextWGL::Initialize(std::span<const Version> versions_to_try, Error* error)
|
||||
{
|
||||
if (m_wi.type == WindowInfo::Type::Win32)
|
||||
{
|
||||
if (!InitializeDC())
|
||||
{
|
||||
Error::SetStringView(error, "Failed to create DC.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CreatePBuffer())
|
||||
{
|
||||
Error::SetStringView(error, "Failed to create PBuffer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Everything including core/ES requires a dummy profile to load the WGL extensions.
|
||||
if (!CreateAnyContext(nullptr, true))
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < num_versions_to_try; i++)
|
||||
{
|
||||
const Version& cv = versions_to_try[i];
|
||||
Error::SetStringView(error, "Failed to create dummy context.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const Version& cv : versions_to_try)
|
||||
{
|
||||
if (cv.profile == Profile::NoProfile)
|
||||
{
|
||||
// we already have the dummy context, so just use that
|
||||
|
@ -94,6 +103,7 @@ bool ContextWGL::Initialize(const Version* versions_to_try, size_t num_versions_
|
|||
}
|
||||
}
|
||||
|
||||
Error::SetStringView(error, "Failed to create any contexts.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@ public:
|
|||
ContextWGL(const WindowInfo& wi);
|
||||
~ContextWGL() override;
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
|
||||
size_t num_versions_to_try);
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, std::span<const Version> versions_to_try, Error* error);
|
||||
|
||||
void* GetProcAddress(const char* name) override;
|
||||
bool ChangeSurface(const WindowInfo& new_wi) override;
|
||||
|
@ -38,7 +37,7 @@ private:
|
|||
|
||||
HDC GetDCAndSetPixelFormat(HWND hwnd);
|
||||
|
||||
bool Initialize(const Version* versions_to_try, size_t num_versions_to_try);
|
||||
bool Initialize(std::span<const Version> versions_to_try, Error* error);
|
||||
bool InitializeDC();
|
||||
void ReleaseDC();
|
||||
bool CreatePBuffer();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "shadergen.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/error.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/path.h"
|
||||
|
@ -258,20 +259,21 @@ bool GPUDevice::IsSameRenderAPI(RenderAPI lhs, RenderAPI rhs)
|
|||
|
||||
bool GPUDevice::Create(const std::string_view& adapter, const std::string_view& shader_cache_path,
|
||||
u32 shader_cache_version, bool debug_device, bool vsync, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features, Error* error)
|
||||
{
|
||||
m_vsync_enabled = vsync;
|
||||
m_debug_device = debug_device;
|
||||
|
||||
if (!AcquireWindow(true))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to acquire window from host.");
|
||||
Error::SetStringView(error, "Failed to acquire window from host.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateDevice(adapter, threaded_presentation, exclusive_fullscreen_control, disabled_features))
|
||||
if (!CreateDevice(adapter, threaded_presentation, exclusive_fullscreen_control, disabled_features, error))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create device.");
|
||||
if (error && !error->IsValid())
|
||||
error->SetStringView("Failed to create device.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -281,7 +283,7 @@ bool GPUDevice::Create(const std::string_view& adapter, const std::string_view&
|
|||
|
||||
if (!CreateResources())
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create base resources.");
|
||||
Error::SetStringView(error, "Failed to create base resources.");
|
||||
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
|
||||
|
@ -23,6 +23,8 @@
|
|||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
class Error;
|
||||
|
||||
enum class RenderAPI : u32
|
||||
{
|
||||
None,
|
||||
|
@ -537,7 +539,7 @@ public:
|
|||
|
||||
bool Create(const std::string_view& adapter, const std::string_view& shader_cache_path, u32 shader_cache_version,
|
||||
bool debug_device, bool vsync, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features);
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features, Error* error);
|
||||
void Destroy();
|
||||
|
||||
virtual bool HasSurface() const = 0;
|
||||
|
@ -652,7 +654,8 @@ public:
|
|||
|
||||
protected:
|
||||
virtual bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) = 0;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
||||
Error* error) = 0;
|
||||
virtual void DestroyDevice() = 0;
|
||||
|
||||
std::string GetShaderCacheBaseName(const std::string_view& type) const;
|
||||
|
|
|
@ -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 "imgui_manager.h"
|
||||
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "common/assert.h"
|
||||
#include "common/easing.h"
|
||||
#include "common/error.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/image.h"
|
||||
#include "common/log.h"
|
||||
|
@ -154,11 +155,11 @@ void ImGuiManager::SetShowOSDMessages(bool enable)
|
|||
Host::ClearOSDMessages();
|
||||
}
|
||||
|
||||
bool ImGuiManager::Initialize(float global_scale, bool show_osd_messages)
|
||||
bool ImGuiManager::Initialize(float global_scale, bool show_osd_messages, Error* error)
|
||||
{
|
||||
if (!LoadFontData())
|
||||
{
|
||||
Panic("Failed to load font data");
|
||||
Error::SetString(error, "Failed to load font data");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -191,7 +192,7 @@ bool ImGuiManager::Initialize(float global_scale, bool show_osd_messages)
|
|||
|
||||
if (!AddImGuiFonts(false) || !g_gpu_device->UpdateImGuiFontTexture())
|
||||
{
|
||||
Panic("Failed to create ImGui font text");
|
||||
Error::SetString(error, "Failed to create ImGui font text");
|
||||
ImGui::DestroyContext();
|
||||
return false;
|
||||
}
|
||||
|
@ -554,8 +555,25 @@ ImFont* ImGuiManager::AddFixedFont(float size)
|
|||
|
||||
bool ImGuiManager::AddIconFonts(float size)
|
||||
{
|
||||
static constexpr ImWchar range_fa[] = { 0xf002,0xf002,0xf005,0xf005,0xf007,0xf007,0xf00c,0xf00e,0xf011,0xf011,0xf013,0xf013,0xf017,0xf017,0xf019,0xf019,0xf01c,0xf01c,0xf021,0xf021,0xf023,0xf023,0xf025,0xf025,0xf027,0xf028,0xf02e,0xf02e,0xf030,0xf030,0xf03a,0xf03a,0xf03d,0xf03d,0xf049,0xf04c,0xf050,0xf050,0xf059,0xf059,0xf05e,0xf05e,0xf062,0xf063,0xf065,0xf065,0xf067,0xf067,0xf071,0xf071,0xf075,0xf075,0xf077,0xf078,0xf07b,0xf07c,0xf084,0xf085,0xf091,0xf091,0xf0a0,0xf0a0,0xf0ac,0xf0ad,0xf0c5,0xf0c5,0xf0c7,0xf0c8,0xf0cb,0xf0cb,0xf0d0,0xf0d0,0xf0dc,0xf0dc,0xf0e2,0xf0e2,0xf0eb,0xf0eb,0xf0f1,0xf0f1,0xf0f3,0xf0f3,0xf0fe,0xf0fe,0xf110,0xf110,0xf119,0xf119,0xf11b,0xf11c,0xf140,0xf140,0xf144,0xf144,0xf14a,0xf14a,0xf15b,0xf15b,0xf15d,0xf15d,0xf188,0xf188,0xf191,0xf192,0xf1ab,0xf1ab,0xf1dd,0xf1de,0xf1e6,0xf1e6,0xf1eb,0xf1eb,0xf1f8,0xf1f8,0xf1fc,0xf1fc,0xf242,0xf242,0xf245,0xf245,0xf26c,0xf26c,0xf279,0xf279,0xf2d0,0xf2d0,0xf2db,0xf2db,0xf2f2,0xf2f2,0xf2f5,0xf2f5,0xf3c1,0xf3c1,0xf410,0xf410,0xf466,0xf466,0xf500,0xf500,0xf51f,0xf51f,0xf545,0xf545,0xf547,0xf548,0xf552,0xf552,0xf57a,0xf57a,0xf5a2,0xf5a2,0xf5aa,0xf5aa,0xf5e7,0xf5e7,0xf65d,0xf65e,0xf6a9,0xf6a9,0xf7c2,0xf7c2,0xf807,0xf807,0xf815,0xf815,0xf818,0xf818,0xf84c,0xf84c,0xf8cc,0xf8cc,0x0,0x0 };
|
||||
static constexpr ImWchar range_pf[] = { 0x2196,0x2199,0x219e,0x21a1,0x21b0,0x21b3,0x21ba,0x21c3,0x21c7,0x21ca,0x21d0,0x21d4,0x21dc,0x21dd,0x21e0,0x21e3,0x21ed,0x21ee,0x21f7,0x21f8,0x21fa,0x21fb,0x227a,0x227d,0x23b2,0x23b4,0x23f4,0x23f7,0x2427,0x243a,0x243c,0x243c,0x243e,0x243e,0x2460,0x246b,0x24f5,0x24fd,0x24ff,0x24ff,0x278a,0x278e,0x27fc,0x27fc,0xe001,0xe001,0xff21,0xff3a,0x0,0x0 };
|
||||
static constexpr ImWchar range_fa[] = {
|
||||
0xf002, 0xf002, 0xf005, 0xf005, 0xf007, 0xf007, 0xf00c, 0xf00e, 0xf011, 0xf011, 0xf013, 0xf013, 0xf017, 0xf017,
|
||||
0xf019, 0xf019, 0xf01c, 0xf01c, 0xf021, 0xf021, 0xf023, 0xf023, 0xf025, 0xf025, 0xf027, 0xf028, 0xf02e, 0xf02e,
|
||||
0xf030, 0xf030, 0xf03a, 0xf03a, 0xf03d, 0xf03d, 0xf049, 0xf04c, 0xf050, 0xf050, 0xf059, 0xf059, 0xf05e, 0xf05e,
|
||||
0xf062, 0xf063, 0xf065, 0xf065, 0xf067, 0xf067, 0xf071, 0xf071, 0xf075, 0xf075, 0xf077, 0xf078, 0xf07b, 0xf07c,
|
||||
0xf084, 0xf085, 0xf091, 0xf091, 0xf0a0, 0xf0a0, 0xf0ac, 0xf0ad, 0xf0c5, 0xf0c5, 0xf0c7, 0xf0c8, 0xf0cb, 0xf0cb,
|
||||
0xf0d0, 0xf0d0, 0xf0dc, 0xf0dc, 0xf0e2, 0xf0e2, 0xf0eb, 0xf0eb, 0xf0f1, 0xf0f1, 0xf0f3, 0xf0f3, 0xf0fe, 0xf0fe,
|
||||
0xf110, 0xf110, 0xf119, 0xf119, 0xf11b, 0xf11c, 0xf140, 0xf140, 0xf144, 0xf144, 0xf14a, 0xf14a, 0xf15b, 0xf15b,
|
||||
0xf15d, 0xf15d, 0xf188, 0xf188, 0xf191, 0xf192, 0xf1ab, 0xf1ab, 0xf1dd, 0xf1de, 0xf1e6, 0xf1e6, 0xf1eb, 0xf1eb,
|
||||
0xf1f8, 0xf1f8, 0xf1fc, 0xf1fc, 0xf242, 0xf242, 0xf245, 0xf245, 0xf26c, 0xf26c, 0xf279, 0xf279, 0xf2d0, 0xf2d0,
|
||||
0xf2db, 0xf2db, 0xf2f2, 0xf2f2, 0xf2f5, 0xf2f5, 0xf3c1, 0xf3c1, 0xf410, 0xf410, 0xf466, 0xf466, 0xf500, 0xf500,
|
||||
0xf51f, 0xf51f, 0xf545, 0xf545, 0xf547, 0xf548, 0xf552, 0xf552, 0xf57a, 0xf57a, 0xf5a2, 0xf5a2, 0xf5aa, 0xf5aa,
|
||||
0xf5e7, 0xf5e7, 0xf65d, 0xf65e, 0xf6a9, 0xf6a9, 0xf7c2, 0xf7c2, 0xf807, 0xf807, 0xf815, 0xf815, 0xf818, 0xf818,
|
||||
0xf84c, 0xf84c, 0xf8cc, 0xf8cc, 0x0, 0x0};
|
||||
static constexpr ImWchar range_pf[] = {0x2196, 0x2199, 0x219e, 0x21a1, 0x21b0, 0x21b3, 0x21ba, 0x21c3, 0x21c7, 0x21ca,
|
||||
0x21d0, 0x21d4, 0x21dc, 0x21dd, 0x21e0, 0x21e3, 0x21ed, 0x21ee, 0x21f7, 0x21f8,
|
||||
0x21fa, 0x21fb, 0x227a, 0x227d, 0x23b2, 0x23b4, 0x23f4, 0x23f7, 0x2427, 0x243a,
|
||||
0x243c, 0x243c, 0x243e, 0x243e, 0x2460, 0x246b, 0x24f5, 0x24fd, 0x24ff, 0x24ff,
|
||||
0x278a, 0x278e, 0x27fc, 0x27fc, 0xe001, 0xe001, 0xff21, 0xff3a, 0x0, 0x0};
|
||||
|
||||
{
|
||||
ImFontConfig cfg;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 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
|
||||
|
@ -6,6 +6,8 @@
|
|||
#include "common/types.h"
|
||||
#include <string>
|
||||
|
||||
class Error;
|
||||
|
||||
struct ImFont;
|
||||
|
||||
union InputBindingKey;
|
||||
|
@ -22,7 +24,7 @@ void SetGlobalScale(float global_scale);
|
|||
void SetShowOSDMessages(bool enable);
|
||||
|
||||
/// Initializes ImGui, creates fonts, etc.
|
||||
bool Initialize(float global_scale, bool show_osd_messages);
|
||||
bool Initialize(float global_scale, bool show_osd_messages, Error* error);
|
||||
|
||||
/// Frees all ImGui resources.
|
||||
void Shutdown();
|
||||
|
|
|
@ -257,7 +257,8 @@ public:
|
|||
|
||||
protected:
|
||||
bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) override;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
||||
Error* error) override;
|
||||
void DestroyDevice() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "common/align.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/error.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/path.h"
|
||||
|
@ -122,7 +123,7 @@ void MetalDevice::SetVSync(bool enabled)
|
|||
|
||||
bool MetalDevice::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control,
|
||||
FeatureMask disabled_features)
|
||||
FeatureMask disabled_features, Error* error)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
|
@ -149,7 +150,7 @@ bool MetalDevice::CreateDevice(const std::string_view& adapter, bool threaded_pr
|
|||
device = [MTLCreateSystemDefaultDevice() autorelease];
|
||||
if (device == nil)
|
||||
{
|
||||
Log_ErrorPrint("Failed to create default Metal device.");
|
||||
Error::SetStringView(error, "Failed to create default Metal device.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +158,7 @@ bool MetalDevice::CreateDevice(const std::string_view& adapter, bool threaded_pr
|
|||
id<MTLCommandQueue> queue = [[device newCommandQueue] autorelease];
|
||||
if (queue == nil)
|
||||
{
|
||||
Log_ErrorPrint("Failed to create command queue.");
|
||||
Error::SetStringView(error, "Failed to create command queue.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -168,20 +169,23 @@ bool MetalDevice::CreateDevice(const std::string_view& adapter, bool threaded_pr
|
|||
SetFeatures(disabled_features);
|
||||
|
||||
if (m_window_info.type != WindowInfo::Type::Surfaceless && !CreateLayer())
|
||||
{
|
||||
Error::SetStringView(error, "Failed to create layer.");
|
||||
return false;
|
||||
}
|
||||
|
||||
CreateCommandBuffer();
|
||||
RenderBlankFrame();
|
||||
|
||||
if (!LoadShaders())
|
||||
{
|
||||
Log_ErrorPrint("Failed to load shaders.");
|
||||
Error::SetStringView(error, "Failed to load shaders.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateBuffers())
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create buffers.");
|
||||
Error::SetStringView(error, "Failed to create buffers.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -307,9 +307,9 @@ bool OpenGLDevice::HasSurface() const
|
|||
}
|
||||
|
||||
bool OpenGLDevice::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features, Error* error)
|
||||
{
|
||||
m_gl_context = GL::Context::Create(m_window_info);
|
||||
m_gl_context = GL::Context::Create(m_window_info, error);
|
||||
if (!m_gl_context)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create any GL context");
|
||||
|
|
|
@ -120,7 +120,8 @@ public:
|
|||
|
||||
protected:
|
||||
bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) override;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
||||
Error* error) override;
|
||||
void DestroyDevice() override;
|
||||
|
||||
bool ReadPipelineCache(const std::string& filename) override;
|
||||
|
|
|
@ -544,7 +544,7 @@ void OpenGLDevice::UnrefVAO(const OpenGLPipeline::VertexArrayCacheKey& key)
|
|||
OpenGLPipeline::OpenGLPipeline(const ProgramCacheKey& key, GLuint program, VertexArrayCache::const_iterator vao,
|
||||
const RasterizationState& rs, const DepthState& ds, const BlendState& bs,
|
||||
GLenum topology)
|
||||
: m_key(key), m_program(program), m_vao(vao), m_blend_state(bs), m_rasterization_state(rs), m_depth_state(ds),
|
||||
: m_key(key), m_vao(vao), m_program(program), m_blend_state(bs), m_rasterization_state(rs), m_depth_state(ds),
|
||||
m_topology(topology)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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 "vulkan_device.h"
|
||||
|
@ -13,6 +13,7 @@
|
|||
#include "common/align.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/bitutils.h"
|
||||
#include "common/error.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/path.h"
|
||||
|
@ -1859,7 +1860,8 @@ bool VulkanDevice::HasSurface() const
|
|||
}
|
||||
|
||||
bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
||||
Error* error)
|
||||
{
|
||||
std::unique_lock lock(s_instance_mutex);
|
||||
bool enable_debug_utils = m_debug_device;
|
||||
|
@ -1867,7 +1869,7 @@ bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_p
|
|||
|
||||
if (!Vulkan::LoadVulkanLibrary())
|
||||
{
|
||||
Host::ReportErrorAsync("Error", "Failed to load Vulkan library. Does your GPU and/or driver support Vulkan?");
|
||||
Error::SetStringView(error, "Failed to load Vulkan library. Does your GPU and/or driver support Vulkan?");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1883,8 +1885,7 @@ bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_p
|
|||
CreateVulkanInstance(m_window_info, &m_optional_extensions, enable_debug_utils, enable_validation_layer);
|
||||
if (m_instance == VK_NULL_HANDLE)
|
||||
{
|
||||
Host::ReportErrorAsync("Error",
|
||||
"Failed to create Vulkan instance. Does your GPU and/or driver support Vulkan?");
|
||||
Error::SetStringView(error, "Failed to create Vulkan instance. Does your GPU and/or driver support Vulkan?");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1895,13 +1896,14 @@ bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_p
|
|||
if (!Vulkan::LoadVulkanInstanceFunctions(m_instance))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to load Vulkan instance functions");
|
||||
Error::SetStringView(error, "Failed to load Vulkan instance functions");
|
||||
return false;
|
||||
}
|
||||
|
||||
GPUList gpus = EnumerateGPUs(m_instance);
|
||||
if (gpus.empty())
|
||||
{
|
||||
Host::ReportErrorAsync("Error", "No physical devices found. Does your GPU and/or driver support Vulkan?");
|
||||
Error::SetStringView(error, "No physical devices found. Does your GPU and/or driver support Vulkan?");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1964,7 +1966,7 @@ bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_p
|
|||
|
||||
if (!CheckFeatures(disabled_features))
|
||||
{
|
||||
Host::ReportErrorAsync("Error", "Your GPU does not support the required Vulkan features.");
|
||||
Error::SetStringView(error, "Your GPU does not support the required Vulkan features.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1982,7 +1984,7 @@ bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_p
|
|||
m_swap_chain = VulkanSwapChain::Create(m_window_info, surface, m_vsync_enabled, m_exclusive_fullscreen_control);
|
||||
if (!m_swap_chain)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create swap chain");
|
||||
Error::SetStringView(error, "Failed to create swap chain");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1998,12 +2000,15 @@ bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_p
|
|||
|
||||
if (!CreateNullTexture())
|
||||
{
|
||||
Log_ErrorPrint("Failed to create dummy texture");
|
||||
Error::SetStringView(error, "Failed to create dummy texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateBuffers() || !CreatePersistentDescriptorSets())
|
||||
{
|
||||
Error::SetStringView(error, "Failed to create buffers/descriptor sets");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -218,7 +218,8 @@ public:
|
|||
|
||||
protected:
|
||||
bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) override;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
||||
Error* error) override;
|
||||
void DestroyDevice() override;
|
||||
|
||||
bool ReadPipelineCache(const std::string& filename) override;
|
||||
|
|
Loading…
Reference in New Issue