From ab44536a3c5e03851a94848c8c08779d11eedf3d Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 9 Sep 2017 12:44:25 +1000 Subject: [PATCH 1/3] OGL: Update the window size after swapping buffers, not before Prevents us from rendering beyond the viewport bounds. --- .../VideoBackends/OGL/FramebufferManager.cpp | 1 + .../Core/VideoBackends/OGL/PostProcessing.cpp | 2 + Source/Core/VideoBackends/OGL/Render.cpp | 57 +++++++++---------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index af526fce36..a00b026103 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -54,6 +54,7 @@ GLuint FramebufferManager::CreateTexture(GLenum texture_type, GLenum internal_fo GLenum pixel_format, GLenum data_type) { GLuint texture; + glActiveTexture(GL_TEXTURE9); glGenTextures(1, &texture); glBindTexture(texture_type, texture); if (texture_type == GL_TEXTURE_2D_ARRAY) diff --git a/Source/Core/VideoBackends/OGL/PostProcessing.cpp b/Source/Core/VideoBackends/OGL/PostProcessing.cpp index bf34e2a54c..74a4c2da0e 100644 --- a/Source/Core/VideoBackends/OGL/PostProcessing.cpp +++ b/Source/Core/VideoBackends/OGL/PostProcessing.cpp @@ -12,6 +12,7 @@ #include "Core/Config/GraphicsSettings.h" #include "VideoBackends/OGL/FramebufferManager.h" +#include "VideoBackends/OGL/OGLTexture.h" #include "VideoBackends/OGL/ProgramShaderCache.h" #include "VideoBackends/OGL/SamplerCache.h" @@ -121,6 +122,7 @@ void OpenGLPostProcessing::BlitFromTexture(TargetRectangle src, TargetRectangle glBindTexture(GL_TEXTURE_2D_ARRAY, src_texture); g_sampler_cache->BindLinearSampler(9); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + OGLTexture::SetStage(); } void OpenGLPostProcessing::ApplyShader() diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index ac662e456b..8408d3bcae 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1355,11 +1355,37 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region xfb_texture->GetConfig().width, xfb_texture->GetConfig().height); // Finish up the current frame, print some stats + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // Reset viewport for drawing text + glViewport(0, 0, GLInterface->GetBackBufferWidth(), GLInterface->GetBackBufferHeight()); + DrawDebugText(); + + // Do our OSD callbacks + OSD::DoCallbacks(OSD::CallbackType::OnFrame); + OSD::DrawMessages(); + + // Copy the rendered frame to the real window. + GLInterface->Swap(); + +#ifdef ANDROID + // Handle surface changes on Android. + if (m_surface_needs_change.IsSet()) + { + GLInterface->UpdateHandle(m_new_surface_handle); + GLInterface->UpdateSurface(); + m_new_surface_handle = nullptr; + m_surface_needs_change.Clear(); + m_surface_changed.Set(); + } +#endif + + // Update the render window position and the backbuffer size SetWindowSize(xfb_texture->GetConfig().width, xfb_texture->GetConfig().height); + GLInterface->Update(); - GLInterface->Update(); // just updates the render window position and the backbuffer size - + // Was the size changed since the last frame? bool window_resized = false; int window_width = static_cast(std::max(GLInterface->GetBackBufferWidth(), 1u)); int window_height = static_cast(std::max(GLInterface->GetBackBufferHeight(), 1u)); @@ -1404,33 +1430,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region BoundingBox::SetTargetSizeChanged(m_target_width, m_target_height); } - // --------------------------------------------------------------------- - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // Reset viewport for drawing text - glViewport(0, 0, GLInterface->GetBackBufferWidth(), GLInterface->GetBackBufferHeight()); - - DrawDebugText(); - - // Do our OSD callbacks - OSD::DoCallbacks(OSD::CallbackType::OnFrame); - OSD::DrawMessages(); - -#ifdef ANDROID - if (m_surface_needs_change.IsSet()) - { - GLInterface->UpdateHandle(m_new_surface_handle); - GLInterface->UpdateSurface(); - m_new_surface_handle = nullptr; - m_surface_needs_change.Clear(); - m_surface_changed.Set(); - } -#endif - - // Copy the rendered frame to the real window - GLInterface->Swap(); - // Clear framebuffer glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); From 32125cf1817b57f0b6eb390409ba7167a1671cf7 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 23 Nov 2017 16:53:44 +1000 Subject: [PATCH 2/3] OGL: Fix headless frame dumping Also skips swapping the window system buffers in headless mode, as there may not be a surface which can be swapped in the first place. Instead, we call glFlush() at the end of a frame in this case. --- Source/Core/VideoBackends/OGL/Render.cpp | 50 ++++++++++++------- .../VideoBackends/Software/SWRenderer.cpp | 8 +-- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 2 +- Source/Core/VideoCommon/RenderBase.cpp | 8 ++- Source/Core/VideoCommon/RenderBase.h | 4 +- 5 files changed, 48 insertions(+), 24 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 8408d3bcae..84c1ce0dfc 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1349,25 +1349,35 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region // Flip top and bottom for some reason; TODO: Fix the code to suck less? std::swap(flipped_trc.top, flipped_trc.bottom); - // Copy the framebuffer to screen. - glBindFramebuffer(GL_FRAMEBUFFER, 0); - BlitScreen(sourceRc, flipped_trc, xfb_texture->GetRawTexIdentifier(), - xfb_texture->GetConfig().width, xfb_texture->GetConfig().height); - - // Finish up the current frame, print some stats - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // Reset viewport for drawing text - glViewport(0, 0, GLInterface->GetBackBufferWidth(), GLInterface->GetBackBufferHeight()); - DrawDebugText(); - // Do our OSD callbacks OSD::DoCallbacks(OSD::CallbackType::OnFrame); - OSD::DrawMessages(); - // Copy the rendered frame to the real window. - GLInterface->Swap(); + // Skip screen rendering when running in headless mode. + if (!IsHeadless()) + { + // Copy the framebuffer to screen. + glBindFramebuffer(GL_FRAMEBUFFER, 0); + BlitScreen(sourceRc, flipped_trc, xfb_texture->GetRawTexIdentifier(), + xfb_texture->GetConfig().width, xfb_texture->GetConfig().height); + + // Finish up the current frame, print some stats + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // Reset viewport for drawing text + glViewport(0, 0, GLInterface->GetBackBufferWidth(), GLInterface->GetBackBufferHeight()); + DrawDebugText(); + OSD::DrawMessages(); + + // Copy the rendered frame to the real window. + GLInterface->Swap(); + } + else + { + // Since we're not swapping in headless mode, ensure all commands are sent to the GPU. + // Otherwise the driver could batch several frames togehter. + glFlush(); + } #ifdef ANDROID // Handle surface changes on Android. @@ -1375,6 +1385,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region { GLInterface->UpdateHandle(m_new_surface_handle); GLInterface->UpdateSurface(); + m_surface_handle = m_new_surface_handle; m_new_surface_handle = nullptr; m_surface_needs_change.Clear(); m_surface_changed.Set(); @@ -1431,8 +1442,11 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region } // Clear framebuffer - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if (!IsHeadless()) + { + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } if (s_vsync != g_ActiveConfig.IsVSync()) { diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp index 69523efe78..4c298e927e 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp @@ -45,9 +45,11 @@ void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_regi { OSD::DoCallbacks(OSD::CallbackType::OnFrame); - DrawDebugText(); - - SWOGLWindow::s_instance->ShowImage(texture, xfb_region); + if (!IsHeadless()) + { + DrawDebugText(); + SWOGLWindow::s_instance->ShowImage(texture, xfb_region); + } UpdateActiveConfig(); } diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 8f83e2b202..084e7a2880 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -600,7 +600,6 @@ void Renderer::DrawScreen(VKTexture* xfb_texture, const EFBRectangle& xfb_region VK_SUBPASS_CONTENTS_INLINE); // Draw - TargetRectangle source_rc = xfb_texture->GetConfig().GetRect(); BlitScreen(m_swap_chain->GetRenderPass(), GetTargetRectangle(), xfb_region, xfb_texture->GetRawTexIdentifier()); @@ -702,6 +701,7 @@ void Renderer::CheckForSurfaceChange() // Notify calling thread. m_surface_needs_change.Clear(); + m_surface_handle = m_new_surface_handle; m_new_surface_handle = nullptr; m_surface_changed.Set(); } diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 4a46475344..2edd6dcfd5 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -94,6 +94,7 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height) if (SConfig::GetInstance().bWii) m_aspect_wide = Config::Get(Config::SYSCONF_WIDESCREEN); + m_surface_handle = Host_GetRenderHandle(); m_last_host_config_bits = ShaderHostConfig::GetCurrent().bits; } @@ -400,6 +401,11 @@ float Renderer::CalculateDrawAspectRatio() const } } +bool Renderer::IsHeadless() const +{ + return !m_surface_handle; +} + std::tuple Renderer::ScaleToDisplayAspectRatio(const int width, const int height) const { @@ -711,7 +717,7 @@ void Renderer::DoDumpFrame() void Renderer::UpdateFrameDumpTexture() { int target_width, target_height; - if (!g_ActiveConfig.bInternalResolutionFrameDumps) + if (!g_ActiveConfig.bInternalResolutionFrameDumps && !IsHeadless()) { auto target_rect = GetTargetRectangle(); target_width = target_rect.GetWidth(); diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index b622372b90..1edb5c75d4 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -94,6 +94,7 @@ public: const TargetRectangle& GetTargetRectangle() const { return m_target_rectangle; } float CalculateDrawAspectRatio() const; + bool IsHeadless() const; std::tuple ScaleToDisplayAspectRatio(int width, int height) const; void UpdateDrawRectangle(); @@ -176,9 +177,10 @@ protected: static const float GX_MAX_DEPTH; + void* m_surface_handle = nullptr; + void* m_new_surface_handle = nullptr; Common::Flag m_surface_needs_change; Common::Event m_surface_changed; - void* m_new_surface_handle = nullptr; u32 m_last_host_config_bits = 0; From cf1f97514866a655f0d497ab61c9c392d83bef6c Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 23 Nov 2017 17:00:25 +1000 Subject: [PATCH 3/3] Vulkan: Fix headless framedumping without USE_X11 set --- Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp b/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp index f72d43d62e..0c9fae677b 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp @@ -14,7 +14,7 @@ #if defined(VK_USE_PLATFORM_WIN32_KHR) #include #elif defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR) || \ - defined(VK_USE_PLATFORM_ANDROID_KHR) + defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(USE_HEADLESS) #include #endif @@ -98,7 +98,7 @@ void UnloadVulkanLibrary() } #elif defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR) || \ - defined(VK_USE_PLATFORM_ANDROID_KHR) + defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(USE_HEADLESS) static void* vulkan_module; static std::atomic_int vulkan_module_ref_count = {0};