From d6fe5d4ba039719af190673313ef72c6ad4e09fe Mon Sep 17 00:00:00 2001 From: xebra Date: Tue, 31 Jan 2017 23:11:40 +0900 Subject: [PATCH 1/5] Add supports floating-point-texture into GL extensions. --- ext/native/gfx_es2/gpu_features.cpp | 2 ++ ext/native/gfx_es2/gpu_features.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ext/native/gfx_es2/gpu_features.cpp b/ext/native/gfx_es2/gpu_features.cpp index 6c625a7bde..ca58326e41 100644 --- a/ext/native/gfx_es2/gpu_features.cpp +++ b/ext/native/gfx_es2/gpu_features.cpp @@ -266,6 +266,7 @@ void CheckGLExtensions() { gl_extensions.EXT_copy_image = strstr(extString, "GL_EXT_copy_image") != 0; gl_extensions.ARB_copy_image = strstr(extString, "GL_ARB_copy_image") != 0; gl_extensions.ARB_vertex_array_object = strstr(extString, "GL_ARB_vertex_array_object") != 0; + gl_extensions.ARB_texture_float = strstr(extString, "GL_ARB_texture_float") != 0; if (gl_extensions.IsGLES) { gl_extensions.OES_texture_npot = strstr(extString, "OES_texture_npot") != 0; @@ -278,6 +279,7 @@ void CheckGLExtensions() { gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0; + gl_extensions.OES_texture_float = strstr(extString, "OES_texture_float") != 0; #if defined(__ANDROID__) // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. diff --git a/ext/native/gfx_es2/gpu_features.h b/ext/native/gfx_es2/gpu_features.h index fdd444f00a..c67f03a001 100644 --- a/ext/native/gfx_es2/gpu_features.h +++ b/ext/native/gfx_es2/gpu_features.h @@ -47,6 +47,7 @@ struct GLExtensions { bool OES_mapbuffer; bool OES_vertex_array_object; bool OES_copy_image; + bool OES_texture_float; // ARB bool ARB_framebuffer_object; @@ -57,6 +58,7 @@ struct GLExtensions { bool ARB_conservative_depth; bool ARB_copy_image; bool ARB_vertex_array_object; + bool ARB_texture_float; // EXT bool EXT_swap_control_tear; From ce27f7b0b5c4cb655471e417b386c4c0407a636a Mon Sep 17 00:00:00 2001 From: xebra Date: Tue, 31 Jan 2017 23:18:27 +0900 Subject: [PATCH 2/5] Expand gpu features flags to 64-bit. --- GPU/GLES/GPU_GLES.cpp | 2 +- GPU/GPUState.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index b302dbaf57..152742d0a7 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -491,7 +491,7 @@ GPU_GLES::~GPU_GLES() { // Take the raw GL extension and versioning data and turn into feature flags. void GPU_GLES::CheckGPUFeatures() { - u32 features = 0; + u64 features = 0; if (gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended) { if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) { // Don't use this extension to off on sub 3.0 OpenGL versions as it does not seem reliable diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 8114faadc2..fe202e1279 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -441,11 +441,11 @@ struct UVScale { float uOff, vOff; }; -#define FLAG_BIT(x) (1 << x) +#define FLAG_BIT(x) (1ULL << x) // Some of these are OpenGL-specific even though this file is neutral, unfortunately. // Might want to move this mechanism into the backend later. -enum { +enum : u64 { GPU_SUPPORTS_DUALSOURCE_BLEND = FLAG_BIT(0), GPU_SUPPORTS_GLSL_ES_300 = FLAG_BIT(1), GPU_SUPPORTS_GLSL_330 = FLAG_BIT(2), @@ -482,7 +482,7 @@ struct KnownVertexBounds { }; struct GPUStateCache { - bool Supports(int flag) { return (featureFlags & flag) != 0; } + bool Supports(u64 flag) { return (featureFlags & flag) != 0; } uint64_t GetDirtyUniforms() { return dirty & DIRTY_ALL_UNIFORMS; } void Dirty(u64 what) { dirty |= what; @@ -497,7 +497,7 @@ struct GPUStateCache { return (dirty & what) != 0ULL; } - u32 featureFlags; + u64 featureFlags; u32 vertexAddr; u32 indexAddr; From 159aa1415d84756eea9efb00ebd63f7f54480dbc Mon Sep 17 00:00:00 2001 From: xebra Date: Tue, 31 Jan 2017 23:21:22 +0900 Subject: [PATCH 3/5] [spline/bezier]Add some gpu features flags for Instanced Tessellation. --- GPU/GLES/GPU_GLES.cpp | 11 +++++++++++ GPU/GPUState.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 152742d0a7..7ef0d2a1f4 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -580,6 +580,17 @@ void GPU_GLES::CheckGPUFeatures() { features |= GPU_SUPPORTS_ANISOTROPY; + if (gl_extensions.EXT_gpu_shader4) + features |= GPU_SUPPORTS_INSTANCE_RENDERING; + + int maxVertexTextureImageUnits; + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextureImageUnits); + if (maxVertexTextureImageUnits >= 3) // At least 3 for hardware tessellation + features |= GPU_SUPPORTS_VERTEX_TEXTURE_FETCH; + + if (gl_extensions.ARB_texture_float || gl_extensions.OES_texture_float) + features |= GPU_SUPPORTS_TEXTURE_FLOAT; + // If we already have a 16-bit depth buffer, we don't need to round. if (fbo_standard_z_depth() > 16) { if (!g_Config.bHighQualityDepth && (features & GPU_SUPPORTS_ACCURATE_DEPTH) != 0) { diff --git a/GPU/GPUState.h b/GPU/GPUState.h index fe202e1279..51ffffc1a6 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -472,6 +472,9 @@ enum : u64 { GPU_IS_MOBILE = FLAG_BIT(29), GPU_PREFER_CPU_DOWNLOAD = FLAG_BIT(30), GPU_PREFER_REVERSE_COLOR_ORDER = FLAG_BIT(31), + GPU_SUPPORTS_INSTANCE_RENDERING = FLAG_BIT(32), + GPU_SUPPORTS_VERTEX_TEXTURE_FETCH = FLAG_BIT(33), + GPU_SUPPORTS_TEXTURE_FLOAT = FLAG_BIT(34), }; struct KnownVertexBounds { From 6adddbbd38512a9d4c2f5fb1045b5a6733b7a54c Mon Sep 17 00:00:00 2001 From: xebra Date: Tue, 31 Jan 2017 23:29:13 +0900 Subject: [PATCH 4/5] [spline/bezier]Turn off Hardware Tessellation if device is unsupported. --- GPU/GLES/GPU_GLES.cpp | 12 ++++++++++++ UI/GameSettingsScreen.cpp | 17 ++++++++++++++++- UI/GameSettingsScreen.h | 1 + 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 7ef0d2a1f4..8c960b29b1 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -17,6 +17,7 @@ #include "base/logging.h" #include "profiler/profiler.h" +#include "i18n/i18n.h" #include "Common/ChunkFile.h" #include "Common/GraphicsContext.h" @@ -471,6 +472,17 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) shaderCachePath_ = GetSysDirectory(DIRECTORY_APP_CACHE) + "/" + g_paramSFO.GetValueString("DISC_ID") + ".glshadercache"; shaderManagerGL_->LoadAndPrecompile(shaderCachePath_); } + + if (g_Config.bHardwareTessellation) { + // Disable hardware tessellation if device is unsupported. + if (!gstate_c.Supports(GPU_SUPPORTS_INSTANCE_RENDERING | GPU_SUPPORTS_VERTEX_TEXTURE_FETCH | GPU_SUPPORTS_TEXTURE_FLOAT)) { + // TODO: Check unsupported device name list.(Above gpu features are supported but it has issues with weak gpu, memory, shader compiler etc...) + g_Config.bHardwareTessellation = false; + ERROR_LOG(G3D, "Hardware Tessellation is unsupported, falling back to software tessellation"); + I18NCategory *gr = GetI18NCategory("Graphics"); + host->NotifyUserMessage(gr->T("Turn off Hardware Tessellation - unsupported"), 2.5f, 0xFF3030FF); + } + } } GPU_GLES::~GPU_GLES() { diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 2b5476c3b7..00a638d8c3 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -76,6 +76,18 @@ bool GameSettingsScreen::UseVerticalLayout() const { return dp_yres > dp_xres * 1.1f; } +// This needs before run CheckGPUFeatures() +// TODO: Remove this if fix the issue +bool CheckSupportInstancedTessellation() { + int maxVertexTextureImageUnits; + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextureImageUnits); + bool vertexTexture = maxVertexTextureImageUnits >= 3; // At least 3 for hardware tessellation + bool instanceRendering = gl_extensions.EXT_gpu_shader4; + bool textureFloat = gl_extensions.ARB_texture_float || gl_extensions.OES_texture_float; + + return instanceRendering && vertexTexture && textureFloat; +} + void GameSettingsScreen::CreateViews() { GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); @@ -286,7 +298,8 @@ void GameSettingsScreen::CreateViews() { bezierChoiceDisable_ = g_Config.bSoftwareRendering || g_Config.bHardwareTessellation; return UI::EVENT_CONTINUE; }); - tessellationHW->SetEnabledPtr(&vtxCacheEnable_); // Same as Vertex Cache(!g_Config.bSoftwareRendering && g_Config.bHardwareTransform) + tessHWEnable_ = CheckSupportInstancedTessellation() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform; + tessellationHW->SetEnabledPtr(&tessHWEnable_); // In case we're going to add few other antialiasing option like MSAA in the future. // graphicsSettings->Add(new CheckBox(&g_Config.bFXAA, gr->T("FXAA"))); @@ -724,11 +737,13 @@ UI::EventReturn GameSettingsScreen::OnSoftwareRendering(UI::EventParams &e) { postProcEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE); resolutionEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE); bezierChoiceDisable_ = g_Config.bSoftwareRendering || g_Config.bHardwareTessellation; + tessHWEnable_ = CheckSupportInstancedTessellation() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform; return UI::EVENT_DONE; } UI::EventReturn GameSettingsScreen::OnHardwareTransform(UI::EventParams &e) { vtxCacheEnable_ = !g_Config.bSoftwareRendering && g_Config.bHardwareTransform; + tessHWEnable_ = CheckSupportInstancedTessellation() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform; return UI::EVENT_DONE; } diff --git a/UI/GameSettingsScreen.h b/UI/GameSettingsScreen.h index 64ff85a100..f37e6284fe 100644 --- a/UI/GameSettingsScreen.h +++ b/UI/GameSettingsScreen.h @@ -117,6 +117,7 @@ private: bool resolutionEnable_; bool bloomHackEnable_; bool bezierChoiceDisable_; + bool tessHWEnable_; }; class SettingInfoMessage : public UI::TextView { From 4fbc92d3f0cf83ed600ad9055d39c2d5aa312c31 Mon Sep 17 00:00:00 2001 From: xebra Date: Wed, 1 Feb 2017 00:14:38 +0900 Subject: [PATCH 5/5] Revert gpu features flags to 32-bit. --- GPU/GLES/GPU_GLES.cpp | 2 +- GPU/GPUState.h | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 8c960b29b1..a8704fdf15 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -503,7 +503,7 @@ GPU_GLES::~GPU_GLES() { // Take the raw GL extension and versioning data and turn into feature flags. void GPU_GLES::CheckGPUFeatures() { - u64 features = 0; + u32 features = 0; if (gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended) { if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) { // Don't use this extension to off on sub 3.0 OpenGL versions as it does not seem reliable diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 51ffffc1a6..4544530fe5 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -441,11 +441,11 @@ struct UVScale { float uOff, vOff; }; -#define FLAG_BIT(x) (1ULL << x) +#define FLAG_BIT(x) (1 << x) // Some of these are OpenGL-specific even though this file is neutral, unfortunately. // Might want to move this mechanism into the backend later. -enum : u64 { +enum { GPU_SUPPORTS_DUALSOURCE_BLEND = FLAG_BIT(0), GPU_SUPPORTS_GLSL_ES_300 = FLAG_BIT(1), GPU_SUPPORTS_GLSL_330 = FLAG_BIT(2), @@ -456,6 +456,9 @@ enum : u64 { GPU_SUPPORTS_WIDE_LINES = FLAG_BIT(7), GPU_SUPPORTS_ANISOTROPY = FLAG_BIT(8), GPU_USE_CLEAR_RAM_HACK = FLAG_BIT(9), + GPU_SUPPORTS_INSTANCE_RENDERING = FLAG_BIT(10), + GPU_SUPPORTS_VERTEX_TEXTURE_FETCH = FLAG_BIT(11), + GPU_SUPPORTS_TEXTURE_FLOAT = FLAG_BIT(12), GPU_SUPPORTS_LARGE_VIEWPORTS = FLAG_BIT(16), GPU_SUPPORTS_ACCURATE_DEPTH = FLAG_BIT(17), GPU_SUPPORTS_VAO = FLAG_BIT(18), @@ -472,9 +475,6 @@ enum : u64 { GPU_IS_MOBILE = FLAG_BIT(29), GPU_PREFER_CPU_DOWNLOAD = FLAG_BIT(30), GPU_PREFER_REVERSE_COLOR_ORDER = FLAG_BIT(31), - GPU_SUPPORTS_INSTANCE_RENDERING = FLAG_BIT(32), - GPU_SUPPORTS_VERTEX_TEXTURE_FETCH = FLAG_BIT(33), - GPU_SUPPORTS_TEXTURE_FLOAT = FLAG_BIT(34), }; struct KnownVertexBounds { @@ -485,7 +485,7 @@ struct KnownVertexBounds { }; struct GPUStateCache { - bool Supports(u64 flag) { return (featureFlags & flag) != 0; } + bool Supports(u32 flag) { return (featureFlags & flag) != 0; } uint64_t GetDirtyUniforms() { return dirty & DIRTY_ALL_UNIFORMS; } void Dirty(u64 what) { dirty |= what; @@ -500,7 +500,7 @@ struct GPUStateCache { return (dirty & what) != 0ULL; } - u64 featureFlags; + u32 featureFlags; u32 vertexAddr; u32 indexAddr;