From 14cf8659057d10a1734029f955848cf15b39e0ed Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 28 Jan 2023 21:38:03 +1000 Subject: [PATCH] Misc: Correctness fixes for OpenGL GLES2 fallback should be functional again. --- README.md | 2 +- src/common/gl/texture.cpp | 15 +++--- src/core/gpu_hw_d3d11.cpp | 40 +++++++-------- src/core/gpu_hw_d3d11.h | 4 +- src/core/gpu_hw_d3d12.cpp | 25 +++++----- src/core/gpu_hw_d3d12.h | 2 +- src/core/gpu_hw_opengl.cpp | 55 +++++++++++---------- src/core/gpu_hw_opengl.h | 2 +- src/core/gpu_hw_vulkan.cpp | 28 +++++------ src/core/gpu_hw_vulkan.h | 2 +- src/core/gpu_sw.cpp | 39 ++++++++------- src/core/system.cpp | 7 ++- src/duckstation-nogui/nogui_host.cpp | 2 +- src/duckstation-qt/qthost.cpp | 2 +- src/frontend-common/imgui_impl_opengl3.cpp | 29 ++++++----- src/frontend-common/imgui_manager.cpp | 7 ++- src/frontend-common/imgui_manager.h | 2 +- src/frontend-common/opengl_host_display.cpp | 7 +-- 18 files changed, 145 insertions(+), 125 deletions(-) diff --git a/README.md b/README.md index 929ab50b1..1bfb40704 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Other features include: ## System Requirements - A CPU faster than a potato. But it needs to be x86_64, AArch32/armv7, or AArch64/ARMv8, otherwise you won't get a recompiler and it'll be slow. - - For the hardware renderers, a GPU capable of OpenGL 3.1/OpenGL ES 3.0/Direct3D 11 Feature Level 10.0 (or Vulkan 1.0) and above. So, basically anything made in the last 10 years or so. + - For the hardware renderers, a GPU capable of OpenGL 3.1/OpenGL ES 3.1/Direct3D 11 Feature Level 10.0 (or Vulkan 1.0) and above. So, basically anything made in the last 10 years or so. - SDL, XInput or DInput compatible game controller (e.g. XB360/XBOne). DualShock 3 users on Windows will need to install the official DualShock 3 drivers included as part of PlayStation Now. ## Downloading and running diff --git a/src/common/gl/texture.cpp b/src/common/gl/texture.cpp index 9af644fb1..08bcce89a 100644 --- a/src/common/gl/texture.cpp +++ b/src/common/gl/texture.cpp @@ -118,6 +118,9 @@ bool GL::Texture::Create(u32 width, u32 height, u32 layers, u32 levels, u32 samp else glTexImage2DMultisample(target, samples, gl_internal_format, width, height, GL_FALSE); } + + glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels); } else { @@ -148,8 +151,12 @@ bool GL::Texture::Create(u32 width, u32 height, u32 layers, u32 levels, u32 samp glTexImage2D(target, i, gl_internal_format, width, height, 0, gl_format, gl_type, data); } - glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels); + // This doesn't exist on GLES2. + if (!GLAD_GL_ES_VERSION_2_0 || GLAD_GL_ES_VERSION_3_0) + { + glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels); + } } glTexParameteri(target, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); @@ -161,10 +168,6 @@ bool GL::Texture::Create(u32 width, u32 height, u32 layers, u32 levels, u32 samp glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap ? GL_REPEAT : GL_CLAMP_TO_EDGE); } - // This doesn't exist on GLES2. - if (!GLAD_GL_ES_VERSION_2_0 || GLAD_GL_ES_VERSION_3_0) - glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 1); - GLenum error = glGetError(); if (error != GL_NO_ERROR) { diff --git a/src/core/gpu_hw_d3d11.cpp b/src/core/gpu_hw_d3d11.cpp index 35067506b..55eaa753f 100644 --- a/src/core/gpu_hw_d3d11.cpp +++ b/src/core/gpu_hw_d3d11.cpp @@ -14,18 +14,12 @@ #include "util/state_wrapper.h" Log_SetChannel(GPU_HW_D3D11); -GPU_HW_D3D11::GPU_HW_D3D11() = default; +GPU_HW_D3D11::GPU_HW_D3D11(ID3D11Device* device, ID3D11DeviceContext* context) : m_device(device), m_context(context) {} GPU_HW_D3D11::~GPU_HW_D3D11() { - if (g_host_display) - { - g_host_display->ClearDisplayTexture(); - ResetGraphicsAPIState(); - } - - if (m_context) - m_context->ClearState(); + g_host_display->ClearDisplayTexture(); + GPU_HW_D3D11::ResetGraphicsAPIState(); DestroyShaders(); DestroyStateObjects(); @@ -38,17 +32,6 @@ GPURenderer GPU_HW_D3D11::GetRendererType() const bool GPU_HW_D3D11::Initialize() { - if (!Host::AcquireHostDisplay(RenderAPI::D3D11)) - { - Log_ErrorPrintf("Host render API is incompatible"); - return false; - } - - m_device = static_cast(g_host_display->GetDevice()); - m_context = static_cast(g_host_display->GetContext()); - if (!m_device || !m_context) - return false; - SetCapabilities(); if (!GPU_HW::Initialize()) @@ -1213,5 +1196,20 @@ void GPU_HW_D3D11::DownsampleFramebufferBoxFilter(D3D11::Texture& source, u32 le std::unique_ptr GPU::CreateHardwareD3D11Renderer() { - return std::make_unique(); + if (!Host::AcquireHostDisplay(RenderAPI::D3D11)) + { + Log_ErrorPrintf("Host render API is incompatible"); + return nullptr; + } + + ID3D11Device* device = static_cast(g_host_display->GetDevice()); + ID3D11DeviceContext* context = static_cast(g_host_display->GetContext()); + if (!device || !context) + return nullptr; + + std::unique_ptr gpu(std::make_unique(device, context)); + if (!gpu->Initialize()) + return nullptr; + + return gpu; } diff --git a/src/core/gpu_hw_d3d11.h b/src/core/gpu_hw_d3d11.h index 00cd65b59..0a6f7533d 100644 --- a/src/core/gpu_hw_d3d11.h +++ b/src/core/gpu_hw_d3d11.h @@ -13,13 +13,13 @@ #include #include -class GPU_HW_D3D11 : public GPU_HW +class GPU_HW_D3D11 final : public GPU_HW { public: template using ComPtr = Microsoft::WRL::ComPtr; - GPU_HW_D3D11(); + GPU_HW_D3D11(ID3D11Device* device, ID3D11DeviceContext* context); ~GPU_HW_D3D11() override; GPURenderer GetRendererType() const override; diff --git a/src/core/gpu_hw_d3d12.cpp b/src/core/gpu_hw_d3d12.cpp index 02b06815a..b1544a276 100644 --- a/src/core/gpu_hw_d3d12.cpp +++ b/src/core/gpu_hw_d3d12.cpp @@ -21,11 +21,8 @@ GPU_HW_D3D12::GPU_HW_D3D12() = default; GPU_HW_D3D12::~GPU_HW_D3D12() { - if (g_host_display) - { - g_host_display->ClearDisplayTexture(); - ResetGraphicsAPIState(); - } + g_host_display->ClearDisplayTexture(); + GPU_HW_D3D12::ResetGraphicsAPIState(); DestroyResources(); } @@ -37,12 +34,6 @@ GPURenderer GPU_HW_D3D12::GetRendererType() const bool GPU_HW_D3D12::Initialize() { - if (!Host::AcquireHostDisplay(RenderAPI::D3D12)) - { - Log_ErrorPrintf("Host render API is incompatible"); - return false; - } - SetCapabilities(); if (!GPU_HW::Initialize()) @@ -1193,5 +1184,15 @@ void GPU_HW_D3D12::ClearDepthBuffer() std::unique_ptr GPU::CreateHardwareD3D12Renderer() { - return std::make_unique(); + if (!Host::AcquireHostDisplay(RenderAPI::D3D12)) + { + Log_ErrorPrintf("Host render API is incompatible"); + return nullptr; + } + + std::unique_ptr gpu(std::make_unique()); + if (!gpu->Initialize()) + return nullptr; + + return gpu; } diff --git a/src/core/gpu_hw_d3d12.h b/src/core/gpu_hw_d3d12.h index 209614585..88cf60e8e 100644 --- a/src/core/gpu_hw_d3d12.h +++ b/src/core/gpu_hw_d3d12.h @@ -12,7 +12,7 @@ #include #include -class GPU_HW_D3D12 : public GPU_HW +class GPU_HW_D3D12 final : public GPU_HW { public: template diff --git a/src/core/gpu_hw_opengl.cpp b/src/core/gpu_hw_opengl.cpp index 7386bf67d..a208f1017 100644 --- a/src/core/gpu_hw_opengl.cpp +++ b/src/core/gpu_hw_opengl.cpp @@ -28,11 +28,8 @@ GPU_HW_OpenGL::~GPU_HW_OpenGL() if (m_texture_buffer_r16ui_texture != 0) glDeleteTextures(1, &m_texture_buffer_r16ui_texture); - if (g_host_display) - { - g_host_display->ClearDisplayTexture(); - ResetGraphicsAPIState(); - } + g_host_display->ClearDisplayTexture(); + GPU_HW_OpenGL::ResetGraphicsAPIState(); // One of our programs might've been bound. GL::Program::ResetLastProgram(); @@ -46,27 +43,6 @@ GPURenderer GPU_HW_OpenGL::GetRendererType() const bool GPU_HW_OpenGL::Initialize() { - // Don't re-request GL when we already have GLES here... - const RenderAPI current_api = g_host_display ? g_host_display->GetRenderAPI() : RenderAPI::None; - if (current_api != RenderAPI::OpenGL && current_api != RenderAPI::OpenGLES && - !Host::AcquireHostDisplay(RenderAPI::OpenGL)) - { - Log_ErrorPrintf("Host render API type is incompatible"); - return false; - } - - const bool opengl_is_available = ((g_host_display->GetRenderAPI() == RenderAPI::OpenGL && - (GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_uniform_buffer_object)) || - (g_host_display->GetRenderAPI() == RenderAPI::OpenGLES && GLAD_GL_ES_VERSION_3_0)); - if (!opengl_is_available) - { - Host::AddOSDMessage(Host::TranslateStdString("OSDMessage", - "OpenGL renderer unavailable, your driver or hardware is not " - "recent enough. OpenGL 3.1 or OpenGL ES 3.0 is required."), - 20.0f); - return false; - } - SetCapabilities(); if (!GPU_HW::Initialize()) @@ -1333,5 +1309,30 @@ void GPU_HW_OpenGL::DownsampleFramebufferBoxFilter(GL::Texture& source, u32 left std::unique_ptr GPU::CreateHardwareOpenGLRenderer() { - return std::make_unique(); + // Don't re-request GL when we already have GLES here... + const RenderAPI current_api = g_host_display ? g_host_display->GetRenderAPI() : RenderAPI::None; + if (current_api != RenderAPI::OpenGL && current_api != RenderAPI::OpenGLES && + !Host::AcquireHostDisplay(RenderAPI::OpenGL)) + { + Log_ErrorPrintf("Host render API type is incompatible"); + return nullptr; + } + + const bool opengl_is_available = ((g_host_display->GetRenderAPI() == RenderAPI::OpenGL && + (GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_uniform_buffer_object)) || + (g_host_display->GetRenderAPI() == RenderAPI::OpenGLES && GLAD_GL_ES_VERSION_3_1)); + if (!opengl_is_available) + { + Host::AddOSDMessage(Host::TranslateStdString("OSDMessage", + "OpenGL renderer unavailable, your driver or hardware is not " + "recent enough. OpenGL 3.1 or OpenGL ES 3.1 is required."), + 20.0f); + return nullptr; + } + + std::unique_ptr gpu(std::make_unique()); + if (!gpu->Initialize()) + return nullptr; + + return gpu; } diff --git a/src/core/gpu_hw_opengl.h b/src/core/gpu_hw_opengl.h index c116e2f14..b7a091bfc 100644 --- a/src/core/gpu_hw_opengl.h +++ b/src/core/gpu_hw_opengl.h @@ -13,7 +13,7 @@ #include #include -class GPU_HW_OpenGL : public GPU_HW +class GPU_HW_OpenGL final : public GPU_HW { public: GPU_HW_OpenGL(); diff --git a/src/core/gpu_hw_vulkan.cpp b/src/core/gpu_hw_vulkan.cpp index d931d1658..4e614809b 100644 --- a/src/core/gpu_hw_vulkan.cpp +++ b/src/core/gpu_hw_vulkan.cpp @@ -20,12 +20,8 @@ GPU_HW_Vulkan::GPU_HW_Vulkan() = default; GPU_HW_Vulkan::~GPU_HW_Vulkan() { - if (g_host_display) - { - g_host_display->ClearDisplayTexture(); - ResetGraphicsAPIState(); - } - + g_host_display->ClearDisplayTexture(); + GPU_HW_Vulkan::ResetGraphicsAPIState(); DestroyResources(); } @@ -36,13 +32,6 @@ GPURenderer GPU_HW_Vulkan::GetRendererType() const bool GPU_HW_Vulkan::Initialize() { - if (!Host::AcquireHostDisplay(RenderAPI::Vulkan)) - { - Log_ErrorPrintf("Host render API is incompatible"); - return false; - } - - Assert(g_vulkan_shader_cache); SetCapabilities(); if (!GPU_HW::Initialize()) @@ -1993,5 +1982,16 @@ void GPU_HW_Vulkan::DownsampleFramebufferAdaptive(Vulkan::Texture& source, u32 l std::unique_ptr GPU::CreateHardwareVulkanRenderer() { - return std::make_unique(); + if (!Host::AcquireHostDisplay(RenderAPI::Vulkan)) + { + Log_ErrorPrintf("Host render API is incompatible"); + return nullptr; + } + + Assert(g_vulkan_shader_cache); + std::unique_ptr gpu(std::make_unique()); + if (!gpu->Initialize()) + return nullptr; + + return gpu; } diff --git a/src/core/gpu_hw_vulkan.h b/src/core/gpu_hw_vulkan.h index 1e67746a5..fbb8200c4 100644 --- a/src/core/gpu_hw_vulkan.h +++ b/src/core/gpu_hw_vulkan.h @@ -11,7 +11,7 @@ #include #include -class GPU_HW_Vulkan : public GPU_HW +class GPU_HW_Vulkan final : public GPU_HW { public: GPU_HW_Vulkan(); diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp index fc3ef598a..188e1b9fb 100644 --- a/src/core/gpu_sw.cpp +++ b/src/core/gpu_sw.cpp @@ -39,8 +39,7 @@ GPU_SW::GPU_SW() GPU_SW::~GPU_SW() { m_backend.Shutdown(); - if (g_host_display) - g_host_display->ClearDisplayTexture(); + g_host_display->ClearDisplayTexture(); } GPURenderer GPU_SW::GetRendererType() const @@ -55,18 +54,13 @@ const Threading::Thread* GPU_SW::GetSWThread() const bool GPU_SW::Initialize() { - // we need something to draw in.. but keep the current api if we have one - if (!g_host_display && !Host::AcquireHostDisplay(HostDisplay::GetPreferredAPI())) - return false; - if (!GPU::Initialize() || !m_backend.Initialize(false)) return false; static constexpr auto formats_for_16bit = make_array(GPUTexture::Format::RGB565, GPUTexture::Format::RGBA5551, GPUTexture::Format::RGBA8, GPUTexture::Format::BGRA8); - static constexpr auto formats_for_24bit = - make_array(GPUTexture::Format::RGBA8, GPUTexture::Format::BGRA8, GPUTexture::Format::RGB565, - GPUTexture::Format::RGBA5551); + static constexpr auto formats_for_24bit = make_array(GPUTexture::Format::RGBA8, GPUTexture::Format::BGRA8, + GPUTexture::Format::RGB565, GPUTexture::Format::RGBA5551); for (const GPUTexture::Format format : formats_for_16bit) { if (g_host_display->SupportsTextureFormat(format)) @@ -260,8 +254,9 @@ void GPU_SW::CopyOut15Bit(u32 src_x, u32 src_y, u32 width, u32 height, u32 field u8* dst_ptr; u32 dst_stride; - using OutputPixelType = std::conditional_t< - display_format == GPUTexture::Format::RGBA8 || display_format == GPUTexture::Format::BGRA8, u32, u16>; + using OutputPixelType = + std::conditional_t; GPUTexture* texture = GetDisplayTexture(width, height, display_format); if (!texture) @@ -353,8 +348,9 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh u8* dst_ptr; u32 dst_stride; - using OutputPixelType = std::conditional_t< - display_format == GPUTexture::Format::RGBA8 || display_format == GPUTexture::Format::BGRA8, u32, u16>; + using OutputPixelType = + std::conditional_t; GPUTexture* texture = GetDisplayTexture(width, height, display_format); if (!texture) @@ -481,14 +477,13 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh g_host_display->SetDisplayTexture(texture, 0, 0, width, height); } -void GPU_SW::CopyOut24Bit(GPUTexture::Format display_format, u32 src_x, u32 src_y, u32 skip_x, u32 width, - u32 height, u32 field, bool interlaced, bool interleaved) +void GPU_SW::CopyOut24Bit(GPUTexture::Format display_format, u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 height, + u32 field, bool interlaced, bool interleaved) { switch (display_format) { case GPUTexture::Format::RGBA5551: - CopyOut24Bit(src_x, src_y, skip_x, width, height, field, interlaced, - interleaved); + CopyOut24Bit(src_x, src_y, skip_x, width, height, field, interlaced, interleaved); break; case GPUTexture::Format::RGB565: CopyOut24Bit(src_x, src_y, skip_x, width, height, field, interlaced, interleaved); @@ -899,5 +894,13 @@ void GPU_SW::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 std::unique_ptr GPU::CreateSoftwareRenderer() { - return std::make_unique(); + // we need something to draw in.. but keep the current api if we have one + if (!g_host_display && !Host::AcquireHostDisplay(HostDisplay::GetPreferredAPI())) + return nullptr; + + std::unique_ptr gpu(std::make_unique()); + if (!gpu->Initialize()) + return nullptr; + + return gpu; } diff --git a/src/core/system.cpp b/src/core/system.cpp index dcf4703e1..4fa5f1a54 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -1619,7 +1619,7 @@ bool System::CreateGPU(GPURenderer renderer) break; } - if (!g_gpu || !g_gpu->Initialize()) + if (!g_gpu) { Log_ErrorPrintf("Failed to initialize %s renderer, falling back to software renderer", Settings::GetRendererName(renderer)); @@ -1629,8 +1629,11 @@ bool System::CreateGPU(GPURenderer renderer) Settings::GetRendererName(renderer)); g_gpu.reset(); g_gpu = GPU::CreateSoftwareRenderer(); - if (!g_gpu->Initialize()) + if (!g_gpu) + { + Log_ErrorPrintf("Failed to create fallback software renderer."); return false; + } } return true; diff --git a/src/duckstation-nogui/nogui_host.cpp b/src/duckstation-nogui/nogui_host.cpp index 0c5191f1d..617aeec7b 100644 --- a/src/duckstation-nogui/nogui_host.cpp +++ b/src/duckstation-nogui/nogui_host.cpp @@ -791,7 +791,7 @@ void Host::RenderDisplay(bool skip_present) { FullscreenUI::Render(); ImGuiManager::RenderTextOverlays(); - ImGuiManager::RenderOSD(); + ImGuiManager::RenderOSDMessages(); } // Debug windows are always rendered, otherwise mouse input breaks on skip. diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index e37be1587..1e4d50039 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -1455,7 +1455,7 @@ void EmuThread::renderDisplay(bool skip_present) { FullscreenUI::Render(); ImGuiManager::RenderTextOverlays(); - ImGuiManager::RenderOSD(); + ImGuiManager::RenderOSDMessages(); } // Debug windows are always rendered, otherwise mouse input breaks on skip. diff --git a/src/frontend-common/imgui_impl_opengl3.cpp b/src/frontend-common/imgui_impl_opengl3.cpp index 6385e40fa..ab606b90f 100644 --- a/src/frontend-common/imgui_impl_opengl3.cpp +++ b/src/frontend-common/imgui_impl_opengl3.cpp @@ -159,9 +159,6 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) } bd->GlVersion = (GLuint)(major * 100 + minor * 10); - if (bd->GlVersion >= 320) - io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. - // Store GLSL version string so we can refer to it later in case we recreate shaders. // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. if (glsl_version == NULL) @@ -171,11 +168,10 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) strcpy(bd->GlslVersionString, glsl_version); strcat(bd->GlslVersionString, "\n"); - if (!glDrawElementsBaseVertex) - { - Log_ErrorPrintf("Missing glDrawElementsBaseVertex()"); - return false; - } + if (glDrawElementsBaseVertex) + io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. + else + Log_WarningPrintf("Missing glDrawElementsBaseVertex()"); return ImGui_ImplOpenGL3_CreateDeviceObjects(); } @@ -226,7 +222,9 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); // Bind vertex/index buffers and setup attributes for ImDrawVert - glBindVertexArray(bd->VaoHandle); + if (bd->VaoHandle) + glBindVertexArray(bd->VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, bd->VboHandle); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bd->ElementsHandle); glEnableVertexAttribArray(bd->AttribLocationVtxPos); @@ -305,12 +303,17 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) const GL::Texture* tex = static_cast(pcmd->GetTexID()); if (tex) tex->Bind(); - glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); + + if (glDrawElementsBaseVertex) + glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); + else + glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); } } } - glBindVertexArray(0); + if (bd->VaoHandle) + glBindVertexArray(0); } bool ImGui_ImplOpenGL3_CreateFontsTexture() @@ -544,7 +547,9 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() // Create buffers glGenBuffers(1, &bd->VboHandle); glGenBuffers(1, &bd->ElementsHandle); - glGenVertexArrays(1, &bd->VaoHandle); + + if (glGenVertexArrays) + glGenVertexArrays(1, &bd->VaoHandle); return true; } diff --git a/src/frontend-common/imgui_manager.cpp b/src/frontend-common/imgui_manager.cpp index 88e70eb8c..d2f570548 100644 --- a/src/frontend-common/imgui_manager.cpp +++ b/src/frontend-common/imgui_manager.cpp @@ -569,6 +569,11 @@ void Host::AddOSDMessage(std::string message, float duration /*= 2.0f*/) void Host::AddKeyedOSDMessage(std::string key, std::string message, float duration /* = 2.0f */) { + if (!key.empty()) + Log_InfoPrintf("OSD [%s]: %s", key.c_str(), message.c_str()); + else + Log_InfoPrintf("OSD: %s", message.c_str()); + OSDMessage msg; msg.key = std::move(key); msg.text = std::move(message); @@ -711,7 +716,7 @@ void ImGuiManager::DrawOSDMessages() } } -void ImGuiManager::RenderOSD() +void ImGuiManager::RenderOSDMessages() { AcquirePendingOSDMessages(); DrawOSDMessages(); diff --git a/src/frontend-common/imgui_manager.h b/src/frontend-common/imgui_manager.h index 6ecddbf60..e5f01fc21 100644 --- a/src/frontend-common/imgui_manager.h +++ b/src/frontend-common/imgui_manager.h @@ -34,7 +34,7 @@ void UpdateScale(); void NewFrame(); /// Renders any on-screen display elements. -void RenderOSD(); +void RenderOSDMessages(); /// Returns the scale of all on-screen elements. float GetGlobalScale(); diff --git a/src/frontend-common/opengl_host_display.cpp b/src/frontend-common/opengl_host_display.cpp index cab46fce1..9acaf3c86 100644 --- a/src/frontend-common/opengl_host_display.cpp +++ b/src/frontend-common/opengl_host_display.cpp @@ -297,7 +297,8 @@ bool OpenGLHostDisplay::CreateDevice(const WindowInfo& wi, bool vsync) bool OpenGLHostDisplay::SetupDevice() { - m_use_gles2_draw_path = (GetRenderAPI() == RenderAPI::OpenGLES && !GLAD_GL_ES_VERSION_3_0); + // If we don't have GLES3.1, then SV_VertexID isn't defined when no VBOs are active. + m_use_gles2_draw_path = (GetRenderAPI() == RenderAPI::OpenGLES && !GLAD_GL_ES_VERSION_3_1); if (!m_use_gles2_draw_path) glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, reinterpret_cast(&m_uniform_buffer_alignment)); @@ -540,7 +541,7 @@ void main() glSamplerParameteri(m_display_border_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glSamplerParameteri(m_display_border_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glTexParameterfv(m_display_border_sampler, GL_TEXTURE_BORDER_COLOR, border_color); + glSamplerParameterfv(m_display_border_sampler, GL_TEXTURE_BORDER_COLOR, border_color); } } else @@ -740,7 +741,7 @@ void OpenGLHostDisplay::RenderDisplay() return; } - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT); if (!HasDisplayTexture())