diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index 9865444e1..dfd538c35 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -6640,6 +6640,11 @@ void FullscreenUI::DrawAdvancedSettingsPage() FSUI_VSTR("Enable GPU-based validation when supported by the host's renderer API. Only for developer use."), "GPU", "UseGPUBasedValidation", false); + DrawToggleSetting( + bsi, FSUI_VSTR("Prefer OpenGL ES Device"), + FSUI_VSTR("Uses OpenGL ES even when desktop OpenGL is supported. May improve performance on some SBC drivers."), + "GPU", "PreferGLESContext", Settings::DEFAULT_GPU_PREFER_GLES_CONTEXT); + DrawToggleSetting( bsi, FSUI_VSTR("Load Devices From Save States"), FSUI_VSTR("When enabled, memory cards and controllers will be overwritten when save states are loaded."), "Main", @@ -9870,6 +9875,7 @@ TRANSLATE_NOOP("FullscreenUI", "Port {} Controller Type"); TRANSLATE_NOOP("FullscreenUI", "Post-Processing Settings"); TRANSLATE_NOOP("FullscreenUI", "Post-processing chain cleared."); TRANSLATE_NOOP("FullscreenUI", "Post-processing shaders reloaded."); +TRANSLATE_NOOP("FullscreenUI", "Prefer OpenGL ES Device"); TRANSLATE_NOOP("FullscreenUI", "Preload Images to RAM"); TRANSLATE_NOOP("FullscreenUI", "Preload Replacement Textures"); TRANSLATE_NOOP("FullscreenUI", "Preserve Projection Precision"); @@ -10115,6 +10121,7 @@ TRANSLATE_NOOP("FullscreenUI", "Use Separate Disc Settings"); TRANSLATE_NOOP("FullscreenUI", "Use Single Card For Multi-Disc Games"); TRANSLATE_NOOP("FullscreenUI", "Use Software Renderer For Readbacks"); TRANSLATE_NOOP("FullscreenUI", "User Name"); +TRANSLATE_NOOP("FullscreenUI", "Uses OpenGL ES even when desktop OpenGL is supported. May improve performance on some SBC drivers."); TRANSLATE_NOOP("FullscreenUI", "Uses PGXP for all instructions, not just memory operations."); TRANSLATE_NOOP("FullscreenUI", "Uses a blit presentation model instead of flipping. This may be needed on some systems."); TRANSLATE_NOOP("FullscreenUI", "Uses a second thread for drawing graphics. Provides a significant speed improvement particularly with the software renderer, and is safe to use."); diff --git a/src/core/gpu_thread.cpp b/src/core/gpu_thread.cpp index bf86e2f9a..eff5cdf32 100644 --- a/src/core/gpu_thread.cpp +++ b/src/core/gpu_thread.cpp @@ -639,21 +639,29 @@ bool GPUThread::CreateDeviceOnThread(RenderAPI api, bool fullscreen, bool clear_ (g_gpu_settings.display_exclusive_fullscreen_control == DisplayExclusiveFullscreenControl::Allowed); } - u32 disabled_features = 0; + GPUDevice::CreateFlags create_flags = GPUDevice::CreateFlags::None; + if (g_gpu_settings.gpu_prefer_gles_context) + create_flags |= GPUDevice::CreateFlags::PreferGLESContext; + if (g_gpu_settings.gpu_use_debug_device) + create_flags |= GPUDevice::CreateFlags::EnableDebugDevice; + if (g_gpu_settings.gpu_use_debug_device && g_gpu_settings.gpu_use_debug_device_gpu_validation) + create_flags |= GPUDevice::CreateFlags::EnableGPUValidation; if (g_gpu_settings.gpu_disable_dual_source_blend) - disabled_features |= GPUDevice::FEATURE_MASK_DUAL_SOURCE_BLEND; + create_flags |= GPUDevice::CreateFlags::DisableDualSourceBlend; if (g_gpu_settings.gpu_disable_framebuffer_fetch) - disabled_features |= GPUDevice::FEATURE_MASK_FRAMEBUFFER_FETCH; + create_flags |= GPUDevice::CreateFlags::DisableFramebufferFetch; if (g_gpu_settings.gpu_disable_texture_buffers) - disabled_features |= GPUDevice::FEATURE_MASK_TEXTURE_BUFFERS; + create_flags |= GPUDevice::CreateFlags::DisableTextureBuffers; + if (g_gpu_settings.gpu_disable_texture_copy_to_self) + create_flags |= GPUDevice::CreateFlags::DisableTextureCopyToSelf; if (g_gpu_settings.gpu_disable_memory_import) - disabled_features |= GPUDevice::FEATURE_MASK_MEMORY_IMPORT; + create_flags |= GPUDevice::CreateFlags::DisableMemoryImport; if (g_gpu_settings.gpu_disable_raster_order_views) - disabled_features |= GPUDevice::FEATURE_MASK_RASTER_ORDER_VIEWS; + create_flags |= GPUDevice::CreateFlags::DisableRasterOrderViews; if (g_gpu_settings.gpu_disable_compute_shaders) - disabled_features |= GPUDevice::FEATURE_MASK_COMPUTE_SHADERS; + create_flags |= GPUDevice::CreateFlags::DisableComputeShaders; if (g_gpu_settings.gpu_disable_compressed_textures) - disabled_features |= GPUDevice::FEATURE_MASK_COMPRESSED_TEXTURES; + create_flags |= GPUDevice::CreateFlags::DisableCompressedTextures; // Don't dump shaders on debug builds for Android, users will complain about storage... #if !defined(__ANDROID__) || defined(_DEBUG) @@ -667,11 +675,9 @@ bool GPUThread::CreateDeviceOnThread(RenderAPI api, bool fullscreen, bool clear_ if (!g_gpu_device || !(wi = Host::AcquireRenderWindow(api, fullscreen, fullscreen_mode.has_value(), &create_error)).has_value() || !g_gpu_device->Create( - Host::GetStringSettingValue("GPU", "Adapter"), static_cast(disabled_features), - shader_dump_directory, + Host::GetStringSettingValue("GPU", "Adapter"), create_flags, shader_dump_directory, g_gpu_settings.gpu_disable_shader_cache ? std::string_view() : std::string_view(EmuFolders::Cache), - SHADER_CACHE_VERSION, g_gpu_settings.gpu_use_debug_device, g_gpu_settings.gpu_use_debug_device_gpu_validation, - wi.value(), s_state.requested_vsync, s_state.requested_allow_present_throttle, + SHADER_CACHE_VERSION, wi.value(), s_state.requested_vsync, s_state.requested_allow_present_throttle, fullscreen_mode.has_value() ? &fullscreen_mode.value() : nullptr, exclusive_fullscreen_control, &create_error)) { ERROR_LOG("Failed to create GPU device: {}", create_error.GetDescription()); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index fafac6b01..cc92d7eee 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -240,6 +240,7 @@ void Settings::Load(const SettingsInterface& si, const SettingsInterface& contro gpu_multisamples = static_cast(si.GetUIntValue("GPU", "Multisamples", 1u)); gpu_use_debug_device = si.GetBoolValue("GPU", "UseDebugDevice", false); gpu_use_debug_device_gpu_validation = si.GetBoolValue("GPU", "UseGPUBasedValidation", false); + gpu_prefer_gles_context = si.GetBoolValue("GPU", "PreferGLESContext", DEFAULT_GPU_PREFER_GLES_CONTEXT); gpu_disable_shader_cache = si.GetBoolValue("GPU", "DisableShaderCache", false); gpu_disable_dual_source_blend = si.GetBoolValue("GPU", "DisableDualSourceBlend", false); gpu_disable_framebuffer_fetch = si.GetBoolValue("GPU", "DisableFramebufferFetch", false); @@ -622,6 +623,7 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const { si.SetBoolValue("GPU", "UseDebugDevice", gpu_use_debug_device); si.SetBoolValue("GPU", "UseGPUBasedValidation", gpu_use_debug_device_gpu_validation); + si.SetBoolValue("GPU", "PreferGLESContext", gpu_prefer_gles_context); si.SetBoolValue("GPU", "DisableShaderCache", gpu_disable_shader_cache); si.SetBoolValue("GPU", "DisableDualSourceBlend", gpu_disable_dual_source_blend); si.SetBoolValue("GPU", "DisableFramebufferFetch", gpu_disable_framebuffer_fetch); @@ -1184,6 +1186,7 @@ bool Settings::AreGPUDeviceSettingsChanged(const Settings& old_settings) const return (gpu_adapter != old_settings.gpu_adapter || gpu_use_thread != old_settings.gpu_use_thread || gpu_use_debug_device != old_settings.gpu_use_debug_device || gpu_use_debug_device_gpu_validation != old_settings.gpu_use_debug_device_gpu_validation || + gpu_prefer_gles_context != old_settings.gpu_prefer_gles_context || gpu_disable_shader_cache != old_settings.gpu_disable_shader_cache || gpu_disable_dual_source_blend != old_settings.gpu_disable_dual_source_blend || gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch || diff --git a/src/core/settings.h b/src/core/settings.h index b84580d28..d01ea0206 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -98,6 +98,7 @@ struct GPUSettings bool gpu_use_software_renderer_for_readbacks : 1 = false; bool gpu_use_debug_device : 1 = false; bool gpu_use_debug_device_gpu_validation : 1 = false; + bool gpu_prefer_gles_context : 1 = DEFAULT_GPU_PREFER_GLES_CONTEXT; bool gpu_disable_shader_cache : 1 = false; bool gpu_disable_dual_source_blend : 1 = false; bool gpu_disable_framebuffer_fetch : 1 = false; @@ -264,8 +265,10 @@ struct GPUSettings #ifndef __ANDROID__ static constexpr u8 DEFAULT_GPU_MAX_QUEUED_FRAMES = 2; + static constexpr bool DEFAULT_GPU_PREFER_GLES_CONTEXT = false; #else static constexpr u8 DEFAULT_GPU_MAX_QUEUED_FRAMES = 3; + static constexpr bool DEFAULT_GPU_PREFER_GLES_CONTEXT = true; #endif }; diff --git a/src/duckstation-qt/graphicssettingswidget.cpp b/src/duckstation-qt/graphicssettingswidget.cpp index 7b0d3206c..9f506ac0e 100644 --- a/src/duckstation-qt/graphicssettingswidget.cpp +++ b/src/duckstation-qt/graphicssettingswidget.cpp @@ -334,6 +334,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useDebugDevice, "GPU", "UseDebugDevice", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useGPUBasedValidation, "GPU", "UseGPUBasedValidation", false); + SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.preferGLESContext, "GPU", "PreferGLESContext", + Settings::DEFAULT_GPU_PREFER_GLES_CONTEXT); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableShaderCache, "GPU", "DisableShaderCache", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableDualSource, "GPU", "DisableDualSourceBlend", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableFramebufferFetch, "GPU", "DisableFramebufferFetch", @@ -421,8 +423,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* dialog->registerWidgetHelp( m_ui.displayScaling, tr("Scaling"), tr("Bilinear (Smooth)"), tr("Determines how the emulated console's output is upscaled or downscaled to your monitor's resolution.")); - dialog->registerWidgetHelp(m_ui.displayScaling24Bit, tr("FMV Scaling"), tr("Bilinear (Smooth)"), - tr("Determines the scaling algorithm used when 24-bit content is active, typically FMVs.")); + dialog->registerWidgetHelp( + m_ui.displayScaling24Bit, tr("FMV Scaling"), tr("Bilinear (Smooth)"), + tr("Determines the scaling algorithm used when 24-bit content is active, typically FMVs.")); dialog->registerWidgetHelp( m_ui.widescreenHack, tr("Widescreen Rendering"), tr("Unchecked"), tr("Scales vertex positions in screen-space to a widescreen aspect ratio, essentially " @@ -660,6 +663,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* dialog->registerWidgetHelp( m_ui.useGPUBasedValidation, tr("Use GPU-Based Validation"), tr("Unchecked"), tr("Enable GPU-based validation when supported by the renderer API. Only for developer use.")); + dialog->registerWidgetHelp( + m_ui.preferGLESContext, tr("Prefer OpenGL ES Context"), tr("Unchecked"), + tr("Uses OpenGL ES even when desktop OpenGL is supported. May improve performance on some SBC drivers.")); dialog->registerWidgetHelp( m_ui.disableShaderCache, tr("Disable Shader Cache"), tr("Unchecked"), tr("Forces shaders to be compiled for every run of the program. Only for developer use.")); diff --git a/src/duckstation-qt/graphicssettingswidget.ui b/src/duckstation-qt/graphicssettingswidget.ui index 0e18f4a23..4e5f0c282 100644 --- a/src/duckstation-qt/graphicssettingswidget.ui +++ b/src/duckstation-qt/graphicssettingswidget.ui @@ -1362,62 +1362,69 @@ + + + Prefer OpenGL ES Context + + + + Disable Shader Cache - + Disable Compressed Textures - + Disable Dual-Source Blending - + Disable Framebuffer Fetch - + Disable Texture Buffers - + Disable Texture Copy To Self - + Disable Memory Import - + Disable Rasterizer Order Views - + Disable Compute Shaders diff --git a/src/util/d3d11_device.cpp b/src/util/d3d11_device.cpp index 9c9b78030..cb18af77b 100644 --- a/src/util/d3d11_device.cpp +++ b/src/util/d3d11_device.cpp @@ -57,17 +57,16 @@ D3D11Device::~D3D11Device() Assert(!m_device); } -bool D3D11Device::CreateDeviceAndMainSwapChain(std::string_view adapter, FeatureMask disabled_features, - const WindowInfo& wi, GPUVSyncMode vsync_mode, - bool allow_present_throttle, +bool D3D11Device::CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, + GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) { std::unique_lock lock(s_instance_mutex); - UINT create_flags = 0; + UINT d3d_create_flags = 0; if (m_debug_device) - create_flags |= D3D11_CREATE_DEVICE_DEBUG; + d3d_create_flags |= D3D11_CREATE_DEVICE_DEBUG; m_dxgi_factory = D3DCommon::CreateFactory(m_debug_device, error); if (!m_dxgi_factory) @@ -82,7 +81,7 @@ bool D3D11Device::CreateDeviceAndMainSwapChain(std::string_view adapter, Feature ComPtr temp_device; ComPtr temp_context; HRESULT hr; - if (!D3DCommon::CreateD3D11Device(dxgi_adapter.Get(), create_flags, requested_feature_levels.data(), + if (!D3DCommon::CreateD3D11Device(dxgi_adapter.Get(), d3d_create_flags, requested_feature_levels.data(), static_cast(requested_feature_levels.size()), &temp_device, nullptr, &temp_context, error)) { @@ -129,7 +128,7 @@ bool D3D11Device::CreateDeviceAndMainSwapChain(std::string_view adapter, Feature D3DCommon::GetFeatureLevelString(D3DCommon::GetRenderAPIVersionForFeatureLevel(m_max_feature_level))); SetDriverType(driver_type); - SetFeatures(disabled_features); + SetFeatures(create_flags); if (!wi.IsSurfaceless()) { @@ -155,7 +154,7 @@ void D3D11Device::DestroyDevice() m_device.Reset(); } -void D3D11Device::SetFeatures(FeatureMask disabled_features) +void D3D11Device::SetFeatures(CreateFlags create_flags) { const D3D_FEATURE_LEVEL feature_level = m_device->GetFeatureLevel(); @@ -173,17 +172,17 @@ void D3D11Device::SetFeatures(FeatureMask disabled_features) } } - m_features.dual_source_blend = !(disabled_features & FEATURE_MASK_DUAL_SOURCE_BLEND); + m_features.dual_source_blend = !HasCreateFlag(create_flags, CreateFlags::DisableDualSourceBlend); m_features.framebuffer_fetch = false; m_features.per_sample_shading = (feature_level >= D3D_FEATURE_LEVEL_10_1); m_features.noperspective_interpolation = true; m_features.texture_copy_to_self = false; - m_features.texture_buffers = !(disabled_features & FEATURE_MASK_TEXTURE_BUFFERS); + m_features.texture_buffers = !HasCreateFlag(create_flags, CreateFlags::DisableTextureBuffers); m_features.texture_buffers_emulated_with_ssbo = false; m_features.feedback_loops = false; - m_features.geometry_shaders = !(disabled_features & FEATURE_MASK_GEOMETRY_SHADERS); + m_features.geometry_shaders = !HasCreateFlag(create_flags, CreateFlags::DisableGeometryShaders); m_features.compute_shaders = - (!(disabled_features & FEATURE_MASK_COMPUTE_SHADERS) && feature_level >= D3D_FEATURE_LEVEL_11_0); + (!HasCreateFlag(create_flags, CreateFlags::DisableComputeShaders) && feature_level >= D3D_FEATURE_LEVEL_11_0); m_features.partial_msaa_resolve = false; m_features.memory_import = false; m_features.exclusive_fullscreen = true; @@ -194,7 +193,7 @@ void D3D11Device::SetFeatures(FeatureMask disabled_features) m_features.pipeline_cache = false; m_features.prefer_unused_textures = false; m_features.raster_order_views = false; - if (!(disabled_features & FEATURE_MASK_RASTER_ORDER_VIEWS)) + if (!!HasCreateFlag(create_flags, CreateFlags::DisableRasterOrderViews)) { D3D11_FEATURE_DATA_D3D11_OPTIONS2 data = {}; m_features.raster_order_views = @@ -203,11 +202,11 @@ void D3D11Device::SetFeatures(FeatureMask disabled_features) } m_features.dxt_textures = - (!(disabled_features & FEATURE_MASK_COMPRESSED_TEXTURES) && + (!HasCreateFlag(create_flags, CreateFlags::DisableCompressedTextures) && (SupportsTextureFormat(GPUTexture::Format::BC1) && SupportsTextureFormat(GPUTexture::Format::BC2) && SupportsTextureFormat(GPUTexture::Format::BC3))); - m_features.bptc_textures = - (!(disabled_features & FEATURE_MASK_COMPRESSED_TEXTURES) && SupportsTextureFormat(GPUTexture::Format::BC7)); + m_features.bptc_textures = (!HasCreateFlag(create_flags, CreateFlags::DisableCompressedTextures) && + SupportsTextureFormat(GPUTexture::Format::BC7)); } D3D11SwapChain::D3D11SwapChain(const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, diff --git a/src/util/d3d11_device.h b/src/util/d3d11_device.h index e9048047d..1a4660fc5 100644 --- a/src/util/d3d11_device.h +++ b/src/util/d3d11_device.h @@ -116,7 +116,7 @@ public: void UnbindTexture(D3D11Texture* tex); protected: - bool CreateDeviceAndMainSwapChain(std::string_view adapter, FeatureMask disabled_features, const WindowInfo& wi, + bool CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) override; @@ -142,7 +142,7 @@ private: static constexpr u32 UNIFORM_BUFFER_ALIGNMENT_DISCARD = 16; static constexpr u8 NUM_TIMESTAMP_QUERIES = 3; - void SetFeatures(FeatureMask disabled_features); + void SetFeatures(CreateFlags create_flags); bool CreateBuffers(Error* error); void DestroyBuffers(); diff --git a/src/util/d3d12_device.cpp b/src/util/d3d12_device.cpp index 48f4bff77..2ea68c875 100644 --- a/src/util/d3d12_device.cpp +++ b/src/util/d3d12_device.cpp @@ -148,7 +148,7 @@ D3D12Device::ComPtr D3D12Device::CreateRootSignature(const return rs; } -bool D3D12Device::CreateDeviceAndMainSwapChain(std::string_view adapter, FeatureMask disabled_features, +bool D3D12Device::CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, @@ -173,7 +173,7 @@ bool D3D12Device::CreateDeviceAndMainSwapChain(std::string_view adapter, Feature INFO_LOG("Enabling debug layer."); debug12->EnableDebugLayer(); - if (m_debug_device_gpu_validation) + if (HasCreateFlag(create_flags, GPUDevice::CreateFlags::EnableGPUValidation)) { ComPtr debug12_1; if (SUCCEEDED(debug12.As(&debug12_1))) @@ -184,7 +184,6 @@ bool D3D12Device::CreateDeviceAndMainSwapChain(std::string_view adapter, Feature else { ERROR_LOG("GPU-based validation requested but not available."); - m_debug_device_gpu_validation = false; } } } @@ -283,7 +282,7 @@ bool D3D12Device::CreateDeviceAndMainSwapChain(std::string_view adapter, Feature return false; } - SetFeatures(feature_level, disabled_features); + SetFeatures(feature_level, create_flags); if (!CreateCommandLists(error) || !CreateDescriptorHeaps(error)) return false; @@ -1319,7 +1318,7 @@ void D3D12Device::InsertDebugMessage(const char* msg) #endif -void D3D12Device::SetFeatures(D3D_FEATURE_LEVEL feature_level, FeatureMask disabled_features) +void D3D12Device::SetFeatures(D3D_FEATURE_LEVEL feature_level, CreateFlags create_flags) { m_render_api_version = D3DCommon::GetRenderAPIVersionForFeatureLevel(feature_level); m_max_texture_size = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION; @@ -1336,17 +1335,17 @@ void D3D12Device::SetFeatures(D3D_FEATURE_LEVEL feature_level, FeatureMask disab } } - m_features.dual_source_blend = !(disabled_features & FEATURE_MASK_DUAL_SOURCE_BLEND); + m_features.dual_source_blend = !HasCreateFlag(create_flags, CreateFlags::DisableDualSourceBlend); m_features.framebuffer_fetch = false; m_features.per_sample_shading = true; m_features.noperspective_interpolation = true; m_features.texture_copy_to_self = - /*!(disabled_features & FEATURE_MASK_TEXTURE_COPY_TO_SELF)*/ false; // TODO: Support with Enhanced Barriers - m_features.texture_buffers = !(disabled_features & FEATURE_MASK_TEXTURE_BUFFERS); + /*!HasCreateFlag(create_flags, CreateFlag::DisableTextureCopyToSelf)*/ false; // TODO: Support with Enhanced Barriers + m_features.texture_buffers = !HasCreateFlag(create_flags, CreateFlags::DisableTextureBuffers); m_features.texture_buffers_emulated_with_ssbo = false; m_features.feedback_loops = false; - m_features.geometry_shaders = !(disabled_features & FEATURE_MASK_GEOMETRY_SHADERS); - m_features.compute_shaders = !(disabled_features & FEATURE_MASK_COMPUTE_SHADERS); + m_features.geometry_shaders = !HasCreateFlag(create_flags, CreateFlags::DisableGeometryShaders); + m_features.compute_shaders = !HasCreateFlag(create_flags, CreateFlags::DisableComputeShaders); m_features.partial_msaa_resolve = true; m_features.memory_import = false; m_features.exclusive_fullscreen = true; @@ -1358,7 +1357,7 @@ void D3D12Device::SetFeatures(D3D_FEATURE_LEVEL feature_level, FeatureMask disab m_features.prefer_unused_textures = true; m_features.raster_order_views = false; - if (!(disabled_features & FEATURE_MASK_RASTER_ORDER_VIEWS)) + if (!!HasCreateFlag(create_flags, CreateFlags::DisableRasterOrderViews)) { D3D12_FEATURE_DATA_D3D12_OPTIONS options = {}; m_features.raster_order_views = @@ -1367,11 +1366,11 @@ void D3D12Device::SetFeatures(D3D_FEATURE_LEVEL feature_level, FeatureMask disab } m_features.dxt_textures = - (!(disabled_features & FEATURE_MASK_COMPRESSED_TEXTURES) && + (!HasCreateFlag(create_flags, CreateFlags::DisableCompressedTextures) && (SupportsTextureFormat(GPUTexture::Format::BC1) && SupportsTextureFormat(GPUTexture::Format::BC2) && SupportsTextureFormat(GPUTexture::Format::BC3))); m_features.bptc_textures = - (!(disabled_features & FEATURE_MASK_COMPRESSED_TEXTURES) && SupportsTextureFormat(GPUTexture::Format::BC7)); + (!HasCreateFlag(create_flags, CreateFlags::DisableCompressedTextures) && SupportsTextureFormat(GPUTexture::Format::BC7)); } void D3D12Device::CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, diff --git a/src/util/d3d12_device.h b/src/util/d3d12_device.h index 4fc92fa0d..2ec5f1356 100644 --- a/src/util/d3d12_device.h +++ b/src/util/d3d12_device.h @@ -199,7 +199,7 @@ public: u32 src_width, u32 src_height); protected: - bool CreateDeviceAndMainSwapChain(std::string_view adapter, FeatureMask disabled_features, const WindowInfo& wi, + bool CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) override; @@ -246,7 +246,7 @@ private: static_assert(sizeof(PIPELINE_CACHE_HEADER) == 16); void GetPipelineCacheHeader(PIPELINE_CACHE_HEADER* hdr); - void SetFeatures(D3D_FEATURE_LEVEL feature_level, FeatureMask disabled_features); + void SetFeatures(D3D_FEATURE_LEVEL feature_level, CreateFlags create_flags); bool CreateCommandLists(Error* error); void DestroyCommandLists(); diff --git a/src/util/gpu_device.cpp b/src/util/gpu_device.cpp index 69096fe55..b38f5a384 100644 --- a/src/util/gpu_device.cpp +++ b/src/util/gpu_device.cpp @@ -446,19 +446,50 @@ GPUDevice::AdapterInfoList GPUDevice::GetAdapterListForAPI(RenderAPI api) return ret; } -bool GPUDevice::Create(std::string_view adapter, FeatureMask disabled_features, std::string_view shader_dump_path, - std::string_view shader_cache_path, u32 shader_cache_version, bool debug_device, - bool gpu_validation, const WindowInfo& wi, GPUVSyncMode vsync, bool allow_present_throttle, +bool GPUDevice::Create(std::string_view adapter, CreateFlags create_flags, std::string_view shader_dump_path, + std::string_view shader_cache_path, u32 shader_cache_version, const WindowInfo& wi, + GPUVSyncMode vsync, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) { - m_debug_device = debug_device; - m_debug_device_gpu_validation = debug_device && gpu_validation; + m_debug_device = HasCreateFlag(create_flags, CreateFlags::EnableDebugDevice); s_shader_dump_path = shader_dump_path; INFO_LOG("Main render window is {}x{}.", wi.surface_width, wi.surface_height); - if (!CreateDeviceAndMainSwapChain(adapter, disabled_features, wi, vsync, allow_present_throttle, - exclusive_fullscreen_mode, exclusive_fullscreen_control, error)) + + if (create_flags != CreateFlags::None) [[unlikely]] + { + WARNING_LOG("One or more non-standard creation flags are set:"); + if (HasCreateFlag(create_flags, CreateFlags::EnableDebugDevice)) + WARNING_LOG(" - Use debug device"); + if (HasCreateFlag(create_flags, CreateFlags::EnableGPUValidation)) + WARNING_LOG(" - Enable GPU validation"); + if (HasCreateFlag(create_flags, CreateFlags::PreferGLESContext)) + WARNING_LOG(" - Prefer OpenGL ES context"); + if (HasCreateFlag(create_flags, CreateFlags::DisableDualSourceBlend)) + WARNING_LOG(" - Disable dual source blend"); + if (HasCreateFlag(create_flags, CreateFlags::DisableFeedbackLoops)) + WARNING_LOG(" - Disable feedback loops"); + if (HasCreateFlag(create_flags, CreateFlags::DisableFramebufferFetch)) + WARNING_LOG(" - Disable framebuffer fetch"); + if (HasCreateFlag(create_flags, CreateFlags::DisableTextureBuffers)) + WARNING_LOG(" - Disable texture buffers"); + if (HasCreateFlag(create_flags, CreateFlags::DisableGeometryShaders)) + WARNING_LOG(" - Disable geometry shaders"); + if (HasCreateFlag(create_flags, CreateFlags::DisableComputeShaders)) + WARNING_LOG(" - Disable compute shaders"); + if (HasCreateFlag(create_flags, CreateFlags::DisableTextureCopyToSelf)) + WARNING_LOG(" - Disable texture copy to self"); + if (HasCreateFlag(create_flags, CreateFlags::DisableMemoryImport)) + WARNING_LOG(" - Disable memory import"); + if (HasCreateFlag(create_flags, CreateFlags::DisableRasterOrderViews)) + WARNING_LOG(" - Disable raster order views"); + if (HasCreateFlag(create_flags, CreateFlags::DisableCompressedTextures)) + WARNING_LOG(" - Disable compressed textures"); + } + + if (!CreateDeviceAndMainSwapChain(adapter, create_flags, wi, vsync, allow_present_throttle, exclusive_fullscreen_mode, + exclusive_fullscreen_control, error)) { if (error && !error->IsValid()) error->SetStringView("Failed to create device."); @@ -1203,7 +1234,6 @@ void GPUDevice::ResetStatistics() s_stats = {}; } - GPUDriverType GPUDevice::GuessDriverType(u32 pci_vendor_id, std::string_view vendor_name, std::string_view adapter_name) { #define ACHECK(name) (adapter_name.find(name) != std::string_view::npos) diff --git a/src/util/gpu_device.h b/src/util/gpu_device.h index 3af70d20f..430779c8d 100644 --- a/src/util/gpu_device.h +++ b/src/util/gpu_device.h @@ -578,22 +578,24 @@ class GPUDevice public: friend GPUTexture; - // TODO: drop virtuals - // TODO: gpu crash handling on present using DrawIndex = u16; - enum FeatureMask : u32 + enum class CreateFlags : u32 { - FEATURE_MASK_DUAL_SOURCE_BLEND = (1 << 0), - FEATURE_MASK_FEEDBACK_LOOPS = (1 << 1), - FEATURE_MASK_FRAMEBUFFER_FETCH = (1 << 2), - FEATURE_MASK_TEXTURE_BUFFERS = (1 << 3), - FEATURE_MASK_GEOMETRY_SHADERS = (1 << 4), - FEATURE_MASK_COMPUTE_SHADERS = (1 << 5), - FEATURE_MASK_TEXTURE_COPY_TO_SELF = (1 << 6), - FEATURE_MASK_MEMORY_IMPORT = (1 << 7), - FEATURE_MASK_RASTER_ORDER_VIEWS = (1 << 8), - FEATURE_MASK_COMPRESSED_TEXTURES = (1 << 9), + None = 0, + PreferGLESContext = (1 << 0), + EnableDebugDevice = (1 << 1), + EnableGPUValidation = (1 << 2), + DisableDualSourceBlend = (1 << 3), + DisableFeedbackLoops = (1 << 4), + DisableFramebufferFetch = (1 << 5), + DisableTextureBuffers = (1 << 6), + DisableGeometryShaders = (1 << 7), + DisableComputeShaders = (1 << 8), + DisableTextureCopyToSelf = (1 << 9), + DisableMemoryImport = (1 << 10), + DisableRasterOrderViews = (1 << 11), + DisableCompressedTextures = (1 << 12), }; enum class DrawBarrier : u32 @@ -715,6 +717,12 @@ public: /// Converts a RGBA8 value to 4 floating-point values. static std::array RGBA8ToFloat(u32 rgba); + /// Returns true if the given device creation flag is present. + static constexpr bool HasCreateFlag(CreateFlags flags, CreateFlags flag) + { + return ((static_cast(flags) & static_cast(flag)) != 0); + } + /// Returns the number of texture bindings for a given pipeline layout. static constexpr u32 GetActiveTexturesForLayout(GPUPipeline::Layout layout) { @@ -763,10 +771,9 @@ public: ALWAYS_INLINE bool IsGPUTimingEnabled() const { return m_gpu_timing_enabled; } - bool Create(std::string_view adapter, FeatureMask disabled_features, std::string_view shader_dump_path, - std::string_view shader_cache_path, u32 shader_cache_version, bool debug_device, bool gpu_validation, - const WindowInfo& wi, GPUVSyncMode vsync, bool allow_present_throttle, - const ExclusiveFullscreenMode* exclusive_fullscreen_mode, + bool Create(std::string_view adapter, CreateFlags create_flags, std::string_view shader_dump_path, + std::string_view shader_cache_path, u32 shader_cache_version, const WindowInfo& wi, GPUVSyncMode vsync, + bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error); void Destroy(); @@ -920,8 +927,8 @@ public: static void ResetStatistics(); protected: - virtual bool CreateDeviceAndMainSwapChain(std::string_view adapter, FeatureMask disabled_features, - const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, + virtual bool CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, + GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) = 0; virtual void DestroyDevice() = 0; @@ -1030,11 +1037,12 @@ protected: bool m_gpu_timing_enabled = false; bool m_debug_device = false; - bool m_debug_device_gpu_validation = false; }; extern std::unique_ptr g_gpu_device; +IMPLEMENT_ENUM_CLASS_BITWISE_OPERATORS(GPUDevice::CreateFlags); + ALWAYS_INLINE void GPUDevice::PooledTextureDeleter::operator()(GPUTexture* const tex) { g_gpu_device->RecycleTexture(std::unique_ptr(tex)); diff --git a/src/util/metal_device.h b/src/util/metal_device.h index 0a27fca2d..5f899b705 100644 --- a/src/util/metal_device.h +++ b/src/util/metal_device.h @@ -329,7 +329,7 @@ public: static void DeferRelease(u64 fence_counter, id obj); protected: - bool CreateDeviceAndMainSwapChain(std::string_view adapter, FeatureMask disabled_features, const WindowInfo& wi, + bool CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) override; @@ -358,7 +358,7 @@ private: }; static_assert(sizeof(ClearPipelineConfig) == 8); - void SetFeatures(FeatureMask disabled_features); + void SetFeatures(CreateFlags create_flags); bool LoadShaders(); std::unique_ptr CreateShaderFromMSL(GPUShaderStage stage, std::string_view source, diff --git a/src/util/metal_device.mm b/src/util/metal_device.mm index 24bc64eb5..4c752129b 100644 --- a/src/util/metal_device.mm +++ b/src/util/metal_device.mm @@ -284,7 +284,7 @@ void MetalDevice::RenderBlankFrame(MetalSwapChain* swap_chain) } } -bool MetalDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, FeatureMask disabled_features, +bool MetalDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, @@ -334,7 +334,7 @@ bool MetalDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, Feature INFO_LOG("Metal Device: {}", device_name); SetDriverType(GuessDriverType(0, {}, device_name)); - SetFeatures(disabled_features); + SetFeatures(create_flags); CreateCommandBuffer(); if (!wi.IsSurfaceless()) @@ -363,7 +363,7 @@ bool MetalDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, Feature } } -void MetalDevice::SetFeatures(FeatureMask disabled_features) +void MetalDevice::SetFeatures(CreateFlags create_flags) { // Set version to Metal 2.3, that's all we're using. Use SPIRV-Cross version encoding. m_render_api_version = 20300; @@ -377,12 +377,12 @@ void MetalDevice::SetFeatures(FeatureMask disabled_features) const bool supports_barriers = ([m_device supportsFamily:MTLGPUFamilyMac1] && ![m_device supportsFamily:MTLGPUFamilyApple3]); - m_features.dual_source_blend = !(disabled_features & FEATURE_MASK_DUAL_SOURCE_BLEND); - m_features.framebuffer_fetch = !(disabled_features & FEATURE_MASK_FRAMEBUFFER_FETCH) && supports_fbfetch; + m_features.dual_source_blend = !HasCreateFlag(create_flags, CreateFlags::DisableDualSourceBlend); + m_features.framebuffer_fetch = !HasCreateFlag(create_flags, CreateFlags::DisableFramebufferFetch) && supports_fbfetch; m_features.per_sample_shading = true; m_features.noperspective_interpolation = true; - m_features.texture_copy_to_self = !(disabled_features & FEATURE_MASK_TEXTURE_COPY_TO_SELF); - m_features.texture_buffers = !(disabled_features & FEATURE_MASK_TEXTURE_BUFFERS); + m_features.texture_copy_to_self = !HasCreateFlag(create_flags, CreateFlags::DisableTextureCopyToSelf); + m_features.texture_buffers = !HasCreateFlag(create_flags, CreateFlags::DisableTextureBuffers); m_features.texture_buffers_emulated_with_ssbo = true; m_features.feedback_loops = (m_features.framebuffer_fetch || supports_barriers); m_features.geometry_shaders = false; @@ -397,7 +397,7 @@ void MetalDevice::SetFeatures(FeatureMask disabled_features) // Same feature bit for both. m_features.dxt_textures = m_features.bptc_textures = - !(disabled_features & FEATURE_MASK_COMPRESSED_TEXTURES) && m_device.supportsBCTextureCompression; + !HasCreateFlag(create_flags, CreateFlags::DisableCompressedTextures) && m_device.supportsBCTextureCompression; } bool MetalDevice::LoadShaders() diff --git a/src/util/opengl_context.cpp b/src/util/opengl_context.cpp index 6db3ce870..1cc72e146 100644 --- a/src/util/opengl_context.cpp +++ b/src/util/opengl_context.cpp @@ -39,21 +39,6 @@ LOG_CHANNEL(GPUDevice); -static bool ShouldPreferESContext() -{ -#if defined(__ANDROID__) - return true; -#elif !defined(_MSC_VER) - const char* value = std::getenv("PREFER_GLES_CONTEXT"); - return (value && std::strcmp(value, "1") == 0); -#else - char buffer[2] = {}; - size_t buffer_size = sizeof(buffer); - getenv_s(&buffer_size, buffer, "PREFER_GLES_CONTEXT"); - return (std::strcmp(buffer, "1") == 0); -#endif -} - static void DisableBrokenExtensions(const char* gl_vendor, const char* gl_renderer, const char* gl_version) { if (std::strstr(gl_vendor, "ARM")) @@ -122,7 +107,8 @@ OpenGLContext::OpenGLContext() = default; OpenGLContext::~OpenGLContext() = default; -std::unique_ptr OpenGLContext::Create(WindowInfo& wi, SurfaceHandle* surface, Error* error) +std::unique_ptr OpenGLContext::Create(WindowInfo& wi, SurfaceHandle* surface, bool prefer_gles_context, + Error* error) { static constexpr std::array vlist = {{{Profile::Core, 4, 6}, {Profile::Core, 4, 5}, @@ -140,7 +126,7 @@ std::unique_ptr OpenGLContext::Create(WindowInfo& wi, SurfaceHand {Profile::Core, 3, 0}}}; std::span versions_to_try = vlist; - if (ShouldPreferESContext()) + if (prefer_gles_context) { // move ES versions to the front Version* new_versions_to_try = static_cast(alloca(sizeof(Version) * versions_to_try.size())); diff --git a/src/util/opengl_context.h b/src/util/opengl_context.h index 82e002a8e..36d237281 100644 --- a/src/util/opengl_context.h +++ b/src/util/opengl_context.h @@ -49,7 +49,8 @@ public: virtual bool SetSwapInterval(s32 interval, Error* error = nullptr) = 0; virtual std::unique_ptr CreateSharedContext(WindowInfo& wi, SurfaceHandle* surface, Error* error) = 0; - static std::unique_ptr Create(WindowInfo& wi, SurfaceHandle* surface, Error* error); + static std::unique_ptr Create(WindowInfo& wi, SurfaceHandle* surface, bool prefer_gles_context, + Error* error); protected: Version m_version = {}; diff --git a/src/util/opengl_device.cpp b/src/util/opengl_device.cpp index c2bf3cdc7..467b2cdf7 100644 --- a/src/util/opengl_device.cpp +++ b/src/util/opengl_device.cpp @@ -266,15 +266,15 @@ static void GLAD_API_PTR GLDebugCallback(GLenum source, GLenum type, GLuint id, } } -bool OpenGLDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, FeatureMask disabled_features, - const WindowInfo& wi, GPUVSyncMode vsync_mode, - bool allow_present_throttle, +bool OpenGLDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, + GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) { WindowInfo wi_copy(wi); OpenGLContext::SurfaceHandle wi_surface; - m_gl_context = OpenGLContext::Create(wi_copy, &wi_surface, error); + m_gl_context = + OpenGLContext::Create(wi_copy, &wi_surface, HasCreateFlag(create_flags, CreateFlags::PreferGLESContext), error); if (!m_gl_context) { ERROR_LOG("Failed to create any GL context"); @@ -324,7 +324,7 @@ bool OpenGLDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, Featur RenderBlankFrame(); } - if (!CheckFeatures(disabled_features)) + if (!CheckFeatures(create_flags)) return false; if (!CreateBuffers()) @@ -336,7 +336,7 @@ bool OpenGLDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, Featur return true; } -bool OpenGLDevice::CheckFeatures(FeatureMask disabled_features) +bool OpenGLDevice::CheckFeatures(CreateFlags create_flags) { const bool is_gles = m_gl_context->IsGLES(); @@ -374,11 +374,11 @@ bool OpenGLDevice::CheckFeatures(FeatureMask disabled_features) GLint max_dual_source_draw_buffers = 0; glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS, &max_dual_source_draw_buffers); m_features.dual_source_blend = - !(disabled_features & FEATURE_MASK_DUAL_SOURCE_BLEND) && (max_dual_source_draw_buffers > 0) && + !HasCreateFlag(create_flags, CreateFlags::DisableDualSourceBlend) && (max_dual_source_draw_buffers > 0) && (GLAD_GL_VERSION_3_3 || GLAD_GL_ARB_blend_func_extended || GLAD_GL_EXT_blend_func_extended); m_features.framebuffer_fetch = - !(disabled_features & (FEATURE_MASK_FEEDBACK_LOOPS | FEATURE_MASK_FRAMEBUFFER_FETCH)) && + !HasCreateFlag(create_flags, CreateFlags::DisableFeedbackLoops | CreateFlags::DisableFramebufferFetch) && (GLAD_GL_EXT_shader_framebuffer_fetch || GLAD_GL_ARM_shader_framebuffer_fetch); #ifdef __APPLE__ @@ -386,7 +386,7 @@ bool OpenGLDevice::CheckFeatures(FeatureMask disabled_features) m_features.texture_buffers = false; #else m_features.texture_buffers = - !(disabled_features & FEATURE_MASK_TEXTURE_BUFFERS) && (GLAD_GL_VERSION_3_1 || GLAD_GL_ES_VERSION_3_2); + !HasCreateFlag(create_flags, CreateFlags::DisableTextureBuffers) && (GLAD_GL_VERSION_3_1 || GLAD_GL_ES_VERSION_3_2); // And Samsung's ANGLE/GLES driver? if (std::strstr(reinterpret_cast(glGetString(GL_RENDERER)), "ANGLE")) @@ -406,7 +406,7 @@ bool OpenGLDevice::CheckFeatures(FeatureMask disabled_features) } #endif - if (!m_features.texture_buffers && !(disabled_features & FEATURE_MASK_TEXTURE_BUFFERS)) + if (!m_features.texture_buffers && !HasCreateFlag(create_flags, CreateFlags::DisableTextureBuffers)) { // Try SSBOs. GLint max_fragment_storage_blocks = 0; @@ -443,13 +443,13 @@ bool OpenGLDevice::CheckFeatures(FeatureMask disabled_features) // glBlitFramebufer with same source/destination should be legal, but on Mali (at least Bifrost) it breaks. // So, blit from the shadow texture, like in the other renderers. - m_features.texture_copy_to_self = - (m_driver_type != GPUDriverType::ARMProprietary) && !(disabled_features & FEATURE_MASK_TEXTURE_COPY_TO_SELF); + m_features.texture_copy_to_self = (m_driver_type != GPUDriverType::ARMProprietary) && + !HasCreateFlag(create_flags, CreateFlags::DisableTextureCopyToSelf); m_features.feedback_loops = false; m_features.geometry_shaders = - !(disabled_features & FEATURE_MASK_GEOMETRY_SHADERS) && (GLAD_GL_VERSION_3_2 || GLAD_GL_ES_VERSION_3_2); + !HasCreateFlag(create_flags, CreateFlags::DisableGeometryShaders) && (GLAD_GL_VERSION_3_2 || GLAD_GL_ES_VERSION_3_2); m_features.compute_shaders = false; m_features.gpu_timing = !(m_gl_context->IsGLES() && @@ -463,9 +463,9 @@ bool OpenGLDevice::CheckFeatures(FeatureMask disabled_features) m_features.shader_cache = false; m_features.dxt_textures = - (!(disabled_features & FEATURE_MASK_COMPRESSED_TEXTURES) && GLAD_GL_EXT_texture_compression_s3tc); + (!HasCreateFlag(create_flags, CreateFlags::DisableCompressedTextures) && GLAD_GL_EXT_texture_compression_s3tc); m_features.bptc_textures = - (!(disabled_features & FEATURE_MASK_COMPRESSED_TEXTURES) && + (!HasCreateFlag(create_flags, CreateFlags::DisableCompressedTextures) && (GLAD_GL_VERSION_4_2 || GLAD_GL_ARB_texture_compression_bptc || GLAD_GL_EXT_texture_compression_bptc)); m_features.pipeline_cache = m_gl_context->IsGLES() || GLAD_GL_ARB_get_program_binary; diff --git a/src/util/opengl_device.h b/src/util/opengl_device.h index 68b5352c3..d580446ca 100644 --- a/src/util/opengl_device.h +++ b/src/util/opengl_device.h @@ -143,7 +143,7 @@ public: void RenderBlankFrame(); protected: - bool CreateDeviceAndMainSwapChain(std::string_view adapter, FeatureMask disabled_features, const WindowInfo& wi, + bool CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) override; @@ -163,7 +163,7 @@ private: static constexpr u32 UNIFORM_BUFFER_SIZE = 2 * 1024 * 1024; static constexpr u32 TEXTURE_STREAM_BUFFER_SIZE = 16 * 1024 * 1024; - bool CheckFeatures(FeatureMask disabled_features); + bool CheckFeatures(CreateFlags create_flags); bool CreateBuffers(); void DestroyBuffers(); diff --git a/src/util/vulkan_device.cpp b/src/util/vulkan_device.cpp index 31fa11778..71e95b825 100644 --- a/src/util/vulkan_device.cpp +++ b/src/util/vulkan_device.cpp @@ -745,7 +745,7 @@ bool VulkanDevice::EnableOptionalDeviceExtensions(VkPhysicalDevice physical_devi } bool VulkanDevice::CreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surface, bool enable_validation_layer, - FeatureMask disabled_features, Error* error) + CreateFlags create_flags, Error* error) { u32 queue_family_count; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, nullptr); @@ -932,7 +932,7 @@ bool VulkanDevice::CreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR s queue_family_properties[m_graphics_queue_family_index].timestampValidBits, m_device_properties.limits.timestampPeriod); - SetFeatures(disabled_features, physical_device, enabled_features); + SetFeatures(create_flags, physical_device, enabled_features); return true; } @@ -1973,9 +1973,8 @@ bool VulkanDevice::IsSuitableDefaultRenderer() #endif } -bool VulkanDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, FeatureMask disabled_features, - const WindowInfo& wi, GPUVSyncMode vsync_mode, - bool allow_present_throttle, +bool VulkanDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, + GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) { @@ -2078,7 +2077,7 @@ bool VulkanDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, Featur // Attempt to create the device. if (!CreateDevice(physical_device, swap_chain ? swap_chain->GetSurface() : VK_NULL_HANDLE, enable_validation_layer, - disabled_features, error)) + create_flags, error)) { return false; } @@ -2481,7 +2480,7 @@ u32 VulkanDevice::GetMaxMultisamples(VkPhysicalDevice physical_device, const VkP return 1; } -void VulkanDevice::SetFeatures(FeatureMask disabled_features, VkPhysicalDevice physical_device, +void VulkanDevice::SetFeatures(CreateFlags create_flags, VkPhysicalDevice physical_device, const VkPhysicalDeviceFeatures& vk_features) { const u32 store_api_version = std::min(m_device_properties.apiVersion, VK_API_VERSION_1_1); @@ -2491,19 +2490,20 @@ void VulkanDevice::SetFeatures(FeatureMask disabled_features, VkPhysicalDevice p std::min(m_device_properties.limits.maxImageDimension2D, m_device_properties.limits.maxFramebufferWidth); m_max_multisamples = static_cast(GetMaxMultisamples(physical_device, m_device_properties)); - m_features.dual_source_blend = !(disabled_features & FEATURE_MASK_DUAL_SOURCE_BLEND) && vk_features.dualSrcBlend; + m_features.dual_source_blend = + !HasCreateFlag(create_flags, CreateFlags::DisableDualSourceBlend) && vk_features.dualSrcBlend; m_features.framebuffer_fetch = - !(disabled_features & (FEATURE_MASK_FEEDBACK_LOOPS | FEATURE_MASK_FRAMEBUFFER_FETCH)) && + !HasCreateFlag(create_flags, CreateFlags::DisableFeedbackLoops | CreateFlags::DisableFramebufferFetch) && m_optional_extensions.vk_ext_rasterization_order_attachment_access; if (!m_features.dual_source_blend) WARNING_LOG("Vulkan driver is missing dual-source blending. This will have an impact on performance."); m_features.noperspective_interpolation = true; - m_features.texture_copy_to_self = !(disabled_features & FEATURE_MASK_TEXTURE_COPY_TO_SELF); + m_features.texture_copy_to_self = !HasCreateFlag(create_flags, CreateFlags::DisableTextureCopyToSelf); m_features.per_sample_shading = vk_features.sampleRateShading; - m_features.texture_buffers = !(disabled_features & FEATURE_MASK_TEXTURE_BUFFERS); - m_features.feedback_loops = !(disabled_features & FEATURE_MASK_FEEDBACK_LOOPS); + m_features.texture_buffers = !HasCreateFlag(create_flags, CreateFlags::DisableTextureBuffers); + m_features.feedback_loops = !HasCreateFlag(create_flags, CreateFlags::DisableFeedbackLoops); #ifdef __APPLE__ // Partial texture buffer uploads appear to be broken in macOS/MoltenVK. @@ -2520,8 +2520,9 @@ void VulkanDevice::SetFeatures(FeatureMask disabled_features, VkPhysicalDevice p if (m_features.texture_buffers_emulated_with_ssbo) WARNING_LOG("Emulating texture buffers with SSBOs."); - m_features.geometry_shaders = !(disabled_features & FEATURE_MASK_GEOMETRY_SHADERS) && vk_features.geometryShader; - m_features.compute_shaders = !(disabled_features & FEATURE_MASK_COMPUTE_SHADERS); + m_features.geometry_shaders = + !HasCreateFlag(create_flags, CreateFlags::DisableGeometryShaders) && vk_features.geometryShader; + m_features.compute_shaders = !HasCreateFlag(create_flags, CreateFlags::DisableComputeShaders); m_features.partial_msaa_resolve = true; m_features.memory_import = m_optional_extensions.vk_ext_external_memory_host; @@ -2532,12 +2533,12 @@ void VulkanDevice::SetFeatures(FeatureMask disabled_features, VkPhysicalDevice p m_features.pipeline_cache = true; m_features.prefer_unused_textures = true; m_features.raster_order_views = - (!(disabled_features & FEATURE_MASK_RASTER_ORDER_VIEWS) && vk_features.fragmentStoresAndAtomics && + (!!HasCreateFlag(create_flags, CreateFlags::DisableRasterOrderViews) && vk_features.fragmentStoresAndAtomics && m_optional_extensions.vk_ext_fragment_shader_interlock); // Same feature bit for both. m_features.dxt_textures = m_features.bptc_textures = - (!(disabled_features & FEATURE_MASK_COMPRESSED_TEXTURES) && vk_features.textureCompressionBC); + (!HasCreateFlag(create_flags, CreateFlags::DisableCompressedTextures) && vk_features.textureCompressionBC); } GPUDriverType VulkanDevice::GuessDriverType(const VkPhysicalDeviceProperties& device_properties, diff --git a/src/util/vulkan_device.h b/src/util/vulkan_device.h index c870566c4..614e3a638 100644 --- a/src/util/vulkan_device.h +++ b/src/util/vulkan_device.h @@ -241,7 +241,7 @@ public: void UnbindTextureBuffer(VulkanTextureBuffer* buf); protected: - bool CreateDeviceAndMainSwapChain(std::string_view adapter, FeatureMask disabled_features, const WindowInfo& wi, + bool CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) override; @@ -329,16 +329,16 @@ private: static bool SelectInstanceExtensions(ExtensionList* extension_list, const WindowInfo& wi, OptionalExtensions* oe, bool enable_debug_utils); bool CreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surface, bool enable_validation_layer, - FeatureMask disabled_features, Error* error); + CreateFlags create_flags, Error* error); bool EnableOptionalDeviceExtensions(VkPhysicalDevice physical_device, std::span available_extensions, ExtensionList& enabled_extensions, VkPhysicalDeviceFeatures& enabled_features, bool enable_surface, Error* error); - void SetFeatures(FeatureMask disabled_features, VkPhysicalDevice physical_device, + void SetFeatures(CreateFlags create_flags, VkPhysicalDevice physical_device, const VkPhysicalDeviceFeatures& vk_features); static GPUDriverType GuessDriverType(const VkPhysicalDeviceProperties& device_properties, - const VkPhysicalDeviceDriverProperties& driver_properties); + const VkPhysicalDeviceDriverProperties& driver_properties); static u32 GetMaxMultisamples(VkPhysicalDevice physical_device, const VkPhysicalDeviceProperties& properties); bool CreateAllocator();