diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index b302dbaf57..a8704fdf15 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() { @@ -580,6 +592,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 8114faadc2..4544530fe5 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -456,6 +456,9 @@ enum { 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), @@ -482,7 +485,7 @@ struct KnownVertexBounds { }; struct GPUStateCache { - bool Supports(int 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; 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 { 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;