mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-30 01:25:51 +00:00
Settings: Expose exclusive fullscreen control
This commit is contained in:
parent
46e0afd2d4
commit
62d2f12236
|
@ -241,6 +241,13 @@ bool Host::CreateGPUDevice(RenderAPI api)
|
|||
Log_InfoPrintf("Trying to create a %s GPU device...", GPUDevice::RenderAPIToString(api));
|
||||
g_gpu_device = GPUDevice::CreateDeviceForAPI(api);
|
||||
|
||||
std::optional<bool> exclusive_fullscreen_control;
|
||||
if (g_settings.display_exclusive_fullscreen_control != DisplayExclusiveFullscreenControl::Automatic)
|
||||
{
|
||||
exclusive_fullscreen_control =
|
||||
(g_settings.display_exclusive_fullscreen_control == DisplayExclusiveFullscreenControl::Allowed);
|
||||
}
|
||||
|
||||
u32 disabled_features = 0;
|
||||
if (g_settings.gpu_disable_dual_source_blend)
|
||||
disabled_features |= GPUDevice::FEATURE_MASK_DUAL_SOURCE_BLEND;
|
||||
|
@ -249,11 +256,12 @@ bool Host::CreateGPUDevice(RenderAPI api)
|
|||
|
||||
// TODO: FSUI should always use vsync..
|
||||
const bool vsync = System::IsValid() ? System::ShouldUseVSync() : g_settings.video_sync_enabled;
|
||||
if (!g_gpu_device || !g_gpu_device->Create(
|
||||
g_settings.gpu_adapter,
|
||||
g_settings.gpu_disable_shader_cache ? std::string_view() : std::string_view(EmuFolders::Cache),
|
||||
if (!g_gpu_device || !g_gpu_device->Create(g_settings.gpu_adapter,
|
||||
g_settings.gpu_disable_shader_cache ? std::string_view() :
|
||||
std::string_view(EmuFolders::Cache),
|
||||
SHADER_CACHE_VERSION, g_settings.gpu_use_debug_device, vsync,
|
||||
g_settings.gpu_threaded_presentation, static_cast<GPUDevice::FeatureMask>(disabled_features)))
|
||||
g_settings.gpu_threaded_presentation, exclusive_fullscreen_control,
|
||||
static_cast<GPUDevice::FeatureMask>(disabled_features)))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create GPU device.");
|
||||
if (g_gpu_device)
|
||||
|
|
|
@ -236,6 +236,12 @@ void Settings::Load(SettingsInterface& si)
|
|||
display_scaling =
|
||||
ParseDisplayScaling(si.GetStringValue("Display", "Scaling", GetDisplayScalingName(DEFAULT_DISPLAY_SCALING)).c_str())
|
||||
.value_or(DEFAULT_DISPLAY_SCALING);
|
||||
display_exclusive_fullscreen_control =
|
||||
ParseDisplayExclusiveFullscreenControl(
|
||||
si.GetStringValue("Display", "ExclusiveFullscreenControl",
|
||||
GetDisplayExclusiveFullscreenControlName(DEFAULT_DISPLAY_EXCLUSIVE_FULLSCREEN_CONTROL))
|
||||
.c_str())
|
||||
.value_or(DEFAULT_DISPLAY_EXCLUSIVE_FULLSCREEN_CONTROL);
|
||||
display_force_4_3_for_24bit = si.GetBoolValue("Display", "Force4_3For24Bit", false);
|
||||
display_active_start_offset = static_cast<s16>(si.GetIntValue("Display", "ActiveStartOffset", 0));
|
||||
display_active_end_offset = static_cast<s16>(si.GetIntValue("Display", "ActiveEndOffset", 0));
|
||||
|
@ -475,6 +481,8 @@ void Settings::Save(SettingsInterface& si) const
|
|||
si.SetStringValue("Display", "AspectRatio", GetDisplayAspectRatioName(display_aspect_ratio));
|
||||
si.SetStringValue("Display", "Alignment", GetDisplayAlignmentName(display_alignment));
|
||||
si.SetStringValue("Display", "Scaling", GetDisplayScalingName(display_scaling));
|
||||
si.SetStringValue("Display", "ExclusiveFullscreenControl",
|
||||
GetDisplayExclusiveFullscreenControlName(display_exclusive_fullscreen_control));
|
||||
si.SetIntValue("Display", "CustomAspectRatioNumerator", display_aspect_ratio_custom_numerator);
|
||||
si.GetIntValue("Display", "CustomAspectRatioDenominator", display_aspect_ratio_custom_denominator);
|
||||
si.SetBoolValue("Display", "ShowOSDMessages", display_show_osd_messages);
|
||||
|
@ -1238,6 +1246,42 @@ const char* Settings::GetDisplayScalingDisplayName(DisplayScalingMode mode)
|
|||
return Host::TranslateToCString("DisplayScalingMode", s_display_scaling_display_names[static_cast<int>(mode)]);
|
||||
}
|
||||
|
||||
static constexpr const std::array s_display_exclusive_fullscreen_mode_names = {
|
||||
"Automatic",
|
||||
"Disallowed",
|
||||
"Allowed",
|
||||
};
|
||||
static constexpr const std::array s_display_exclusive_fullscreen_mode_display_names = {
|
||||
TRANSLATE_NOOP("Settings", "Automatic (Default)"),
|
||||
TRANSLATE_NOOP("Settings", "Disallowed"),
|
||||
TRANSLATE_NOOP("Settings", "Allowed"),
|
||||
};
|
||||
|
||||
std::optional<DisplayExclusiveFullscreenControl> Settings::ParseDisplayExclusiveFullscreenControl(const char* str)
|
||||
{
|
||||
int index = 0;
|
||||
for (const char* name : s_display_exclusive_fullscreen_mode_names)
|
||||
{
|
||||
if (StringUtil::Strcasecmp(name, str) == 0)
|
||||
return static_cast<DisplayExclusiveFullscreenControl>(index);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const char* Settings::GetDisplayExclusiveFullscreenControlName(DisplayExclusiveFullscreenControl mode)
|
||||
{
|
||||
return s_display_exclusive_fullscreen_mode_names[static_cast<int>(mode)];
|
||||
}
|
||||
|
||||
const char* Settings::GetDisplayExclusiveFullscreenControlDisplayName(DisplayExclusiveFullscreenControl mode)
|
||||
{
|
||||
return Host::TranslateToCString("Settings",
|
||||
s_display_exclusive_fullscreen_mode_display_names[static_cast<int>(mode)]);
|
||||
}
|
||||
|
||||
static constexpr const std::array s_audio_backend_names = {
|
||||
"Null",
|
||||
#ifdef ENABLE_CUBEB
|
||||
|
|
|
@ -124,6 +124,7 @@ struct Settings
|
|||
DisplayAspectRatio display_aspect_ratio = DEFAULT_DISPLAY_ASPECT_RATIO;
|
||||
DisplayAlignment display_alignment = DEFAULT_DISPLAY_ALIGNMENT;
|
||||
DisplayScalingMode display_scaling = DEFAULT_DISPLAY_SCALING;
|
||||
DisplayExclusiveFullscreenControl display_exclusive_fullscreen_control = DEFAULT_DISPLAY_EXCLUSIVE_FULLSCREEN_CONTROL;
|
||||
u16 display_aspect_ratio_custom_numerator = 0;
|
||||
u16 display_aspect_ratio_custom_denominator = 0;
|
||||
s16 display_active_start_offset = 0;
|
||||
|
@ -391,6 +392,10 @@ struct Settings
|
|||
static const char* GetDisplayScalingName(DisplayScalingMode mode);
|
||||
static const char* GetDisplayScalingDisplayName(DisplayScalingMode mode);
|
||||
|
||||
static std::optional<DisplayExclusiveFullscreenControl> ParseDisplayExclusiveFullscreenControl(const char* str);
|
||||
static const char* GetDisplayExclusiveFullscreenControlName(DisplayExclusiveFullscreenControl mode);
|
||||
static const char* GetDisplayExclusiveFullscreenControlDisplayName(DisplayExclusiveFullscreenControl mode);
|
||||
|
||||
static std::optional<AudioBackend> ParseAudioBackend(const char* str);
|
||||
static const char* GetAudioBackendName(AudioBackend backend);
|
||||
static const char* GetAudioBackendDisplayName(AudioBackend backend);
|
||||
|
@ -450,6 +455,8 @@ struct Settings
|
|||
static constexpr DisplayAspectRatio DEFAULT_DISPLAY_ASPECT_RATIO = DisplayAspectRatio::Auto;
|
||||
static constexpr DisplayAlignment DEFAULT_DISPLAY_ALIGNMENT = DisplayAlignment::Center;
|
||||
static constexpr DisplayScalingMode DEFAULT_DISPLAY_SCALING = DisplayScalingMode::BilinearSmooth;
|
||||
static constexpr DisplayExclusiveFullscreenControl DEFAULT_DISPLAY_EXCLUSIVE_FULLSCREEN_CONTROL =
|
||||
DisplayExclusiveFullscreenControl::Automatic;
|
||||
static constexpr float DEFAULT_OSD_SCALE = 100.0f;
|
||||
|
||||
static constexpr u8 DEFAULT_CDROM_READAHEAD_SECTORS = 8;
|
||||
|
|
|
@ -3509,12 +3509,14 @@ void System::SetCheatList(std::unique_ptr<CheatList> cheats)
|
|||
|
||||
void System::CheckForSettingsChanges(const Settings& old_settings)
|
||||
{
|
||||
if (IsValid() && (g_settings.gpu_renderer != old_settings.gpu_renderer ||
|
||||
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))
|
||||
g_settings.gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch ||
|
||||
g_settings.display_exclusive_fullscreen_control != old_settings.display_exclusive_fullscreen_control))
|
||||
{
|
||||
// if debug device/threaded presentation change, we need to recreate the whole display
|
||||
const bool recreate_device =
|
||||
|
@ -3522,7 +3524,8 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
|||
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);
|
||||
g_settings.gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch ||
|
||||
g_settings.display_exclusive_fullscreen_control != old_settings.display_exclusive_fullscreen_control);
|
||||
|
||||
Host::AddIconOSDMessage("RendererSwitch", ICON_FA_PAINT_ROLLER,
|
||||
fmt::format(TRANSLATE_FS("OSDMessage", "Switching to {}{} GPU renderer."),
|
||||
|
|
|
@ -143,6 +143,14 @@ enum class DisplayScalingMode : u8
|
|||
Count
|
||||
};
|
||||
|
||||
enum class DisplayExclusiveFullscreenControl : u8
|
||||
{
|
||||
Automatic,
|
||||
Disallowed,
|
||||
Allowed,
|
||||
Count
|
||||
};
|
||||
|
||||
enum class AudioBackend : u8
|
||||
{
|
||||
Null,
|
||||
|
|
|
@ -276,6 +276,11 @@ void AdvancedSettingsWidget::addTweakOptions()
|
|||
addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Apply Compatibility Settings"), "Main",
|
||||
"ApplyCompatibilitySettings", true);
|
||||
addIntRangeTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Display FPS Limit"), "Display", "MaxFPS", 0, 1000, 0);
|
||||
addChoiceTweakOption(
|
||||
m_dialog, m_ui.tweakOptionTable, tr("Exclusive Fullscreen Control"), "Display", "ExclusiveFullscreenControl",
|
||||
&Settings::ParseDisplayExclusiveFullscreenControl, &Settings::GetDisplayExclusiveFullscreenControlName,
|
||||
&Settings::GetDisplayExclusiveFullscreenControlDisplayName,
|
||||
static_cast<u32>(DisplayExclusiveFullscreenControl::Count), Settings::DEFAULT_DISPLAY_EXCLUSIVE_FULLSCREEN_CONTROL);
|
||||
|
||||
addMSAATweakOption(m_dialog, m_ui.tweakOptionTable, tr("Multisample Antialiasing"));
|
||||
|
||||
|
@ -377,6 +382,7 @@ void AdvancedSettingsWidget::onResetToDefaultClicked()
|
|||
setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Show frame times
|
||||
setBooleanTweakOption(m_ui.tweakOptionTable, i++, true); // Apply compatibility settings
|
||||
setIntRangeTweakOption(m_ui.tweakOptionTable, i++, 0); // Display FPS limit
|
||||
setChoiceTweakOption(m_ui.tweakOptionTable, i++, Settings::DEFAULT_DISPLAY_EXCLUSIVE_FULLSCREEN_CONTROL);
|
||||
setChoiceTweakOption(m_ui.tweakOptionTable, i++, 0); // Multisample antialiasing
|
||||
setChoiceTweakOption(m_ui.tweakOptionTable, i++, 0); // Wireframe mode
|
||||
setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // PGXP vertex cache
|
||||
|
@ -433,6 +439,7 @@ void AdvancedSettingsWidget::onResetToDefaultClicked()
|
|||
sif->DeleteValue("Display", "LineStartOffset");
|
||||
sif->DeleteValue("Display", "LineEndOffset");
|
||||
sif->DeleteValue("Display", "StretchVertically");
|
||||
sif->DeleteValue("Display", "ExclusiveFullscreenControl");
|
||||
sif->DeleteValue("GPU", "Multisamples");
|
||||
sif->DeleteValue("GPU", "PerSampleShading");
|
||||
sif->DeleteValue("GPU", "PGXPVertexCache");
|
||||
|
|
|
@ -64,7 +64,7 @@ bool D3D11Device::HasSurface() const
|
|||
}
|
||||
|
||||
bool D3D11Device::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
FeatureMask disabled_features)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features)
|
||||
{
|
||||
std::unique_lock lock(s_instance_mutex);
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ public:
|
|||
|
||||
protected:
|
||||
bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
FeatureMask disabled_features) override;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) override;
|
||||
void DestroyDevice() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -117,7 +117,7 @@ D3D12Device::ComPtr<ID3D12RootSignature> D3D12Device::CreateRootSignature(const
|
|||
}
|
||||
|
||||
bool D3D12Device::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
FeatureMask disabled_features)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features)
|
||||
{
|
||||
std::unique_lock lock(s_instance_mutex);
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ public:
|
|||
|
||||
protected:
|
||||
bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
FeatureMask disabled_features) override;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) override;
|
||||
void DestroyDevice() override;
|
||||
|
||||
bool ReadPipelineCache(const std::string& filename) override;
|
||||
|
|
|
@ -258,7 +258,7 @@ bool GPUDevice::IsSameRenderAPI(RenderAPI lhs, RenderAPI rhs)
|
|||
|
||||
bool GPUDevice::Create(const std::string_view& adapter, const std::string_view& shader_cache_path,
|
||||
u32 shader_cache_version, bool debug_device, bool vsync, bool threaded_presentation,
|
||||
FeatureMask disabled_features)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features)
|
||||
{
|
||||
m_vsync_enabled = vsync;
|
||||
m_debug_device = debug_device;
|
||||
|
@ -269,7 +269,7 @@ bool GPUDevice::Create(const std::string_view& adapter, const std::string_view&
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!CreateDevice(adapter, threaded_presentation, disabled_features))
|
||||
if (!CreateDevice(adapter, threaded_presentation, exclusive_fullscreen_control, disabled_features))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create device.");
|
||||
return false;
|
||||
|
|
|
@ -536,7 +536,8 @@ public:
|
|||
virtual RenderAPI GetRenderAPI() const = 0;
|
||||
|
||||
bool Create(const std::string_view& adapter, const std::string_view& shader_cache_path, u32 shader_cache_version,
|
||||
bool debug_device, bool vsync, bool threaded_presentation, FeatureMask disabled_features);
|
||||
bool debug_device, bool vsync, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features);
|
||||
void Destroy();
|
||||
|
||||
virtual bool HasSurface() const = 0;
|
||||
|
@ -651,7 +652,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
FeatureMask disabled_features) = 0;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) = 0;
|
||||
virtual void DestroyDevice() = 0;
|
||||
|
||||
std::string GetShaderCacheBaseName(const std::string_view& type) const;
|
||||
|
@ -775,7 +776,8 @@ struct GLAutoPop
|
|||
#define GL_INS(msg) g_gpu_device->InsertDebugMessage(msg)
|
||||
#define GL_OBJECT_NAME(obj, name) (obj)->SetDebugName(name)
|
||||
|
||||
#define GL_SCOPE_FMT(...) GLAutoPop gl_auto_pop((g_gpu_device->PushDebugGroup(SmallString::from_format(__VA_ARGS__)), 0))
|
||||
#define GL_SCOPE_FMT(...) \
|
||||
GLAutoPop gl_auto_pop((g_gpu_device->PushDebugGroup(SmallString::from_format(__VA_ARGS__)), 0))
|
||||
#define GL_PUSH_FMT(...) g_gpu_device->PushDebugGroup(SmallString::from_format(__VA_ARGS__))
|
||||
#define GL_INS_FMT(...) g_gpu_device->InsertDebugMessage(SmallString::from_format(__VA_ARGS__))
|
||||
#define GL_OBJECT_NAME_FMT(obj, ...) (obj)->SetDebugName(SmallString::from_format(__VA_ARGS__))
|
||||
|
|
|
@ -257,7 +257,7 @@ public:
|
|||
|
||||
protected:
|
||||
bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
FeatureMask disabled_features) override;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) override;
|
||||
void DestroyDevice() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -121,6 +121,7 @@ void MetalDevice::SetVSync(bool enabled)
|
|||
}
|
||||
|
||||
bool MetalDevice::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control,
|
||||
FeatureMask disabled_features)
|
||||
{
|
||||
@autoreleasepool
|
||||
|
|
|
@ -307,7 +307,7 @@ bool OpenGLDevice::HasSurface() const
|
|||
}
|
||||
|
||||
bool OpenGLDevice::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
FeatureMask disabled_features)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features)
|
||||
{
|
||||
m_gl_context = GL::Context::Create(m_window_info);
|
||||
if (!m_gl_context)
|
||||
|
|
|
@ -120,7 +120,7 @@ public:
|
|||
|
||||
protected:
|
||||
bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
FeatureMask disabled_features) override;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) override;
|
||||
void DestroyDevice() override;
|
||||
|
||||
bool ReadPipelineCache(const std::string& filename) override;
|
||||
|
|
|
@ -1836,12 +1836,11 @@ bool VulkanDevice::HasSurface() const
|
|||
}
|
||||
|
||||
bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
FeatureMask disabled_features)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features)
|
||||
{
|
||||
std::unique_lock lock(s_instance_mutex);
|
||||
bool enable_debug_utils = m_debug_device;
|
||||
bool enable_validation_layer = m_debug_device;
|
||||
std::optional<bool> exclusive_fullscreen_control;
|
||||
|
||||
if (!Vulkan::LoadVulkanLibrary())
|
||||
{
|
||||
|
@ -1953,9 +1952,11 @@ bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_p
|
|||
if (threaded_presentation)
|
||||
StartPresentThread();
|
||||
|
||||
m_exclusive_fullscreen_control = exclusive_fullscreen_control;
|
||||
|
||||
if (surface != VK_NULL_HANDLE)
|
||||
{
|
||||
m_swap_chain = VulkanSwapChain::Create(m_window_info, surface, m_vsync_enabled, exclusive_fullscreen_control);
|
||||
m_swap_chain = VulkanSwapChain::Create(m_window_info, surface, m_vsync_enabled, m_exclusive_fullscreen_control);
|
||||
if (!m_swap_chain)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create swap chain");
|
||||
|
@ -2174,8 +2175,7 @@ bool VulkanDevice::UpdateWindow()
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: exclusive fullscreen control
|
||||
m_swap_chain = VulkanSwapChain::Create(m_window_info, surface, m_vsync_enabled, std::nullopt);
|
||||
m_swap_chain = VulkanSwapChain::Create(m_window_info, surface, m_vsync_enabled, m_exclusive_fullscreen_control);
|
||||
if (!m_swap_chain)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create swap chain");
|
||||
|
|
|
@ -218,7 +218,7 @@ public:
|
|||
|
||||
protected:
|
||||
bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
FeatureMask disabled_features) override;
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features) override;
|
||||
void DestroyDevice() override;
|
||||
|
||||
bool ReadPipelineCache(const std::string& filename) override;
|
||||
|
@ -428,6 +428,7 @@ private:
|
|||
VkPhysicalDeviceProperties m_device_properties = {};
|
||||
VkPhysicalDeviceDriverPropertiesKHR m_device_driver_properties = {};
|
||||
OptionalExtensions m_optional_extensions = {};
|
||||
std::optional<bool> m_exclusive_fullscreen_control;
|
||||
|
||||
std::unique_ptr<VulkanSwapChain> m_swap_chain;
|
||||
std::unique_ptr<VulkanTexture> m_null_texture;
|
||||
|
|
Loading…
Reference in a new issue