From 5be76abf2993449e4b6ca07582d0e5825aa13fd2 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 7 Sep 2024 12:15:42 +1000 Subject: [PATCH] GPUDevice: Purge threaded presentation Worse frame pacing, and GPU thread (when I finish it) will give significantly faster performance on mobile anyway. --- src/core/fullscreen_ui.cpp | 21 +-- src/core/host.cpp | 13 +- src/core/settings.cpp | 2 - src/core/settings.h | 3 - src/core/system.cpp | 2 - src/duckstation-qt/graphicssettingswidget.cpp | 6 - src/duckstation-qt/graphicssettingswidget.ui | 21 +-- src/util/d3d11_device.cpp | 5 +- src/util/d3d11_device.h | 5 +- src/util/d3d12_device.cpp | 5 +- src/util/d3d12_device.h | 5 +- src/util/gpu_device.cpp | 4 +- src/util/gpu_device.h | 9 +- src/util/metal_device.h | 5 +- src/util/metal_device.mm | 5 +- src/util/opengl_device.cpp | 5 +- src/util/opengl_device.h | 11 +- src/util/vulkan_device.cpp | 131 +++--------------- src/util/vulkan_device.h | 38 +---- src/util/vulkan_swap_chain.h | 4 - 20 files changed, 65 insertions(+), 235 deletions(-) diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index 163a58548..39fa0a777 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -924,8 +924,8 @@ void FullscreenUI::DestroyResources() ImGuiFullscreen::FileSelectorFilters FullscreenUI::GetDiscImageFilters() { - return {"*.bin", "*.cue", "*.iso", "*.img", "*.chd", "*.ecm", "*.mds", - "*.psexe", "*.ps-exe", "*.exe", "*.psx", "*.psf", "*.minipsf", "*.m3u", "*.pbp"}; + return {"*.bin", "*.cue", "*.iso", "*.img", "*.chd", "*.ecm", "*.mds", "*.psexe", + "*.ps-exe", "*.exe", "*.psx", "*.psf", "*.minipsf", "*.m3u", "*.pbp"}; } void FullscreenUI::DoStartPath(std::string path, std::string state, std::optional fast_boot) @@ -4454,16 +4454,6 @@ void FullscreenUI::DrawDisplaySettingsPage() break; #endif -#ifdef ENABLE_VULKAN - case GPURenderer::HardwareVulkan: - { - DrawToggleSetting(bsi, FSUI_CSTR("Threaded Presentation"), - FSUI_CSTR("Presents frames on a background thread when fast forwarding or vsync is disabled."), - "GPU", "ThreadedPresentation", true); - } - break; -#endif - case GPURenderer::Software: { DrawToggleSetting(bsi, FSUI_CSTR("Threaded Rendering"), @@ -7019,9 +7009,8 @@ void FullscreenUI::DrawAboutWindow() if (ImGui::BeginPopupModal(FSUI_CSTR("About DuckStation"), &s_about_window_open, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize)) { - ImGui::TextWrapped("%s", - FSUI_CSTR("DuckStation is a free simulator/emulator of the Sony PlayStation(TM) " - "console, focusing on playability, speed, and long-term maintainability.")); + ImGui::TextWrapped("%s", FSUI_CSTR("DuckStation is a free simulator/emulator of the Sony PlayStation(TM) " + "console, focusing on playability, speed, and long-term maintainability.")); ImGui::NewLine(); ImGui::TextWrapped(FSUI_CSTR("Version: %s"), g_scm_tag_str); ImGui::NewLine(); @@ -7576,7 +7565,6 @@ TRANSLATE_NOOP("FullscreenUI", "Post-processing chain cleared."); TRANSLATE_NOOP("FullscreenUI", "Post-processing shaders reloaded."); TRANSLATE_NOOP("FullscreenUI", "Preload Images to RAM"); TRANSLATE_NOOP("FullscreenUI", "Preload Replacement Textures"); -TRANSLATE_NOOP("FullscreenUI", "Presents frames on a background thread when fast forwarding or vsync is disabled."); TRANSLATE_NOOP("FullscreenUI", "Preserve Projection Precision"); TRANSLATE_NOOP("FullscreenUI", "Prevents the emulator from producing any audible sound."); TRANSLATE_NOOP("FullscreenUI", "Prevents the screen saver from activating and the host from sleeping while emulation is running."); @@ -7754,7 +7742,6 @@ TRANSLATE_NOOP("FullscreenUI", "The audio backend determines how frames produced TRANSLATE_NOOP("FullscreenUI", "The selected memory card image will be used in shared mode for this slot."); TRANSLATE_NOOP("FullscreenUI", "This game has no achievements."); TRANSLATE_NOOP("FullscreenUI", "This game has no leaderboards."); -TRANSLATE_NOOP("FullscreenUI", "Threaded Presentation"); TRANSLATE_NOOP("FullscreenUI", "Threaded Rendering"); TRANSLATE_NOOP("FullscreenUI", "Time Played"); TRANSLATE_NOOP("FullscreenUI", "Time Played: %s"); diff --git a/src/core/host.cpp b/src/core/host.cpp index 4ff2ffdc0..36f901440 100644 --- a/src/core/host.cpp +++ b/src/core/host.cpp @@ -295,13 +295,12 @@ bool Host::CreateGPUDevice(RenderAPI api, Error* error) disabled_features |= GPUDevice::FEATURE_MASK_RASTER_ORDER_VIEWS; Error create_error; - 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, - System::GetEffectiveVSyncMode(), System::ShouldAllowPresentThrottle(), - g_settings.gpu_threaded_presentation, exclusive_fullscreen_control, - static_cast(disabled_features), &create_error)) + 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, System::GetEffectiveVSyncMode(), + System::ShouldAllowPresentThrottle(), exclusive_fullscreen_control, + static_cast(disabled_features), &create_error)) { ERROR_LOG("Failed to create GPU device: {}", create_error.GetDescription()); if (g_gpu_device) diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 25067971c..9e01752ab 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -203,7 +203,6 @@ void Settings::Load(SettingsInterface& si, SettingsInterface& controller_si) gpu_per_sample_shading = si.GetBoolValue("GPU", "PerSampleShading", false); gpu_use_thread = si.GetBoolValue("GPU", "UseThread", true); gpu_use_software_renderer_for_readbacks = si.GetBoolValue("GPU", "UseSoftwareRendererForReadbacks", false); - gpu_threaded_presentation = si.GetBoolValue("GPU", "ThreadedPresentation", DEFAULT_THREADED_PRESENTATION); gpu_true_color = si.GetBoolValue("GPU", "TrueColor", true); gpu_debanding = si.GetBoolValue("GPU", "Debanding", false); gpu_scaled_dithering = si.GetBoolValue("GPU", "ScaledDithering", true); @@ -523,7 +522,6 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const si.SetBoolValue("GPU", "PerSampleShading", gpu_per_sample_shading); si.SetBoolValue("GPU", "UseThread", gpu_use_thread); - si.SetBoolValue("GPU", "ThreadedPresentation", gpu_threaded_presentation); si.SetBoolValue("GPU", "UseSoftwareRendererForReadbacks", gpu_use_software_renderer_for_readbacks); si.SetBoolValue("GPU", "TrueColor", gpu_true_color); si.SetBoolValue("GPU", "Debanding", gpu_debanding); diff --git a/src/core/settings.h b/src/core/settings.h index a310a32bb..5d1a5b50e 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -106,7 +106,6 @@ struct Settings u8 gpu_multisamples = 1; bool gpu_use_thread : 1 = true; bool gpu_use_software_renderer_for_readbacks : 1 = false; - bool gpu_threaded_presentation : 1 = DEFAULT_THREADED_PRESENTATION; bool gpu_use_debug_device : 1 = false; bool gpu_disable_shader_cache : 1 = false; bool gpu_disable_dual_source_blend : 1 = false; @@ -540,11 +539,9 @@ struct Settings #ifndef __ANDROID__ static constexpr bool DEFAULT_SAVE_STATE_BACKUPS = true; static constexpr bool DEFAULT_FAST_BOOT_VALUE = false; - static constexpr bool DEFAULT_THREADED_PRESENTATION = false; #else static constexpr bool DEFAULT_SAVE_STATE_BACKUPS = false; static constexpr bool DEFAULT_FAST_BOOT_VALUE = true; - static constexpr bool DEFAULT_THREADED_PRESENTATION = true; #endif // PINE uses a concept of "slot" to be able to communicate with multiple diff --git a/src/core/system.cpp b/src/core/system.cpp index 38d9be05b..ed44070d7 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -4173,7 +4173,6 @@ void System::CheckForSettingsChanges(const Settings& old_settings) if (IsValid() && (g_settings.gpu_renderer != old_settings.gpu_renderer || g_settings.gpu_use_debug_device != old_settings.gpu_use_debug_device || - g_settings.gpu_threaded_presentation != old_settings.gpu_threaded_presentation || g_settings.gpu_disable_shader_cache != old_settings.gpu_disable_shader_cache || g_settings.gpu_disable_dual_source_blend != old_settings.gpu_disable_dual_source_blend || g_settings.gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch || @@ -4186,7 +4185,6 @@ void System::CheckForSettingsChanges(const Settings& old_settings) // if debug device/threaded presentation change, we need to recreate the whole display const bool recreate_device = (g_settings.gpu_use_debug_device != old_settings.gpu_use_debug_device || - g_settings.gpu_threaded_presentation != old_settings.gpu_threaded_presentation || g_settings.gpu_disable_shader_cache != old_settings.gpu_disable_shader_cache || g_settings.gpu_disable_dual_source_blend != old_settings.gpu_disable_dual_source_blend || g_settings.gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch || diff --git a/src/duckstation-qt/graphicssettingswidget.cpp b/src/duckstation-qt/graphicssettingswidget.cpp index 6d9cbc333..086bdc080 100644 --- a/src/duckstation-qt/graphicssettingswidget.cpp +++ b/src/duckstation-qt/graphicssettingswidget.cpp @@ -119,8 +119,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* &Settings::ParseDisplayRotation, &Settings::GetDisplayRotationName, Settings::DEFAULT_DISPLAY_ROTATION); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.gpuThread, "GPU", "UseThread", true); - SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.threadedPresentation, "GPU", "ThreadedPresentation", - Settings::DEFAULT_THREADED_PRESENTATION); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableMailboxPresentation, "Display", "DisableMailboxPresentation", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.stretchDisplayVertically, "Display", "StretchVertically", @@ -376,9 +374,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* dialog->registerWidgetHelp(m_ui.gpuThread, tr("Threaded Rendering"), tr("Checked"), tr("Uses a second thread for drawing graphics. Currently only available for the software " "renderer, but can provide a significant speed improvement, and is safe to use.")); - dialog->registerWidgetHelp(m_ui.threadedPresentation, tr("Threaded Presentation"), tr("Checked"), - tr("Presents frames on a background thread when fast forwarding or vsync is disabled. " - "This can measurably improve performance in the Vulkan renderer.")); dialog->registerWidgetHelp( m_ui.disableMailboxPresentation, tr("Disable Mailbox Presentation"), tr("Unchecked"), tr("Forces the use of FIFO over Mailbox presentation, i.e. double buffering instead of triple buffering. " @@ -772,7 +767,6 @@ void GraphicsSettingsWidget::updateRendererDependentOptions() #endif m_ui.gpuThread->setEnabled(!is_hardware); - m_ui.threadedPresentation->setEnabled(render_api == RenderAPI::Vulkan); m_ui.exclusiveFullscreenLabel->setEnabled(render_api == RenderAPI::D3D11 || render_api == RenderAPI::D3D12 || render_api == RenderAPI::Vulkan); diff --git a/src/duckstation-qt/graphicssettingswidget.ui b/src/duckstation-qt/graphicssettingswidget.ui index 1ed5f9579..89236ca20 100644 --- a/src/duckstation-qt/graphicssettingswidget.ui +++ b/src/duckstation-qt/graphicssettingswidget.ui @@ -341,20 +341,6 @@ - - - - Threaded Presentation - - - - - - - Use Blit Swap Chain - - - @@ -362,6 +348,13 @@ + + + + Use Blit Swap Chain + + + diff --git a/src/util/d3d11_device.cpp b/src/util/d3d11_device.cpp index 09af8b9f5..1ebb8a850 100644 --- a/src/util/d3d11_device.cpp +++ b/src/util/d3d11_device.cpp @@ -63,9 +63,8 @@ bool D3D11Device::HasSurface() const return static_cast(m_swap_chain); } -bool D3D11Device::CreateDevice(std::string_view adapter, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, - Error* error) +bool D3D11Device::CreateDevice(std::string_view adapter, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error) { std::unique_lock lock(s_instance_mutex); diff --git a/src/util/d3d11_device.h b/src/util/d3d11_device.h index 151a7b112..577a496d1 100644 --- a/src/util/d3d11_device.h +++ b/src/util/d3d11_device.h @@ -112,9 +112,8 @@ public: void UnbindTexture(D3D11Texture* tex); protected: - bool CreateDevice(std::string_view adapter, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, - Error* error) override; + bool CreateDevice(std::string_view adapter, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error) override; void DestroyDevice() override; private: diff --git a/src/util/d3d12_device.cpp b/src/util/d3d12_device.cpp index ca64fed4e..51afe0846 100644 --- a/src/util/d3d12_device.cpp +++ b/src/util/d3d12_device.cpp @@ -117,9 +117,8 @@ D3D12Device::ComPtr D3D12Device::CreateRootSignature(const return rs; } -bool D3D12Device::CreateDevice(std::string_view adapter, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, - Error* error) +bool D3D12Device::CreateDevice(std::string_view adapter, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error) { std::unique_lock lock(s_instance_mutex); diff --git a/src/util/d3d12_device.h b/src/util/d3d12_device.h index 9167042e6..b2fd4366b 100644 --- a/src/util/d3d12_device.h +++ b/src/util/d3d12_device.h @@ -185,9 +185,8 @@ public: void UnbindTextureBuffer(D3D12TextureBuffer* buf); protected: - bool CreateDevice(std::string_view adapter, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, - Error* error) override; + bool CreateDevice(std::string_view adapter, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error) override; void DestroyDevice() override; bool ReadPipelineCache(std::optional> data) override; diff --git a/src/util/gpu_device.cpp b/src/util/gpu_device.cpp index e64015ba4..f9b09ab84 100644 --- a/src/util/gpu_device.cpp +++ b/src/util/gpu_device.cpp @@ -347,7 +347,7 @@ GPUDevice::AdapterInfoList GPUDevice::GetAdapterListForAPI(RenderAPI api) } bool GPUDevice::Create(std::string_view adapter, std::string_view shader_cache_path, u32 shader_cache_version, - bool debug_device, GPUVSyncMode vsync, bool allow_present_throttle, bool threaded_presentation, + bool debug_device, GPUVSyncMode vsync, bool allow_present_throttle, std::optional exclusive_fullscreen_control, FeatureMask disabled_features, Error* error) { m_vsync_mode = vsync; @@ -360,7 +360,7 @@ bool GPUDevice::Create(std::string_view adapter, std::string_view shader_cache_p return false; } - if (!CreateDevice(adapter, threaded_presentation, exclusive_fullscreen_control, disabled_features, error)) + if (!CreateDevice(adapter, exclusive_fullscreen_control, disabled_features, error)) { if (error && !error->IsValid()) error->SetStringView("Failed to create device."); diff --git a/src/util/gpu_device.h b/src/util/gpu_device.h index cb7c89338..f9965ebf6 100644 --- a/src/util/gpu_device.h +++ b/src/util/gpu_device.h @@ -604,8 +604,8 @@ public: virtual RenderAPI GetRenderAPI() const = 0; bool Create(std::string_view adapter, std::string_view shader_cache_path, u32 shader_cache_version, bool debug_device, - GPUVSyncMode vsync, bool allow_present_throttle, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, Error* error); + GPUVSyncMode vsync, bool allow_present_throttle, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error); void Destroy(); virtual bool HasSurface() const = 0; @@ -737,9 +737,8 @@ public: static void ResetStatistics(); protected: - virtual bool CreateDevice(std::string_view adapter, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, - Error* error) = 0; + virtual bool CreateDevice(std::string_view adapter, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error) = 0; virtual void DestroyDevice() = 0; std::string GetShaderCacheBaseName(std::string_view type) const; diff --git a/src/util/metal_device.h b/src/util/metal_device.h index 6854d0554..84b4aff1b 100644 --- a/src/util/metal_device.h +++ b/src/util/metal_device.h @@ -287,9 +287,8 @@ public: static void DeferRelease(u64 fence_counter, id obj); protected: - bool CreateDevice(std::string_view adapter, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, - Error* error) override; + bool CreateDevice(std::string_view adapter, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error) override; void DestroyDevice() override; private: diff --git a/src/util/metal_device.mm b/src/util/metal_device.mm index 2bd14f86f..9ef0e1de3 100644 --- a/src/util/metal_device.mm +++ b/src/util/metal_device.mm @@ -161,9 +161,8 @@ void MetalDevice::SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle) [m_layer setDisplaySyncEnabled:m_vsync_mode == GPUVSyncMode::FIFO]; } -bool MetalDevice::CreateDevice(std::string_view adapter, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, - Error* error) +bool MetalDevice::CreateDevice(std::string_view adapter, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error) { @autoreleasepool { diff --git a/src/util/opengl_device.cpp b/src/util/opengl_device.cpp index 46208b650..57967a03d 100644 --- a/src/util/opengl_device.cpp +++ b/src/util/opengl_device.cpp @@ -281,9 +281,8 @@ bool OpenGLDevice::HasSurface() const return m_window_info.type != WindowInfo::Type::Surfaceless; } -bool OpenGLDevice::CreateDevice(std::string_view adapter, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, - Error* error) +bool OpenGLDevice::CreateDevice(std::string_view adapter, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error) { m_gl_context = OpenGLContext::Create(m_window_info, error); if (!m_gl_context) diff --git a/src/util/opengl_device.h b/src/util/opengl_device.h index 0c0f445ac..e72a92f1d 100644 --- a/src/util/opengl_device.h +++ b/src/util/opengl_device.h @@ -115,12 +115,14 @@ public: void CommitRTClearInFB(OpenGLTexture* tex, u32 idx); void CommitDSClearInFB(OpenGLTexture* tex); - GLuint LookupProgramCache(const OpenGLPipeline::ProgramCacheKey& key, const GPUPipeline::GraphicsConfig& plconfig, Error* error); + GLuint LookupProgramCache(const OpenGLPipeline::ProgramCacheKey& key, const GPUPipeline::GraphicsConfig& plconfig, + Error* error); GLuint CompileProgram(const GPUPipeline::GraphicsConfig& plconfig, Error* error); void PostLinkProgram(const GPUPipeline::GraphicsConfig& plconfig, GLuint program_id); void UnrefProgram(const OpenGLPipeline::ProgramCacheKey& key); - OpenGLPipeline::VertexArrayCache::const_iterator LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key, Error* error); + OpenGLPipeline::VertexArrayCache::const_iterator LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key, + Error* error); GLuint CreateVAO(std::span attributes, u32 stride, Error* error); void UnrefVAO(const OpenGLPipeline::VertexArrayCacheKey& key); @@ -132,9 +134,8 @@ public: void UnbindPipeline(const OpenGLPipeline* pl); protected: - bool CreateDevice(std::string_view adapter, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, - Error* error) override; + bool CreateDevice(std::string_view adapter, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error) override; void DestroyDevice() override; bool OpenPipelineCache(const std::string& filename) override; diff --git a/src/util/vulkan_device.cpp b/src/util/vulkan_device.cpp index 904d57a9e..2ef663754 100644 --- a/src/util/vulkan_device.cpp +++ b/src/util/vulkan_device.cpp @@ -1268,7 +1268,6 @@ void VulkanDevice::WaitForFenceCounter(u64 fence_counter) void VulkanDevice::WaitForGPUIdle() { - WaitForPresentComplete(); vkDeviceWaitIdle(m_device); } @@ -1287,13 +1286,6 @@ bool VulkanDevice::SetGPUTimingEnabled(bool enabled) void VulkanDevice::WaitForCommandBufferCompletion(u32 index) { - // We might be waiting for the buffer we just submitted to the worker thread. - if (m_queued_present.command_buffer_index == index && !m_present_done.load(std::memory_order_acquire)) - { - WARNING_LOG("Waiting for threaded submission of cmdbuffer {}", index); - WaitForPresentComplete(); - } - // Wait for this command buffer to be completed. static constexpr u32 MAX_TIMEOUTS = 10; u32 timeouts = 0; @@ -1311,7 +1303,7 @@ void VulkanDevice::WaitForCommandBufferCompletion(u32 index) else if (res != VK_SUCCESS) { LOG_VULKAN_ERROR(res, TinyString::from_format("vkWaitForFences() for cmdbuffer {} failed: ", index)); - m_last_submit_failed.store(true, std::memory_order_release); + m_device_is_lost = true; return; } } @@ -1363,10 +1355,9 @@ void VulkanDevice::WaitForCommandBufferCompletion(u32 index) } } -void VulkanDevice::EndAndSubmitCommandBuffer(VulkanSwapChain* present_swap_chain, bool explicit_present, - bool submit_on_thread) +void VulkanDevice::EndAndSubmitCommandBuffer(VulkanSwapChain* present_swap_chain, bool explicit_present) { - if (m_last_submit_failed.load(std::memory_order_acquire)) + if (m_device_is_lost) return; CommandBuffer& resources = m_frame_resources[m_current_frame]; @@ -1399,27 +1390,6 @@ void VulkanDevice::EndAndSubmitCommandBuffer(VulkanSwapChain* present_swap_chain // This command buffer now has commands, so can't be re-used without waiting. resources.needs_fence_wait = true; - std::unique_lock lock(m_present_mutex); - WaitForPresentComplete(lock); - - if (!submit_on_thread || explicit_present || !m_present_thread.joinable()) - { - DoSubmitCommandBuffer(m_current_frame, present_swap_chain); - if (present_swap_chain && !explicit_present) - DoPresent(present_swap_chain); - return; - } - - m_queued_present.command_buffer_index = m_current_frame; - m_queued_present.swap_chain = present_swap_chain; - m_present_done.store(false, std::memory_order_release); - m_present_queued_cv.notify_one(); -} - -void VulkanDevice::DoSubmitCommandBuffer(u32 index, VulkanSwapChain* present_swap_chain) -{ - CommandBuffer& resources = m_frame_resources[index]; - uint32_t wait_bits = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo submit_info = {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, @@ -1442,16 +1412,19 @@ void VulkanDevice::DoSubmitCommandBuffer(u32 index, VulkanSwapChain* present_swa submit_info.signalSemaphoreCount = 1; } - const VkResult res = vkQueueSubmit(m_graphics_queue, 1, &submit_info, resources.fence); + res = vkQueueSubmit(m_graphics_queue, 1, &submit_info, resources.fence); if (res != VK_SUCCESS) { LOG_VULKAN_ERROR(res, "vkQueueSubmit failed: "); - m_last_submit_failed.store(true, std::memory_order_release); + m_device_is_lost = true; return; } + + if (present_swap_chain && !explicit_present) + QueuePresent(present_swap_chain); } -void VulkanDevice::DoPresent(VulkanSwapChain* present_swap_chain) +void VulkanDevice::QueuePresent(VulkanSwapChain* present_swap_chain) { const VkPresentInfoKHR present_info = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, nullptr, @@ -1482,65 +1455,6 @@ void VulkanDevice::DoPresent(VulkanSwapChain* present_swap_chain) present_swap_chain->AcquireNextImage(); } -void VulkanDevice::WaitForPresentComplete() -{ - if (m_present_done.load(std::memory_order_acquire)) - return; - - std::unique_lock lock(m_present_mutex); - WaitForPresentComplete(lock); -} - -void VulkanDevice::WaitForPresentComplete(std::unique_lock& lock) -{ - if (m_present_done.load(std::memory_order_acquire)) - return; - - m_present_done_cv.wait(lock, [this]() { return m_present_done.load(std::memory_order_acquire); }); -} - -void VulkanDevice::PresentThread() -{ - std::unique_lock lock(m_present_mutex); - while (!m_present_thread_done.load(std::memory_order_acquire)) - { - m_present_queued_cv.wait(lock, [this]() { - return !m_present_done.load(std::memory_order_acquire) || m_present_thread_done.load(std::memory_order_acquire); - }); - - if (m_present_done.load(std::memory_order_acquire)) - continue; - - DoSubmitCommandBuffer(m_queued_present.command_buffer_index, m_queued_present.swap_chain); - if (m_queued_present.swap_chain) - DoPresent(m_queued_present.swap_chain); - m_present_done.store(true, std::memory_order_release); - m_present_done_cv.notify_one(); - } -} - -void VulkanDevice::StartPresentThread() -{ - DebugAssert(!m_present_thread.joinable()); - m_present_thread_done.store(false, std::memory_order_release); - m_present_thread = std::thread(&VulkanDevice::PresentThread, this); -} - -void VulkanDevice::StopPresentThread() -{ - if (!m_present_thread.joinable()) - return; - - { - std::unique_lock lock(m_present_mutex); - WaitForPresentComplete(lock); - m_present_thread_done.store(true, std::memory_order_release); - m_present_queued_cv.notify_one(); - } - - m_present_thread.join(); -} - void VulkanDevice::MoveToNextCommandBuffer() { BeginCommandBuffer((m_current_frame + 1) % NUM_COMMAND_BUFFERS); @@ -1602,7 +1516,7 @@ void VulkanDevice::SubmitCommandBuffer(bool wait_for_completion) DebugAssert(!InRenderPass()); const u32 current_frame = m_current_frame; - EndAndSubmitCommandBuffer(nullptr, false, false); + EndAndSubmitCommandBuffer(nullptr, false); MoveToNextCommandBuffer(); if (wait_for_completion) @@ -1629,11 +1543,6 @@ void VulkanDevice::SubmitCommandBufferAndRestartRenderPass(const std::string_vie BeginRenderPass(); } -bool VulkanDevice::CheckLastSubmitFail() -{ - return m_last_submit_failed.load(std::memory_order_acquire); -} - void VulkanDevice::DeferBufferDestruction(VkBuffer object, VmaAllocation allocation) { m_cleanup_objects.emplace_back(GetCurrentFenceCounter(), @@ -1987,9 +1896,8 @@ bool VulkanDevice::HasSurface() const return static_cast(m_swap_chain); } -bool VulkanDevice::CreateDevice(std::string_view adapter, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, - Error* error) +bool VulkanDevice::CreateDevice(std::string_view adapter, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error) { std::unique_lock lock(s_instance_mutex); bool enable_debug_utils = m_debug_device; @@ -2097,9 +2005,6 @@ bool VulkanDevice::CreateDevice(std::string_view adapter, bool threaded_presenta if (!CreateAllocator() || !CreatePersistentDescriptorPool() || !CreateCommandBuffers() || !CreatePipelineLayouts()) return false; - if (threaded_presentation) - StartPresentThread(); - m_exclusive_fullscreen_control = exclusive_fullscreen_control; if (surface != VK_NULL_HANDLE) @@ -2148,7 +2053,6 @@ void VulkanDevice::DestroyDevice() if (m_device != VK_NULL_HANDLE) WaitForGPUIdle(); - StopPresentThread(); m_swap_chain.reset(); if (m_null_texture) @@ -2451,11 +2355,8 @@ bool VulkanDevice::BeginPresent(bool frame_skip, u32 clear_color) return false; } - // Previous frame needs to be presented before we can acquire the swap chain. - WaitForPresentComplete(); - // Check if the device was lost. - if (CheckLastSubmitFail()) + if (m_device_is_lost) { Panic("Fixme"); // TODO TrimTexturePool(); @@ -2511,7 +2412,7 @@ void VulkanDevice::EndPresent(bool explicit_present) VulkanTexture::TransitionSubresourcesToLayout(cmdbuf, m_swap_chain->GetCurrentImage(), GPUTexture::Type::RenderTarget, 0, 1, 0, 1, VulkanTexture::Layout::ColorAttachment, VulkanTexture::Layout::PresentSrc); - EndAndSubmitCommandBuffer(m_swap_chain.get(), explicit_present, !m_swap_chain->IsPresentModeSynchronizing()); + EndAndSubmitCommandBuffer(m_swap_chain.get(), explicit_present); MoveToNextCommandBuffer(); InvalidateCachedState(); TrimTexturePool(); @@ -2520,7 +2421,7 @@ void VulkanDevice::EndPresent(bool explicit_present) void VulkanDevice::SubmitPresent() { DebugAssert(m_swap_chain); - DoPresent(m_swap_chain.get()); + QueuePresent(m_swap_chain.get()); } #ifdef _DEBUG @@ -3185,7 +3086,7 @@ void VulkanDevice::RenderBlankFrame() VulkanTexture::TransitionSubresourcesToLayout(cmdbuf, image, GPUTexture::Type::RenderTarget, 0, 1, 0, 1, VulkanTexture::Layout::TransferDst, VulkanTexture::Layout::PresentSrc); - EndAndSubmitCommandBuffer(m_swap_chain.get(), false, !m_swap_chain->IsPresentModeSynchronizing()); + EndAndSubmitCommandBuffer(m_swap_chain.get(), false); MoveToNextCommandBuffer(); InvalidateCachedState(); diff --git a/src/util/vulkan_device.h b/src/util/vulkan_device.h index dd6231989..851de9a61 100644 --- a/src/util/vulkan_device.h +++ b/src/util/vulkan_device.h @@ -17,9 +17,7 @@ #include #include #include -#include #include -#include #include #include @@ -234,9 +232,8 @@ public: void UnbindTextureBuffer(VulkanTextureBuffer* buf); protected: - bool CreateDevice(std::string_view adapter, bool threaded_presentation, - std::optional exclusive_fullscreen_control, FeatureMask disabled_features, - Error* error) override; + bool CreateDevice(std::string_view adapter, std::optional exclusive_fullscreen_control, + FeatureMask disabled_features, Error* error) override; void DestroyDevice() override; bool ReadPipelineCache(std::optional> data) override; @@ -329,11 +326,6 @@ private: bool IsDeviceImgTec() const; bool IsBrokenMobileDriver() const; - void EndAndSubmitCommandBuffer(VulkanSwapChain* present_swap_chain, bool explicit_present, bool submit_on_thread); - void MoveToNextCommandBuffer(); - void WaitForPresentComplete(); - bool CheckLastSubmitFail(); - using ExtensionList = std::vector; static bool SelectInstanceExtensions(ExtensionList* extension_list, const WindowInfo& wi, OptionalExtensions* oe, bool enable_debug_utils); @@ -395,13 +387,9 @@ private: void BeginCommandBuffer(u32 index); void WaitForCommandBufferCompletion(u32 index); - - void DoSubmitCommandBuffer(u32 index, VulkanSwapChain* present_swap_chain); - void DoPresent(VulkanSwapChain* present_swap_chain); - void WaitForPresentComplete(std::unique_lock& lock); - void PresentThread(); - void StartPresentThread(); - void StopPresentThread(); + void EndAndSubmitCommandBuffer(VulkanSwapChain* present_swap_chain, bool explicit_present); + void MoveToNextCommandBuffer(); + void QueuePresent(VulkanSwapChain* present_swap_chain); VkInstance m_instance = VK_NULL_HANDLE; VkPhysicalDevice m_physical_device = VK_NULL_HANDLE; @@ -426,21 +414,7 @@ private: u64 m_completed_fence_counter = 0; u32 m_current_frame = 0; - std::atomic_bool m_last_submit_failed{false}; - std::atomic_bool m_present_done{true}; - std::mutex m_present_mutex; - std::condition_variable m_present_queued_cv; - std::condition_variable m_present_done_cv; - std::thread m_present_thread; - std::atomic_bool m_present_thread_done{false}; - - struct QueuedPresent - { - VulkanSwapChain* swap_chain; - u32 command_buffer_index; - }; - - QueuedPresent m_queued_present = {nullptr, 0xFFFFFFFFu}; + bool m_device_is_lost = false; std::unordered_map m_render_pass_cache; GPUFramebufferManager m_framebuffer_manager; diff --git a/src/util/vulkan_swap_chain.h b/src/util/vulkan_swap_chain.h index 94a8c4615..cdca30961 100644 --- a/src/util/vulkan_swap_chain.h +++ b/src/util/vulkan_swap_chain.h @@ -69,10 +69,6 @@ public: return &m_semaphores[m_current_semaphore].rendering_finished_semaphore; } - // Returns true if the current present mode is synchronizing (adaptive or hard). - ALWAYS_INLINE bool IsPresentModeSynchronizing() const { return (m_present_mode == VK_PRESENT_MODE_FIFO_KHR); } - ALWAYS_INLINE VkPresentModeKHR GetPresentMode() const { return m_present_mode; } - VkResult AcquireNextImage(); void ReleaseCurrentImage(); void ResetImageAcquireResult();