mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-25 23:25:41 +00:00
GPUDevice: Purge threaded presentation
Worse frame pacing, and GPU thread (when I finish it) will give significantly faster performance on mobile anyway.
This commit is contained in:
parent
fc48133a75
commit
3a4ac13c26
|
@ -924,8 +924,8 @@ void FullscreenUI::DestroyResources()
|
||||||
|
|
||||||
ImGuiFullscreen::FileSelectorFilters FullscreenUI::GetDiscImageFilters()
|
ImGuiFullscreen::FileSelectorFilters FullscreenUI::GetDiscImageFilters()
|
||||||
{
|
{
|
||||||
return {"*.bin", "*.cue", "*.iso", "*.img", "*.chd", "*.ecm", "*.mds",
|
return {"*.bin", "*.cue", "*.iso", "*.img", "*.chd", "*.ecm", "*.mds", "*.psexe",
|
||||||
"*.psexe", "*.ps-exe", "*.exe", "*.psx", "*.psf", "*.minipsf", "*.m3u", "*.pbp"};
|
"*.ps-exe", "*.exe", "*.psx", "*.psf", "*.minipsf", "*.m3u", "*.pbp"};
|
||||||
}
|
}
|
||||||
|
|
||||||
void FullscreenUI::DoStartPath(std::string path, std::string state, std::optional<bool> fast_boot)
|
void FullscreenUI::DoStartPath(std::string path, std::string state, std::optional<bool> fast_boot)
|
||||||
|
@ -4454,16 +4454,6 @@ void FullscreenUI::DrawDisplaySettingsPage()
|
||||||
break;
|
break;
|
||||||
#endif
|
#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:
|
case GPURenderer::Software:
|
||||||
{
|
{
|
||||||
DrawToggleSetting(bsi, FSUI_CSTR("Threaded Rendering"),
|
DrawToggleSetting(bsi, FSUI_CSTR("Threaded Rendering"),
|
||||||
|
@ -7024,9 +7014,8 @@ void FullscreenUI::DrawAboutWindow()
|
||||||
if (ImGui::BeginPopupModal(FSUI_CSTR("About DuckStation"), &s_about_window_open,
|
if (ImGui::BeginPopupModal(FSUI_CSTR("About DuckStation"), &s_about_window_open,
|
||||||
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize))
|
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize))
|
||||||
{
|
{
|
||||||
ImGui::TextWrapped("%s",
|
ImGui::TextWrapped("%s", FSUI_CSTR("DuckStation is a free simulator/emulator of the Sony PlayStation(TM) "
|
||||||
FSUI_CSTR("DuckStation is a free simulator/emulator of the Sony PlayStation(TM) "
|
"console, focusing on playability, speed, and long-term maintainability."));
|
||||||
"console, focusing on playability, speed, and long-term maintainability."));
|
|
||||||
ImGui::NewLine();
|
ImGui::NewLine();
|
||||||
ImGui::TextWrapped(FSUI_CSTR("Version: %s"), g_scm_tag_str);
|
ImGui::TextWrapped(FSUI_CSTR("Version: %s"), g_scm_tag_str);
|
||||||
ImGui::NewLine();
|
ImGui::NewLine();
|
||||||
|
@ -7583,7 +7572,6 @@ TRANSLATE_NOOP("FullscreenUI", "Post-processing chain cleared.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Post-processing shaders reloaded.");
|
TRANSLATE_NOOP("FullscreenUI", "Post-processing shaders reloaded.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Preload Images to RAM");
|
TRANSLATE_NOOP("FullscreenUI", "Preload Images to RAM");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Preload Replacement Textures");
|
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", "Preserve Projection Precision");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Prevents the emulator from producing any audible sound.");
|
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.");
|
TRANSLATE_NOOP("FullscreenUI", "Prevents the screen saver from activating and the host from sleeping while emulation is running.");
|
||||||
|
@ -7761,7 +7749,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", "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 achievements.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "This game has no leaderboards.");
|
TRANSLATE_NOOP("FullscreenUI", "This game has no leaderboards.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Threaded Presentation");
|
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Threaded Rendering");
|
TRANSLATE_NOOP("FullscreenUI", "Threaded Rendering");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Time Played");
|
TRANSLATE_NOOP("FullscreenUI", "Time Played");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Time Played: %s");
|
TRANSLATE_NOOP("FullscreenUI", "Time Played: %s");
|
||||||
|
|
|
@ -295,13 +295,12 @@ bool Host::CreateGPUDevice(RenderAPI api, Error* error)
|
||||||
disabled_features |= GPUDevice::FEATURE_MASK_RASTER_ORDER_VIEWS;
|
disabled_features |= GPUDevice::FEATURE_MASK_RASTER_ORDER_VIEWS;
|
||||||
|
|
||||||
Error create_error;
|
Error create_error;
|
||||||
if (!g_gpu_device || !g_gpu_device->Create(g_settings.gpu_adapter,
|
if (!g_gpu_device || !g_gpu_device->Create(
|
||||||
g_settings.gpu_disable_shader_cache ? std::string_view() :
|
g_settings.gpu_adapter,
|
||||||
std::string_view(EmuFolders::Cache),
|
g_settings.gpu_disable_shader_cache ? std::string_view() : std::string_view(EmuFolders::Cache),
|
||||||
SHADER_CACHE_VERSION, g_settings.gpu_use_debug_device,
|
SHADER_CACHE_VERSION, g_settings.gpu_use_debug_device, System::GetEffectiveVSyncMode(),
|
||||||
System::GetEffectiveVSyncMode(), System::ShouldAllowPresentThrottle(),
|
System::ShouldAllowPresentThrottle(), exclusive_fullscreen_control,
|
||||||
g_settings.gpu_threaded_presentation, exclusive_fullscreen_control,
|
static_cast<GPUDevice::FeatureMask>(disabled_features), &create_error))
|
||||||
static_cast<GPUDevice::FeatureMask>(disabled_features), &create_error))
|
|
||||||
{
|
{
|
||||||
ERROR_LOG("Failed to create GPU device: {}", create_error.GetDescription());
|
ERROR_LOG("Failed to create GPU device: {}", create_error.GetDescription());
|
||||||
if (g_gpu_device)
|
if (g_gpu_device)
|
||||||
|
|
|
@ -203,7 +203,6 @@ void Settings::Load(SettingsInterface& si, SettingsInterface& controller_si)
|
||||||
gpu_per_sample_shading = si.GetBoolValue("GPU", "PerSampleShading", false);
|
gpu_per_sample_shading = si.GetBoolValue("GPU", "PerSampleShading", false);
|
||||||
gpu_use_thread = si.GetBoolValue("GPU", "UseThread", true);
|
gpu_use_thread = si.GetBoolValue("GPU", "UseThread", true);
|
||||||
gpu_use_software_renderer_for_readbacks = si.GetBoolValue("GPU", "UseSoftwareRendererForReadbacks", false);
|
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_true_color = si.GetBoolValue("GPU", "TrueColor", true);
|
||||||
gpu_debanding = si.GetBoolValue("GPU", "Debanding", false);
|
gpu_debanding = si.GetBoolValue("GPU", "Debanding", false);
|
||||||
gpu_scaled_dithering = si.GetBoolValue("GPU", "ScaledDithering", true);
|
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", "PerSampleShading", gpu_per_sample_shading);
|
||||||
si.SetBoolValue("GPU", "UseThread", gpu_use_thread);
|
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", "UseSoftwareRendererForReadbacks", gpu_use_software_renderer_for_readbacks);
|
||||||
si.SetBoolValue("GPU", "TrueColor", gpu_true_color);
|
si.SetBoolValue("GPU", "TrueColor", gpu_true_color);
|
||||||
si.SetBoolValue("GPU", "Debanding", gpu_debanding);
|
si.SetBoolValue("GPU", "Debanding", gpu_debanding);
|
||||||
|
|
|
@ -106,7 +106,6 @@ struct Settings
|
||||||
u8 gpu_multisamples = 1;
|
u8 gpu_multisamples = 1;
|
||||||
bool gpu_use_thread : 1 = true;
|
bool gpu_use_thread : 1 = true;
|
||||||
bool gpu_use_software_renderer_for_readbacks : 1 = false;
|
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_use_debug_device : 1 = false;
|
||||||
bool gpu_disable_shader_cache : 1 = false;
|
bool gpu_disable_shader_cache : 1 = false;
|
||||||
bool gpu_disable_dual_source_blend : 1 = false;
|
bool gpu_disable_dual_source_blend : 1 = false;
|
||||||
|
@ -540,11 +539,9 @@ struct Settings
|
||||||
#ifndef __ANDROID__
|
#ifndef __ANDROID__
|
||||||
static constexpr bool DEFAULT_SAVE_STATE_BACKUPS = true;
|
static constexpr bool DEFAULT_SAVE_STATE_BACKUPS = true;
|
||||||
static constexpr bool DEFAULT_FAST_BOOT_VALUE = false;
|
static constexpr bool DEFAULT_FAST_BOOT_VALUE = false;
|
||||||
static constexpr bool DEFAULT_THREADED_PRESENTATION = false;
|
|
||||||
#else
|
#else
|
||||||
static constexpr bool DEFAULT_SAVE_STATE_BACKUPS = false;
|
static constexpr bool DEFAULT_SAVE_STATE_BACKUPS = false;
|
||||||
static constexpr bool DEFAULT_FAST_BOOT_VALUE = true;
|
static constexpr bool DEFAULT_FAST_BOOT_VALUE = true;
|
||||||
static constexpr bool DEFAULT_THREADED_PRESENTATION = true;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// PINE uses a concept of "slot" to be able to communicate with multiple
|
// PINE uses a concept of "slot" to be able to communicate with multiple
|
||||||
|
|
|
@ -4173,7 +4173,6 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
||||||
if (IsValid() &&
|
if (IsValid() &&
|
||||||
(g_settings.gpu_renderer != old_settings.gpu_renderer ||
|
(g_settings.gpu_renderer != old_settings.gpu_renderer ||
|
||||||
g_settings.gpu_use_debug_device != old_settings.gpu_use_debug_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_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_dual_source_blend != old_settings.gpu_disable_dual_source_blend ||
|
||||||
g_settings.gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch ||
|
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
|
// if debug device/threaded presentation change, we need to recreate the whole display
|
||||||
const bool recreate_device =
|
const bool recreate_device =
|
||||||
(g_settings.gpu_use_debug_device != old_settings.gpu_use_debug_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_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_dual_source_blend != old_settings.gpu_disable_dual_source_blend ||
|
||||||
g_settings.gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch ||
|
g_settings.gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch ||
|
||||||
|
|
|
@ -119,8 +119,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||||
&Settings::ParseDisplayRotation, &Settings::GetDisplayRotationName,
|
&Settings::ParseDisplayRotation, &Settings::GetDisplayRotationName,
|
||||||
Settings::DEFAULT_DISPLAY_ROTATION);
|
Settings::DEFAULT_DISPLAY_ROTATION);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.gpuThread, "GPU", "UseThread", true);
|
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",
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableMailboxPresentation, "Display",
|
||||||
"DisableMailboxPresentation", false);
|
"DisableMailboxPresentation", false);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.stretchDisplayVertically, "Display", "StretchVertically",
|
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"),
|
dialog->registerWidgetHelp(m_ui.gpuThread, tr("Threaded Rendering"), tr("Checked"),
|
||||||
tr("Uses a second thread for drawing graphics. Currently only available for the software "
|
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."));
|
"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(
|
dialog->registerWidgetHelp(
|
||||||
m_ui.disableMailboxPresentation, tr("Disable Mailbox Presentation"), tr("Unchecked"),
|
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. "
|
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
|
#endif
|
||||||
|
|
||||||
m_ui.gpuThread->setEnabled(!is_hardware);
|
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 ||
|
m_ui.exclusiveFullscreenLabel->setEnabled(render_api == RenderAPI::D3D11 || render_api == RenderAPI::D3D12 ||
|
||||||
render_api == RenderAPI::Vulkan);
|
render_api == RenderAPI::Vulkan);
|
||||||
|
|
|
@ -341,20 +341,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QCheckBox" name="threadedPresentation">
|
|
||||||
<property name="text">
|
|
||||||
<string>Threaded Presentation</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QCheckBox" name="blitSwapChain">
|
|
||||||
<property name="text">
|
|
||||||
<string>Use Blit Swap Chain</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QCheckBox" name="stretchDisplayVertically">
|
<widget class="QCheckBox" name="stretchDisplayVertically">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -362,6 +348,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QCheckBox" name="blitSwapChain">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use Blit Swap Chain</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
|
|
|
@ -63,9 +63,8 @@ bool D3D11Device::HasSurface() const
|
||||||
return static_cast<bool>(m_swap_chain);
|
return static_cast<bool>(m_swap_chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11Device::CreateDevice(std::string_view adapter, bool threaded_presentation,
|
bool D3D11Device::CreateDevice(std::string_view adapter, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
FeatureMask disabled_features, Error* error)
|
||||||
Error* error)
|
|
||||||
{
|
{
|
||||||
std::unique_lock lock(s_instance_mutex);
|
std::unique_lock lock(s_instance_mutex);
|
||||||
|
|
||||||
|
|
|
@ -112,9 +112,8 @@ public:
|
||||||
void UnbindTexture(D3D11Texture* tex);
|
void UnbindTexture(D3D11Texture* tex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool CreateDevice(std::string_view adapter, bool threaded_presentation,
|
bool CreateDevice(std::string_view adapter, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
FeatureMask disabled_features, Error* error) override;
|
||||||
Error* error) override;
|
|
||||||
void DestroyDevice() override;
|
void DestroyDevice() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -117,9 +117,8 @@ D3D12Device::ComPtr<ID3D12RootSignature> D3D12Device::CreateRootSignature(const
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D12Device::CreateDevice(std::string_view adapter, bool threaded_presentation,
|
bool D3D12Device::CreateDevice(std::string_view adapter, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
FeatureMask disabled_features, Error* error)
|
||||||
Error* error)
|
|
||||||
{
|
{
|
||||||
std::unique_lock lock(s_instance_mutex);
|
std::unique_lock lock(s_instance_mutex);
|
||||||
|
|
||||||
|
|
|
@ -185,9 +185,8 @@ public:
|
||||||
void UnbindTextureBuffer(D3D12TextureBuffer* buf);
|
void UnbindTextureBuffer(D3D12TextureBuffer* buf);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool CreateDevice(std::string_view adapter, bool threaded_presentation,
|
bool CreateDevice(std::string_view adapter, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
FeatureMask disabled_features, Error* error) override;
|
||||||
Error* error) override;
|
|
||||||
void DestroyDevice() override;
|
void DestroyDevice() override;
|
||||||
|
|
||||||
bool ReadPipelineCache(std::optional<DynamicHeapArray<u8>> data) override;
|
bool ReadPipelineCache(std::optional<DynamicHeapArray<u8>> data) override;
|
||||||
|
|
|
@ -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 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<bool> exclusive_fullscreen_control, FeatureMask disabled_features, Error* error)
|
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features, Error* error)
|
||||||
{
|
{
|
||||||
m_vsync_mode = vsync;
|
m_vsync_mode = vsync;
|
||||||
|
@ -360,7 +360,7 @@ bool GPUDevice::Create(std::string_view adapter, std::string_view shader_cache_p
|
||||||
return false;
|
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())
|
if (error && !error->IsValid())
|
||||||
error->SetStringView("Failed to create device.");
|
error->SetStringView("Failed to create device.");
|
||||||
|
|
|
@ -604,8 +604,8 @@ public:
|
||||||
virtual RenderAPI GetRenderAPI() const = 0;
|
virtual RenderAPI GetRenderAPI() const = 0;
|
||||||
|
|
||||||
bool Create(std::string_view adapter, std::string_view shader_cache_path, u32 shader_cache_version, bool debug_device,
|
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,
|
GPUVSyncMode vsync, bool allow_present_throttle, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features, Error* error);
|
FeatureMask disabled_features, Error* error);
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
virtual bool HasSurface() const = 0;
|
virtual bool HasSurface() const = 0;
|
||||||
|
@ -737,9 +737,8 @@ public:
|
||||||
static void ResetStatistics();
|
static void ResetStatistics();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool CreateDevice(std::string_view adapter, bool threaded_presentation,
|
virtual bool CreateDevice(std::string_view adapter, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
FeatureMask disabled_features, Error* error) = 0;
|
||||||
Error* error) = 0;
|
|
||||||
virtual void DestroyDevice() = 0;
|
virtual void DestroyDevice() = 0;
|
||||||
|
|
||||||
std::string GetShaderCacheBaseName(std::string_view type) const;
|
std::string GetShaderCacheBaseName(std::string_view type) const;
|
||||||
|
|
|
@ -287,9 +287,8 @@ public:
|
||||||
static void DeferRelease(u64 fence_counter, id obj);
|
static void DeferRelease(u64 fence_counter, id obj);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool CreateDevice(std::string_view adapter, bool threaded_presentation,
|
bool CreateDevice(std::string_view adapter, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
FeatureMask disabled_features, Error* error) override;
|
||||||
Error* error) override;
|
|
||||||
void DestroyDevice() override;
|
void DestroyDevice() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -161,9 +161,8 @@ void MetalDevice::SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle)
|
||||||
[m_layer setDisplaySyncEnabled:m_vsync_mode == GPUVSyncMode::FIFO];
|
[m_layer setDisplaySyncEnabled:m_vsync_mode == GPUVSyncMode::FIFO];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MetalDevice::CreateDevice(std::string_view adapter, bool threaded_presentation,
|
bool MetalDevice::CreateDevice(std::string_view adapter, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
FeatureMask disabled_features, Error* error)
|
||||||
Error* error)
|
|
||||||
{
|
{
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
|
|
|
@ -281,9 +281,8 @@ bool OpenGLDevice::HasSurface() const
|
||||||
return m_window_info.type != WindowInfo::Type::Surfaceless;
|
return m_window_info.type != WindowInfo::Type::Surfaceless;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLDevice::CreateDevice(std::string_view adapter, bool threaded_presentation,
|
bool OpenGLDevice::CreateDevice(std::string_view adapter, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
FeatureMask disabled_features, Error* error)
|
||||||
Error* error)
|
|
||||||
{
|
{
|
||||||
m_gl_context = OpenGLContext::Create(m_window_info, error);
|
m_gl_context = OpenGLContext::Create(m_window_info, error);
|
||||||
if (!m_gl_context)
|
if (!m_gl_context)
|
||||||
|
|
|
@ -115,12 +115,14 @@ public:
|
||||||
void CommitRTClearInFB(OpenGLTexture* tex, u32 idx);
|
void CommitRTClearInFB(OpenGLTexture* tex, u32 idx);
|
||||||
void CommitDSClearInFB(OpenGLTexture* tex);
|
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);
|
GLuint CompileProgram(const GPUPipeline::GraphicsConfig& plconfig, Error* error);
|
||||||
void PostLinkProgram(const GPUPipeline::GraphicsConfig& plconfig, GLuint program_id);
|
void PostLinkProgram(const GPUPipeline::GraphicsConfig& plconfig, GLuint program_id);
|
||||||
void UnrefProgram(const OpenGLPipeline::ProgramCacheKey& key);
|
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<const GPUPipeline::VertexAttribute> attributes, u32 stride, Error* error);
|
GLuint CreateVAO(std::span<const GPUPipeline::VertexAttribute> attributes, u32 stride, Error* error);
|
||||||
void UnrefVAO(const OpenGLPipeline::VertexArrayCacheKey& key);
|
void UnrefVAO(const OpenGLPipeline::VertexArrayCacheKey& key);
|
||||||
|
|
||||||
|
@ -132,9 +134,8 @@ public:
|
||||||
void UnbindPipeline(const OpenGLPipeline* pl);
|
void UnbindPipeline(const OpenGLPipeline* pl);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool CreateDevice(std::string_view adapter, bool threaded_presentation,
|
bool CreateDevice(std::string_view adapter, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
FeatureMask disabled_features, Error* error) override;
|
||||||
Error* error) override;
|
|
||||||
void DestroyDevice() override;
|
void DestroyDevice() override;
|
||||||
|
|
||||||
bool OpenPipelineCache(const std::string& filename) override;
|
bool OpenPipelineCache(const std::string& filename) override;
|
||||||
|
|
|
@ -1268,7 +1268,6 @@ void VulkanDevice::WaitForFenceCounter(u64 fence_counter)
|
||||||
|
|
||||||
void VulkanDevice::WaitForGPUIdle()
|
void VulkanDevice::WaitForGPUIdle()
|
||||||
{
|
{
|
||||||
WaitForPresentComplete();
|
|
||||||
vkDeviceWaitIdle(m_device);
|
vkDeviceWaitIdle(m_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1287,13 +1286,6 @@ bool VulkanDevice::SetGPUTimingEnabled(bool enabled)
|
||||||
|
|
||||||
void VulkanDevice::WaitForCommandBufferCompletion(u32 index)
|
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.
|
// Wait for this command buffer to be completed.
|
||||||
static constexpr u32 MAX_TIMEOUTS = 10;
|
static constexpr u32 MAX_TIMEOUTS = 10;
|
||||||
u32 timeouts = 0;
|
u32 timeouts = 0;
|
||||||
|
@ -1311,7 +1303,7 @@ void VulkanDevice::WaitForCommandBufferCompletion(u32 index)
|
||||||
else if (res != VK_SUCCESS)
|
else if (res != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
LOG_VULKAN_ERROR(res, TinyString::from_format("vkWaitForFences() for cmdbuffer {} failed: ", index));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1363,10 +1355,9 @@ void VulkanDevice::WaitForCommandBufferCompletion(u32 index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDevice::EndAndSubmitCommandBuffer(VulkanSwapChain* present_swap_chain, bool explicit_present,
|
void VulkanDevice::EndAndSubmitCommandBuffer(VulkanSwapChain* present_swap_chain, bool explicit_present)
|
||||||
bool submit_on_thread)
|
|
||||||
{
|
{
|
||||||
if (m_last_submit_failed.load(std::memory_order_acquire))
|
if (m_device_is_lost)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CommandBuffer& resources = m_frame_resources[m_current_frame];
|
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.
|
// This command buffer now has commands, so can't be re-used without waiting.
|
||||||
resources.needs_fence_wait = true;
|
resources.needs_fence_wait = true;
|
||||||
|
|
||||||
std::unique_lock<std::mutex> 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;
|
uint32_t wait_bits = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
VkSubmitInfo submit_info = {VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
VkSubmitInfo submit_info = {VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1442,16 +1412,19 @@ void VulkanDevice::DoSubmitCommandBuffer(u32 index, VulkanSwapChain* present_swa
|
||||||
submit_info.signalSemaphoreCount = 1;
|
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)
|
if (res != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
LOG_VULKAN_ERROR(res, "vkQueueSubmit failed: ");
|
LOG_VULKAN_ERROR(res, "vkQueueSubmit failed: ");
|
||||||
m_last_submit_failed.store(true, std::memory_order_release);
|
m_device_is_lost = true;
|
||||||
return;
|
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,
|
const VkPresentInfoKHR present_info = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1482,65 +1455,6 @@ void VulkanDevice::DoPresent(VulkanSwapChain* present_swap_chain)
|
||||||
present_swap_chain->AcquireNextImage();
|
present_swap_chain->AcquireNextImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDevice::WaitForPresentComplete()
|
|
||||||
{
|
|
||||||
if (m_present_done.load(std::memory_order_acquire))
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(m_present_mutex);
|
|
||||||
WaitForPresentComplete(lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanDevice::WaitForPresentComplete(std::unique_lock<std::mutex>& 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<std::mutex> 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<std::mutex> 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()
|
void VulkanDevice::MoveToNextCommandBuffer()
|
||||||
{
|
{
|
||||||
BeginCommandBuffer((m_current_frame + 1) % NUM_COMMAND_BUFFERS);
|
BeginCommandBuffer((m_current_frame + 1) % NUM_COMMAND_BUFFERS);
|
||||||
|
@ -1602,7 +1516,7 @@ void VulkanDevice::SubmitCommandBuffer(bool wait_for_completion)
|
||||||
DebugAssert(!InRenderPass());
|
DebugAssert(!InRenderPass());
|
||||||
|
|
||||||
const u32 current_frame = m_current_frame;
|
const u32 current_frame = m_current_frame;
|
||||||
EndAndSubmitCommandBuffer(nullptr, false, false);
|
EndAndSubmitCommandBuffer(nullptr, false);
|
||||||
MoveToNextCommandBuffer();
|
MoveToNextCommandBuffer();
|
||||||
|
|
||||||
if (wait_for_completion)
|
if (wait_for_completion)
|
||||||
|
@ -1629,11 +1543,6 @@ void VulkanDevice::SubmitCommandBufferAndRestartRenderPass(const std::string_vie
|
||||||
BeginRenderPass();
|
BeginRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanDevice::CheckLastSubmitFail()
|
|
||||||
{
|
|
||||||
return m_last_submit_failed.load(std::memory_order_acquire);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanDevice::DeferBufferDestruction(VkBuffer object, VmaAllocation allocation)
|
void VulkanDevice::DeferBufferDestruction(VkBuffer object, VmaAllocation allocation)
|
||||||
{
|
{
|
||||||
m_cleanup_objects.emplace_back(GetCurrentFenceCounter(),
|
m_cleanup_objects.emplace_back(GetCurrentFenceCounter(),
|
||||||
|
@ -1987,9 +1896,8 @@ bool VulkanDevice::HasSurface() const
|
||||||
return static_cast<bool>(m_swap_chain);
|
return static_cast<bool>(m_swap_chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanDevice::CreateDevice(std::string_view adapter, bool threaded_presentation,
|
bool VulkanDevice::CreateDevice(std::string_view adapter, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
FeatureMask disabled_features, Error* error)
|
||||||
Error* error)
|
|
||||||
{
|
{
|
||||||
std::unique_lock lock(s_instance_mutex);
|
std::unique_lock lock(s_instance_mutex);
|
||||||
bool enable_debug_utils = m_debug_device;
|
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())
|
if (!CreateAllocator() || !CreatePersistentDescriptorPool() || !CreateCommandBuffers() || !CreatePipelineLayouts())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (threaded_presentation)
|
|
||||||
StartPresentThread();
|
|
||||||
|
|
||||||
m_exclusive_fullscreen_control = exclusive_fullscreen_control;
|
m_exclusive_fullscreen_control = exclusive_fullscreen_control;
|
||||||
|
|
||||||
if (surface != VK_NULL_HANDLE)
|
if (surface != VK_NULL_HANDLE)
|
||||||
|
@ -2148,7 +2053,6 @@ void VulkanDevice::DestroyDevice()
|
||||||
if (m_device != VK_NULL_HANDLE)
|
if (m_device != VK_NULL_HANDLE)
|
||||||
WaitForGPUIdle();
|
WaitForGPUIdle();
|
||||||
|
|
||||||
StopPresentThread();
|
|
||||||
m_swap_chain.reset();
|
m_swap_chain.reset();
|
||||||
|
|
||||||
if (m_null_texture)
|
if (m_null_texture)
|
||||||
|
@ -2451,11 +2355,8 @@ bool VulkanDevice::BeginPresent(bool frame_skip, u32 clear_color)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Previous frame needs to be presented before we can acquire the swap chain.
|
|
||||||
WaitForPresentComplete();
|
|
||||||
|
|
||||||
// Check if the device was lost.
|
// Check if the device was lost.
|
||||||
if (CheckLastSubmitFail())
|
if (m_device_is_lost)
|
||||||
{
|
{
|
||||||
Panic("Fixme"); // TODO
|
Panic("Fixme"); // TODO
|
||||||
TrimTexturePool();
|
TrimTexturePool();
|
||||||
|
@ -2511,7 +2412,7 @@ void VulkanDevice::EndPresent(bool explicit_present)
|
||||||
VulkanTexture::TransitionSubresourcesToLayout(cmdbuf, m_swap_chain->GetCurrentImage(), GPUTexture::Type::RenderTarget,
|
VulkanTexture::TransitionSubresourcesToLayout(cmdbuf, m_swap_chain->GetCurrentImage(), GPUTexture::Type::RenderTarget,
|
||||||
0, 1, 0, 1, VulkanTexture::Layout::ColorAttachment,
|
0, 1, 0, 1, VulkanTexture::Layout::ColorAttachment,
|
||||||
VulkanTexture::Layout::PresentSrc);
|
VulkanTexture::Layout::PresentSrc);
|
||||||
EndAndSubmitCommandBuffer(m_swap_chain.get(), explicit_present, !m_swap_chain->IsPresentModeSynchronizing());
|
EndAndSubmitCommandBuffer(m_swap_chain.get(), explicit_present);
|
||||||
MoveToNextCommandBuffer();
|
MoveToNextCommandBuffer();
|
||||||
InvalidateCachedState();
|
InvalidateCachedState();
|
||||||
TrimTexturePool();
|
TrimTexturePool();
|
||||||
|
@ -2520,7 +2421,7 @@ void VulkanDevice::EndPresent(bool explicit_present)
|
||||||
void VulkanDevice::SubmitPresent()
|
void VulkanDevice::SubmitPresent()
|
||||||
{
|
{
|
||||||
DebugAssert(m_swap_chain);
|
DebugAssert(m_swap_chain);
|
||||||
DoPresent(m_swap_chain.get());
|
QueuePresent(m_swap_chain.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
@ -3185,7 +3086,7 @@ void VulkanDevice::RenderBlankFrame()
|
||||||
VulkanTexture::TransitionSubresourcesToLayout(cmdbuf, image, GPUTexture::Type::RenderTarget, 0, 1, 0, 1,
|
VulkanTexture::TransitionSubresourcesToLayout(cmdbuf, image, GPUTexture::Type::RenderTarget, 0, 1, 0, 1,
|
||||||
VulkanTexture::Layout::TransferDst, VulkanTexture::Layout::PresentSrc);
|
VulkanTexture::Layout::TransferDst, VulkanTexture::Layout::PresentSrc);
|
||||||
|
|
||||||
EndAndSubmitCommandBuffer(m_swap_chain.get(), false, !m_swap_chain->IsPresentModeSynchronizing());
|
EndAndSubmitCommandBuffer(m_swap_chain.get(), false);
|
||||||
MoveToNextCommandBuffer();
|
MoveToNextCommandBuffer();
|
||||||
|
|
||||||
InvalidateCachedState();
|
InvalidateCachedState();
|
||||||
|
|
|
@ -17,9 +17,7 @@
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -234,9 +232,8 @@ public:
|
||||||
void UnbindTextureBuffer(VulkanTextureBuffer* buf);
|
void UnbindTextureBuffer(VulkanTextureBuffer* buf);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool CreateDevice(std::string_view adapter, bool threaded_presentation,
|
bool CreateDevice(std::string_view adapter, std::optional<bool> exclusive_fullscreen_control,
|
||||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
FeatureMask disabled_features, Error* error) override;
|
||||||
Error* error) override;
|
|
||||||
void DestroyDevice() override;
|
void DestroyDevice() override;
|
||||||
|
|
||||||
bool ReadPipelineCache(std::optional<DynamicHeapArray<u8>> data) override;
|
bool ReadPipelineCache(std::optional<DynamicHeapArray<u8>> data) override;
|
||||||
|
@ -329,11 +326,6 @@ private:
|
||||||
bool IsDeviceImgTec() const;
|
bool IsDeviceImgTec() const;
|
||||||
bool IsBrokenMobileDriver() 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<const char*>;
|
using ExtensionList = std::vector<const char*>;
|
||||||
static bool SelectInstanceExtensions(ExtensionList* extension_list, const WindowInfo& wi, OptionalExtensions* oe,
|
static bool SelectInstanceExtensions(ExtensionList* extension_list, const WindowInfo& wi, OptionalExtensions* oe,
|
||||||
bool enable_debug_utils);
|
bool enable_debug_utils);
|
||||||
|
@ -395,13 +387,9 @@ private:
|
||||||
|
|
||||||
void BeginCommandBuffer(u32 index);
|
void BeginCommandBuffer(u32 index);
|
||||||
void WaitForCommandBufferCompletion(u32 index);
|
void WaitForCommandBufferCompletion(u32 index);
|
||||||
|
void EndAndSubmitCommandBuffer(VulkanSwapChain* present_swap_chain, bool explicit_present);
|
||||||
void DoSubmitCommandBuffer(u32 index, VulkanSwapChain* present_swap_chain);
|
void MoveToNextCommandBuffer();
|
||||||
void DoPresent(VulkanSwapChain* present_swap_chain);
|
void QueuePresent(VulkanSwapChain* present_swap_chain);
|
||||||
void WaitForPresentComplete(std::unique_lock<std::mutex>& lock);
|
|
||||||
void PresentThread();
|
|
||||||
void StartPresentThread();
|
|
||||||
void StopPresentThread();
|
|
||||||
|
|
||||||
VkInstance m_instance = VK_NULL_HANDLE;
|
VkInstance m_instance = VK_NULL_HANDLE;
|
||||||
VkPhysicalDevice m_physical_device = VK_NULL_HANDLE;
|
VkPhysicalDevice m_physical_device = VK_NULL_HANDLE;
|
||||||
|
@ -426,21 +414,7 @@ private:
|
||||||
u64 m_completed_fence_counter = 0;
|
u64 m_completed_fence_counter = 0;
|
||||||
u32 m_current_frame = 0;
|
u32 m_current_frame = 0;
|
||||||
|
|
||||||
std::atomic_bool m_last_submit_failed{false};
|
bool m_device_is_lost = 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};
|
|
||||||
|
|
||||||
std::unordered_map<RenderPassCacheKey, VkRenderPass, RenderPassCacheKeyHash> m_render_pass_cache;
|
std::unordered_map<RenderPassCacheKey, VkRenderPass, RenderPassCacheKeyHash> m_render_pass_cache;
|
||||||
GPUFramebufferManager<VkFramebuffer, CreateFramebuffer, DestroyFramebuffer> m_framebuffer_manager;
|
GPUFramebufferManager<VkFramebuffer, CreateFramebuffer, DestroyFramebuffer> m_framebuffer_manager;
|
||||||
|
|
|
@ -69,10 +69,6 @@ public:
|
||||||
return &m_semaphores[m_current_semaphore].rendering_finished_semaphore;
|
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();
|
VkResult AcquireNextImage();
|
||||||
void ReleaseCurrentImage();
|
void ReleaseCurrentImage();
|
||||||
void ResetImageAcquireResult();
|
void ResetImageAcquireResult();
|
||||||
|
|
Loading…
Reference in a new issue