GPUDevice: Move options to create flags

And add prefer-GLES-context as a config setting, instead of
environment variable.
pull/3526/head
Stenzek 2 months ago
parent c1d0cf3906
commit 6e926041e5
No known key found for this signature in database

@ -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.");

@ -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<GPUDevice::FeatureMask>(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());

@ -240,6 +240,7 @@ void Settings::Load(const SettingsInterface& si, const SettingsInterface& contro
gpu_multisamples = static_cast<u8>(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 ||

@ -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
};

@ -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. <strong>Only for developer use.</strong>"));
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. <strong>Only for developer use.</strong>"));

@ -1362,62 +1362,69 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="preferGLESContext">
<property name="text">
<string>Prefer OpenGL ES Context</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="disableShaderCache">
<property name="text">
<string>Disable Shader Cache</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="0">
<widget class="QCheckBox" name="disableCompressedTextures">
<property name="text">
<string>Disable Compressed Textures</string>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="2" column="1">
<widget class="QCheckBox" name="disableDualSource">
<property name="text">
<string>Disable Dual-Source Blending</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="0">
<widget class="QCheckBox" name="disableFramebufferFetch">
<property name="text">
<string>Disable Framebuffer Fetch</string>
</property>
</widget>
</item>
<item row="3" column="0">
<item row="3" column="1">
<widget class="QCheckBox" name="disableTextureBuffers">
<property name="text">
<string>Disable Texture Buffers</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="0">
<widget class="QCheckBox" name="disableTextureCopyToSelf">
<property name="text">
<string>Disable Texture Copy To Self</string>
</property>
</widget>
</item>
<item row="4" column="0">
<item row="4" column="1">
<widget class="QCheckBox" name="disableMemoryImport">
<property name="text">
<string>Disable Memory Import</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="0">
<widget class="QCheckBox" name="disableRasterOrderViews">
<property name="text">
<string>Disable Rasterizer Order Views</string>
</property>
</widget>
</item>
<item row="5" column="0">
<item row="5" column="1">
<widget class="QCheckBox" name="disableComputeShaders">
<property name="text">
<string>Disable Compute Shaders</string>

@ -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<bool> 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<ID3D11Device> temp_device;
ComPtr<ID3D11DeviceContext> 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<UINT>(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,

@ -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<bool> 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();

@ -148,7 +148,7 @@ D3D12Device::ComPtr<ID3D12RootSignature> 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<ID3D12Debug1> 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,

@ -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<bool> 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();

@ -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<bool> 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)

@ -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<float, 4> RGBA8ToFloat(u32 rgba);
/// Returns true if the given device creation flag is present.
static constexpr bool HasCreateFlag(CreateFlags flags, CreateFlags flag)
{
return ((static_cast<u32>(flags) & static_cast<u32>(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<bool> 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<bool> 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<GPUDevice> 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<GPUTexture>(tex));

@ -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<bool> 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<GPUShader> CreateShaderFromMSL(GPUShaderStage stage, std::string_view source,

@ -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()

@ -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> OpenGLContext::Create(WindowInfo& wi, SurfaceHandle* surface, Error* error)
std::unique_ptr<OpenGLContext> OpenGLContext::Create(WindowInfo& wi, SurfaceHandle* surface, bool prefer_gles_context,
Error* error)
{
static constexpr std::array<Version, 14> vlist = {{{Profile::Core, 4, 6},
{Profile::Core, 4, 5},
@ -140,7 +126,7 @@ std::unique_ptr<OpenGLContext> OpenGLContext::Create(WindowInfo& wi, SurfaceHand
{Profile::Core, 3, 0}}};
std::span<const Version> versions_to_try = vlist;
if (ShouldPreferESContext())
if (prefer_gles_context)
{
// move ES versions to the front
Version* new_versions_to_try = static_cast<Version*>(alloca(sizeof(Version) * versions_to_try.size()));

@ -49,7 +49,8 @@ public:
virtual bool SetSwapInterval(s32 interval, Error* error = nullptr) = 0;
virtual std::unique_ptr<OpenGLContext> CreateSharedContext(WindowInfo& wi, SurfaceHandle* surface, Error* error) = 0;
static std::unique_ptr<OpenGLContext> Create(WindowInfo& wi, SurfaceHandle* surface, Error* error);
static std::unique_ptr<OpenGLContext> Create(WindowInfo& wi, SurfaceHandle* surface, bool prefer_gles_context,
Error* error);
protected:
Version m_version = {};

@ -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<bool> 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<const char*>(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;

@ -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<bool> 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();

@ -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<bool> 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<u16>(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,

@ -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<bool> 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<const VkExtensionProperties> 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();

Loading…
Cancel
Save