From 1f594f3fb54132799753f7ea47c5c29d40cedefd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2018 12:06:29 -0800 Subject: [PATCH 1/5] GPU: Track draw in shader manager. With device restore etc. everywhere. --- GPU/Common/ShaderCommon.h | 9 ++++++++- GPU/D3D11/GPU_D3D11.cpp | 2 +- GPU/D3D11/ShaderManagerD3D11.cpp | 5 +++-- GPU/D3D11/ShaderManagerD3D11.h | 2 +- GPU/Directx9/GPU_DX9.cpp | 2 +- GPU/Directx9/ShaderManagerDX9.cpp | 4 +++- GPU/Directx9/ShaderManagerDX9.h | 2 +- GPU/GLES/ShaderManagerGLES.cpp | 6 ++++-- GPU/Vulkan/GPU_Vulkan.cpp | 4 ++-- GPU/Vulkan/ShaderManagerVulkan.cpp | 8 +++++--- GPU/Vulkan/ShaderManagerVulkan.h | 4 ++-- 11 files changed, 31 insertions(+), 17 deletions(-) diff --git a/GPU/Common/ShaderCommon.h b/GPU/Common/ShaderCommon.h index 1ef4ba51e4ef..b8827dd03d66 100644 --- a/GPU/Common/ShaderCommon.h +++ b/GPU/Common/ShaderCommon.h @@ -19,6 +19,10 @@ #include +namespace Draw { + class DrawContext; +} + enum ShaderLanguage { GLSL_140, GLSL_300, @@ -116,10 +120,13 @@ enum : uint64_t { class ShaderManagerCommon { public: - ShaderManagerCommon() {} + ShaderManagerCommon(Draw::DrawContext *draw) : draw_(draw) {} virtual ~ShaderManagerCommon() {} virtual void DirtyLastShader() = 0; + +protected: + Draw::DrawContext *draw_ = nullptr; }; struct TBuiltInResource; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index e29f46e296a3..e0ee48ef05ac 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -77,7 +77,7 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) stockD3D11.Create(device_); - shaderManagerD3D11_ = new ShaderManagerD3D11(device_, context_, featureLevel); + shaderManagerD3D11_ = new ShaderManagerD3D11(draw, device_, context_, featureLevel); framebufferManagerD3D11_ = new FramebufferManagerD3D11(draw); framebufferManager_ = framebufferManagerD3D11_; textureCacheD3D11_ = new TextureCacheD3D11(draw); diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp index c5c498f5f52e..70471523da36 100644 --- a/GPU/D3D11/ShaderManagerD3D11.cpp +++ b/GPU/D3D11/ShaderManagerD3D11.cpp @@ -26,6 +26,7 @@ #include "math/lin/matrix4x4.h" #include "math/math_util.h" #include "math/dataconv.h" +#include "thin3d/thin3d.h" #include "util/text/utf8.h" #include "Common/Common.h" #include "Core/Config.h" @@ -88,8 +89,8 @@ std::string D3D11VertexShader::GetShaderString(DebugShaderStringType type) const } } -ShaderManagerD3D11::ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel) - : device_(device), context_(context), featureLevel_(featureLevel), lastVShader_(nullptr), lastFShader_(nullptr) { +ShaderManagerD3D11::ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel) + : ShaderManagerCommon(draw), device_(device), context_(context), featureLevel_(featureLevel), lastVShader_(nullptr), lastFShader_(nullptr) { codeBuffer_ = new char[16384]; memset(&ub_base, 0, sizeof(ub_base)); memset(&ub_lights, 0, sizeof(ub_lights)); diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index 23ff3be8a524..5fa74991fedf 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -81,7 +81,7 @@ class D3D11PushBuffer; class ShaderManagerD3D11 : public ShaderManagerCommon { public: - ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel); + ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel); ~ShaderManagerD3D11(); void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 24d1f6967112..e7501ca702b6 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -61,7 +61,7 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) lastVsync_ = g_Config.bVSync ? 1 : 0; dxstate.SetVSyncInterval(g_Config.bVSync); - shaderManagerDX9_ = new ShaderManagerDX9(device_); + shaderManagerDX9_ = new ShaderManagerDX9(draw, device_); framebufferManagerDX9_ = new FramebufferManagerDX9(draw); framebufferManager_ = framebufferManagerDX9_; textureCacheDX9_ = new TextureCacheDX9(draw); diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index bdc7ce328ff8..a035c307d221 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -27,6 +27,7 @@ #include "math/lin/matrix4x4.h" #include "math/math_util.h" #include "math/dataconv.h" +#include "thin3d/thin3d.h" #include "util/text/utf8.h" #include "Common/Common.h" @@ -499,7 +500,8 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { } } -ShaderManagerDX9::ShaderManagerDX9(LPDIRECT3DDEVICE9 device) : device_(device), lastVShader_(nullptr), lastPShader_(nullptr) { +ShaderManagerDX9::ShaderManagerDX9(Draw::DrawContext *draw, LPDIRECT3DDEVICE9 device) + : ShaderManagerCommon(draw), device_(device), lastVShader_(nullptr), lastPShader_(nullptr) { codeBuffer_ = new char[16384]; } diff --git a/GPU/Directx9/ShaderManagerDX9.h b/GPU/Directx9/ShaderManagerDX9.h index 68fefdccc602..b59efe017541 100644 --- a/GPU/Directx9/ShaderManagerDX9.h +++ b/GPU/Directx9/ShaderManagerDX9.h @@ -77,7 +77,7 @@ class VSShader { class ShaderManagerDX9 : public ShaderManagerCommon { public: - ShaderManagerDX9(LPDIRECT3DDEVICE9 device); + ShaderManagerDX9(Draw::DrawContext *draw, LPDIRECT3DDEVICE9 device); ~ShaderManagerDX9(); void ClearCache(bool deleteThem); // TODO: deleteThem currently not respected diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 1c390a33b7f8..4c5e3d8f4456 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -28,11 +28,12 @@ #include "base/timeutil.h" #include "gfx/gl_debug_log.h" #include "gfx_es2/gpu_features.h" -#include "thin3d/GLRenderManager.h" #include "i18n/i18n.h" #include "math/math_util.h" #include "math/lin/matrix4x4.h" #include "profiler/profiler.h" +#include "thin3d/thin3d.h" +#include "thin3d/GLRenderManager.h" #include "Common/FileUtil.h" #include "Core/Config.h" @@ -571,7 +572,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) { } ShaderManagerGLES::ShaderManagerGLES(Draw::DrawContext *draw) - : lastShader_(nullptr), shaderSwitchDirtyUniforms_(0), diskCacheDirty_(false), fsCache_(16), vsCache_(16) { + : ShaderManagerCommon(draw), lastShader_(nullptr), shaderSwitchDirtyUniforms_(0), diskCacheDirty_(false), fsCache_(16), vsCache_(16) { render_ = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); codeBuffer_ = new char[16384]; lastFSID_.set_invalid(); @@ -610,6 +611,7 @@ void ShaderManagerGLES::DeviceLost() { void ShaderManagerGLES::DeviceRestore(Draw::DrawContext *draw) { render_ = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + draw_ = draw; } void ShaderManagerGLES::DirtyShader() { diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index b41eff7888eb..48d287e571c1 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -59,7 +59,7 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) UpdateVsyncInterval(true); CheckGPUFeatures(); - shaderManagerVulkan_ = new ShaderManagerVulkan(vulkan_); + shaderManagerVulkan_ = new ShaderManagerVulkan(draw, vulkan_); pipelineManager_ = new PipelineManagerVulkan(vulkan_); framebufferManagerVulkan_ = new FramebufferManagerVulkan(draw, vulkan_); framebufferManager_ = framebufferManagerVulkan_; @@ -535,7 +535,7 @@ void GPU_Vulkan::DeviceRestore() { drawEngine_.DeviceRestore(vulkan_, draw_); pipelineManager_->DeviceRestore(vulkan_); textureCacheVulkan_->DeviceRestore(vulkan_, draw_); - shaderManagerVulkan_->DeviceRestore(vulkan_); + shaderManagerVulkan_->DeviceRestore(vulkan_, draw_); depalShaderCache_.DeviceRestore(draw_, vulkan_); } diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 51a9f4a1758a..aa812c7de268 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -25,6 +25,7 @@ #include "math/math_util.h" #include "math/dataconv.h" #include "profiler/profiler.h" +#include "thin3d/thin3d.h" #include "util/text/utf8.h" #include "Common/Vulkan/VulkanContext.h" #include "Common/Vulkan/VulkanMemory.h" @@ -156,8 +157,8 @@ std::string VulkanVertexShader::GetShaderString(DebugShaderStringType type) cons } } -ShaderManagerVulkan::ShaderManagerVulkan(VulkanContext *vulkan) - : vulkan_(vulkan), lastVShader_(nullptr), lastFShader_(nullptr), fsCache_(16), vsCache_(16) { +ShaderManagerVulkan::ShaderManagerVulkan(Draw::DrawContext *draw, VulkanContext *vulkan) + : ShaderManagerCommon(draw), vulkan_(vulkan), lastVShader_(nullptr), lastFShader_(nullptr), fsCache_(16), vsCache_(16) { codeBuffer_ = new char[16384]; uboAlignment_ = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minUniformBufferOffsetAlignment; memset(&ub_base, 0, sizeof(ub_base)); @@ -174,8 +175,9 @@ ShaderManagerVulkan::~ShaderManagerVulkan() { delete[] codeBuffer_; } -void ShaderManagerVulkan::DeviceRestore(VulkanContext *vulkan) { +void ShaderManagerVulkan::DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw) { vulkan_ = vulkan; + draw_ = draw; uboAlignment_ = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minUniformBufferOffsetAlignment; } diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index 2bcce9332b3d..e77d1725dcf0 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -83,10 +83,10 @@ class VulkanPushBuffer; class ShaderManagerVulkan : public ShaderManagerCommon { public: - ShaderManagerVulkan(VulkanContext *vulkan); + ShaderManagerVulkan(Draw::DrawContext *draw, VulkanContext *vulkan); ~ShaderManagerVulkan(); - void DeviceRestore(VulkanContext *vulkan); + void DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw); void GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform); void ClearShaders(); From f8ce9b08baee637e7e085e11c533da6ae2cdfaaa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2018 12:19:34 -0800 Subject: [PATCH 2/5] Vulkan: Limit stencil workaround to Adreno 5xx. --- GPU/Common/ShaderId.cpp | 12 +++++++---- GPU/Common/ShaderId.h | 9 +++++++-- GPU/D3D11/ShaderManagerD3D11.cpp | 2 +- GPU/Directx9/ShaderManagerDX9.cpp | 2 +- GPU/GLES/ShaderManagerGLES.cpp | 2 +- GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp | 10 +++------- GPU/Vulkan/ShaderManagerVulkan.cpp | 2 +- ext/native/thin3d/thin3d.h | 21 ++++++++++++++++++++ ext/native/thin3d/thin3d_vulkan.cpp | 11 +++++++++- 9 files changed, 53 insertions(+), 18 deletions(-) diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index bd5f36f1bb57..f3a8e0922896 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -1,6 +1,7 @@ #include #include +#include "thin3d/thin3d.h" #include "Common/StringUtils.h" #include "Core/Config.h" @@ -225,7 +226,7 @@ std::string FragmentShaderDesc(const ShaderID &id) { // Here we must take all the bits of the gstate that determine what the fragment shader will // look like, and concatenate them together into an ID. -void ComputeFragmentShaderID(ShaderID *id_out) { +void ComputeFragmentShaderID(ShaderID *id_out, const Draw::Bugs &bugs) { ShaderID id; if (gstate.isModeClear()) { // We only need one clear shader, so let's ignore the rest of the bits. @@ -292,9 +293,6 @@ void ComputeFragmentShaderID(ShaderID *id_out) { if (stencilToAlpha != REPLACE_ALPHA_NO) { // 4 bits id.SetBits(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE, 4, ReplaceAlphaWithStencilType()); - } else { - // Use those bits instead for whether stencil output is disabled. - id.SetBit(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE, IsStencilTestOutputDisabled()); } // 2 bits. @@ -312,6 +310,12 @@ void ComputeFragmentShaderID(ShaderID *id_out) { id.SetBit(FS_BIT_FLATSHADE, doFlatShading); id.SetBit(FS_BIT_SHADER_DEPAL, useShaderDepal); + + if (g_Config.bVendorBugChecksEnabled) { + if (bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL)) { + id.SetBit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL, !IsStencilTestOutputDisabled() && !gstate.isDepthWriteEnabled()); + } + } } *id_out = id; diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index df0efb36d547..ec57b0273f00 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -87,7 +87,8 @@ enum { FS_BIT_FLATSHADE = 46, FS_BIT_BGRA_TEXTURE = 47, FS_BIT_TEST_DISCARD_TO_ZERO = 48, - // 49+ are free. + FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL = 49, + // 50+ are free. }; struct ShaderID { @@ -175,11 +176,15 @@ struct FShaderID : ShaderID { } }; +namespace Draw { +class Bugs; +} + void ComputeVertexShaderID(ShaderID *id, uint32_t vertexType, bool useHWTransform); // Generates a compact string that describes the shader. Useful in a list to get an overview // of the current flora of shaders. std::string VertexShaderDesc(const ShaderID &id); -void ComputeFragmentShaderID(ShaderID *id); +void ComputeFragmentShaderID(ShaderID *id, const Draw::Bugs &bugs); std::string FragmentShaderDesc(const ShaderID &id); diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp index 70471523da36..935c101e6848 100644 --- a/GPU/D3D11/ShaderManagerD3D11.cpp +++ b/GPU/D3D11/ShaderManagerD3D11.cpp @@ -191,7 +191,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader ** if (gstate_c.IsDirty(DIRTY_FRAGMENTSHADER_STATE)) { gstate_c.Clean(DIRTY_FRAGMENTSHADER_STATE); - ComputeFragmentShaderID(&FSID); + ComputeFragmentShaderID(&FSID, draw_->GetBugs()); } else { FSID = lastFSID_; } diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index a035c307d221..0fd16f2b3da3 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -556,7 +556,7 @@ VSShader *ShaderManagerDX9::ApplyShader(int prim, u32 vertType) { FShaderID FSID; if (gstate_c.IsDirty(DIRTY_FRAGMENTSHADER_STATE)) { gstate_c.Clean(DIRTY_FRAGMENTSHADER_STATE); - ComputeFragmentShaderID(&FSID); + ComputeFragmentShaderID(&FSID, draw_->GetBugs()); } else { FSID = lastFSID_; } diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 4c5e3d8f4456..585a6cf4597a 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -703,7 +703,7 @@ LinkedShader *ShaderManagerGLES::ApplyFragmentShader(VShaderID VSID, Shader *vs, FShaderID FSID; if (gstate_c.IsDirty(DIRTY_FRAGMENTSHADER_STATE)) { gstate_c.Clean(DIRTY_FRAGMENTSHADER_STATE); - ComputeFragmentShaderID(&FSID); + ComputeFragmentShaderID(&FSID, draw_->GetBugs()); } else { FSID = lastFSID_; } diff --git a/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp b/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp index 92196f2a1e31..361d38813c1e 100644 --- a/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp @@ -84,15 +84,11 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer, uint32_ const char *shading = doFlatShading ? "flat" : ""; bool earlyFragmentTests = ((!enableAlphaTest && !enableColorTest) || testForceToZero) && !gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT); - bool hasStencilOutput = stencilToAlpha != REPLACE_ALPHA_NO || id.Bit(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE) == 0; - - // TODO: This is a bug affecting shader cache generality - we CANNOT check anything but the shader ID and (indirectly) the game ID in here really. - // Need to move this check somehow to the shader ID generator. That's tricky though because it's generic... - bool isAdreno = vulkanVendorId == VULKAN_VENDOR_QUALCOMM && g_Config.bVendorBugChecksEnabled; + bool useAdrenoBugWorkaround = id.Bit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL); if (earlyFragmentTests) { WRITE(p, "layout (early_fragment_tests) in;\n"); - } else if (isAdreno && hasStencilOutput && !gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) { + } else if (useAdrenoBugWorkaround && !gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) { WRITE(p, "layout (depth_unchanged) out float gl_FragDepth;\n"); } @@ -588,7 +584,7 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer, uint32_ WRITE(p, " z = (1.0/65535.0) * floor(z * 65535.0);\n"); } WRITE(p, " gl_FragDepth = z;\n"); - } else if (!earlyFragmentTests && isAdreno && hasStencilOutput) { + } else if (!earlyFragmentTests && useAdrenoBugWorkaround) { // Adreno (and possibly MESA/others) apply early frag tests even with discard in the shader. // Writing depth prevents the bug, even with depth_unchanged specified. WRITE(p, " gl_FragDepth = gl_FragCoord.z;\n"); diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index aa812c7de268..10675fd5e1cd 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -240,7 +240,7 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader FShaderID FSID; if (gstate_c.IsDirty(DIRTY_FRAGMENTSHADER_STATE)) { gstate_c.Clean(DIRTY_FRAGMENTSHADER_STATE); - ComputeFragmentShaderID(&FSID); + ComputeFragmentShaderID(&FSID, draw_->GetBugs()); } else { FSID = lastFSID_; } diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 8baa8cc5e2a9..07b19c08e8b5 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -315,6 +315,23 @@ struct Viewport { float MaxDepth; }; +class Bugs { +public: + bool Has(uint32_t bug) const { + return (flags_ & (1 << bug)) != 0; + } + void Infest(uint32_t bug) { + flags_ |= (1 << bug); + } + + enum : uint32_t { + NO_DEPTH_CANNOT_DISCARD_STENCIL = 0, + }; + +protected: + uint32_t flags_ = 0; +}; + class RefCountedObject { public: RefCountedObject() : refcount_(1) {} @@ -524,6 +541,8 @@ class DrawContext { bool CreatePresets(); void DestroyPresets(); + Bugs GetBugs() const { return bugs_; } + virtual const DeviceCaps &GetDeviceCaps() const = 0; virtual uint32_t GetDataFormatSupport(DataFormat fmt) const = 0; virtual std::vector GetFeatureList() const { return std::vector(); } @@ -647,6 +666,8 @@ class DrawContext { int targetWidth_; int targetHeight_; + + Bugs bugs_; }; extern const UniformBufferDesc UBPresetDesc; diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 7f8d36afac86..1a6ba3e216b5 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -762,7 +762,8 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) caps_.framebufferDepthCopySupported = true; // Will pretty much always be the case. caps_.preferredDepthBufferFormat = DataFormat::D24_S8; // TODO: Ask vulkan. - switch (vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID) { + auto deviceProps = vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()); + switch (deviceProps.vendorID) { case VULKAN_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break; case VULKAN_VENDOR_ARM: caps_.vendor = GPUVendor::VENDOR_ARM; break; case VULKAN_VENDOR_IMGTEC: caps_.vendor = GPUVendor::VENDOR_IMGTEC; break; @@ -773,6 +774,14 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) caps_.vendor = GPUVendor::VENDOR_UNKNOWN; } + if (caps_.vendor == GPUVendor::VENDOR_QUALCOMM) { + // Adreno 5xx devices, all known driver versions, fail to discard stencil when depth write is off. + // See: https://github.com/hrydgard/ppsspp/pull/11684 + if (deviceProps.deviceID >= 0x05000000 && deviceProps.deviceID < 0x06000000) { + bugs_.Infest(Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL); + } + } + device_ = vulkan->GetDevice(); queue_ = vulkan->GetGraphicsQueue(); From 9a3de5cb1c5d2d7a6db83ad42fc107ddfff3c0a9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2018 12:31:19 -0800 Subject: [PATCH 3/5] GPU: Move dual source blending bug check to Draw. This also allows the ini setting to avoid it on Intel. --- GPU/GLES/GPU_GLES.cpp | 36 +---------------------------- GPU/Vulkan/GPU_Vulkan.cpp | 16 +------------ ext/native/thin3d/thin3d.h | 1 + ext/native/thin3d/thin3d_gl.cpp | 35 ++++++++++++++++++++++++++++ ext/native/thin3d/thin3d_vulkan.cpp | 8 +++++++ 5 files changed, 46 insertions(+), 50 deletions(-) diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index cde3291767fc..3a37ba24d8be 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -142,26 +142,6 @@ GPU_GLES::~GPU_GLES() { delete textureCacheGL_; } -static constexpr int MakeIntelSimpleVer(int v1, int v2, int v3) { - return (v1 << 16) | (v2 << 8) | v3; -} - -static bool HasIntelDualSrcBug(int versions[4]) { - // Intel uses a confusing set of at least 3 version numbering schemes. This is the one given to OpenGL. - switch (MakeIntelSimpleVer(versions[0], versions[1], versions[2])) { - case MakeIntelSimpleVer(9, 17, 10): - case MakeIntelSimpleVer(9, 18, 10): - return false; - case MakeIntelSimpleVer(10, 18, 10): - return versions[3] < 4061; - case MakeIntelSimpleVer(10, 18, 14): - return versions[3] < 4080; - default: - // Older than above didn't support dual src anyway, newer should have the fix. - return false; - } -} - // Take the raw GL extension and versioning data and turn into feature flags. void GPU_GLES::CheckGPUFeatures() { u32 features = 0; @@ -170,21 +150,7 @@ void GPU_GLES::CheckGPUFeatures() { features |= GPU_SUPPORTS_VS_RANGE_CULLING; if (gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended) { - if (!gl_extensions.VersionGEThan(3, 0, 0)) { - // Don't use this extension on sub 3.0 OpenGL versions as it does not seem reliable - } else if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL) { - // Also on Intel, see https://github.com/hrydgard/ppsspp/issues/10117 - // TODO: Remove entirely sometime reasonably far in driver years after 2015. - const std::string ver = draw_->GetInfoString(Draw::InfoField::APIVERSION); - int versions[4]{}; - if (sscanf(ver.c_str(), "Build %d.%d.%d.%d", &versions[0], &versions[1], &versions[2], &versions[3]) == 4) { - if (!HasIntelDualSrcBug(versions)) { - features |= GPU_SUPPORTS_DUALSOURCE_BLEND; - } - } else { - features |= GPU_SUPPORTS_DUALSOURCE_BLEND; - } - } else { + if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) { features |= GPU_SUPPORTS_DUALSOURCE_BLEND; } } diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 48d287e571c1..286195898b2c 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -224,23 +224,9 @@ void GPU_Vulkan::CheckGPUFeatures() { features |= GPU_SUPPORTS_DEPTH_CLAMP; } if (vulkan_->GetFeaturesEnabled().dualSrcBlend) { - switch (vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID) { - // We thought we had a bug here on nVidia but turns out we accidentally #ifdef-ed out crucial - // code on Android. - case VULKAN_VENDOR_INTEL: - // Workaround for Intel driver bug. TODO: Re-enable after some driver version - break; - case VULKAN_VENDOR_AMD: - // See issue #10074, and also #10065 (AMD) and #10109 for the choice of the driver version to check for - if (vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).driverVersion >= 0x00407000) - features |= GPU_SUPPORTS_DUALSOURCE_BLEND; - break; - default: + if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) { features |= GPU_SUPPORTS_DUALSOURCE_BLEND; - break; } - if (!g_Config.bVendorBugChecksEnabled) - features |= GPU_SUPPORTS_DUALSOURCE_BLEND; } if (vulkan_->GetFeaturesEnabled().logicOp) { features |= GPU_SUPPORTS_LOGIC_OP; diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 07b19c08e8b5..8e8f5eb81de4 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -326,6 +326,7 @@ class Bugs { enum : uint32_t { NO_DEPTH_CANNOT_DISCARD_STENCIL = 0, + DUAL_SOURCE_BLENDING_BROKEN = 1, }; protected: diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 114253db787f..e3668b8b9756 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -503,6 +503,26 @@ class OpenGLContext : public DrawContext { FrameData frameData_[GLRenderManager::MAX_INFLIGHT_FRAMES]; }; +static constexpr int MakeIntelSimpleVer(int v1, int v2, int v3) { + return (v1 << 16) | (v2 << 8) | v3; +} + +static bool HasIntelDualSrcBug(int versions[4]) { + // Intel uses a confusing set of at least 3 version numbering schemes. This is the one given to OpenGL. + switch (MakeIntelSimpleVer(versions[0], versions[1], versions[2])) { + case MakeIntelSimpleVer(9, 17, 10): + case MakeIntelSimpleVer(9, 18, 10): + return false; + case MakeIntelSimpleVer(10, 18, 10): + return versions[3] < 4061; + case MakeIntelSimpleVer(10, 18, 14): + return versions[3] < 4080; + default: + // Older than above didn't support dual src anyway, newer should have the fix. + return false; + } +} + OpenGLContext::OpenGLContext() { // TODO: Detect more caps if (gl_extensions.IsGLES) { @@ -533,6 +553,21 @@ OpenGLContext::OpenGLContext() { for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { frameData_[i].push = renderManager_.CreatePushBuffer(i, GL_ARRAY_BUFFER, 64 * 1024); } + + if (!gl_extensions.VersionGEThan(3, 0, 0)) { + // Don't use this extension on sub 3.0 OpenGL versions as it does not seem reliable. + bugs_.Infest(Bugs::DUAL_SOURCE_BLENDING_BROKEN); + } else if (caps_.vendor == GPUVendor::VENDOR_INTEL) { + // Also on Intel, see https://github.com/hrydgard/ppsspp/issues/10117 + // TODO: Remove entirely sometime reasonably far in driver years after 2015. + const std::string ver = GetInfoString(Draw::InfoField::APIVERSION); + int versions[4]{}; + if (sscanf(ver.c_str(), "Build %d.%d.%d.%d", &versions[0], &versions[1], &versions[2], &versions[3]) == 4) { + if (HasIntelDualSrcBug(versions)) { + bugs_.Infest(Bugs::DUAL_SOURCE_BLENDING_BROKEN); + } + } + } } OpenGLContext::~OpenGLContext() { diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 1a6ba3e216b5..eaa6b0ad5259 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -780,6 +780,14 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) if (deviceProps.deviceID >= 0x05000000 && deviceProps.deviceID < 0x06000000) { bugs_.Infest(Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL); } + } else if (caps_.vendor == GPUVendor::VENDOR_AMD) { + // See issue #10074, and also #10065 (AMD) and #10109 for the choice of the driver version to check for. + if (deviceProps.driverVersion < 0x00407000) { + bugs_.Infest(Bugs::DUAL_SOURCE_BLENDING_BROKEN); + } + } else if (caps_.vendor == GPUVendor::VENDOR_INTEL) { + // Workaround for Intel driver bug. TODO: Re-enable after some driver version + bugs_.Infest(Bugs::DUAL_SOURCE_BLENDING_BROKEN); } device_ = vulkan->GetDevice(); From adeca2c3ba0023eab746aed1a40029053cddeb4e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2018 12:46:48 -0800 Subject: [PATCH 4/5] GLES: Move some vendor bug checks to Draw. --- GPU/GLES/TextureCacheGLES.cpp | 2 +- Qt/QtMain.h | 2 +- SDL/SDLGLGraphicsContext.h | 2 +- Windows/GPU/WindowsGLContext.cpp | 2 +- android/jni/AndroidEGLContext.h | 2 +- android/jni/AndroidJavaGLContext.h | 2 +- ext/native/gfx_es2/gpu_features.cpp | 7 ------- ext/native/gfx_es2/gpu_features.h | 2 -- ext/native/thin3d/GLRenderManager.cpp | 6 ++++-- ext/native/thin3d/GLRenderManager.h | 6 +++++- ext/native/thin3d/thin3d.h | 2 ++ ext/native/thin3d/thin3d_gl.cpp | 12 ++++++++++++ headless/SDLHeadlessHost.cpp | 2 +- ios/ViewController.mm | 2 +- libretro/LibretroGLContext.h | 2 +- 15 files changed, 32 insertions(+), 21 deletions(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 395651f24b29..9bfc2a6cfa8a 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -672,7 +672,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { } } else { // Avoid PowerVR driver bug - if (canAutoGen && w > 1 && h > 1 && !(h > w && (gl_extensions.bugs & BUG_PVR_GENMIPMAP_HEIGHT_GREATER))) { // Really! only seems to fail if height > width + if (canAutoGen && w > 1 && h > 1 && !(h > w && draw_->GetBugs().Has(Draw::Bugs::PVR_GENMIPMAP_HEIGHT_GREATER))) { // Really! only seems to fail if height > width // NOTICE_LOG(G3D, "Generating mipmap for texture sized %dx%d%d", w, h, (int)format); genMips = true; } else { diff --git a/Qt/QtMain.h b/Qt/QtMain.h index 70d89b88d8d3..3e165a8d9f8c 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -73,7 +73,7 @@ class QtGLGraphicsContext : public GraphicsContext { } void ThreadStart() override { - renderManager_->ThreadStart(); + renderManager_->ThreadStart(draw_); } bool ThreadFrame() override { diff --git a/SDL/SDLGLGraphicsContext.h b/SDL/SDLGLGraphicsContext.h index e0cb35470151..c32d10481463 100644 --- a/SDL/SDLGLGraphicsContext.h +++ b/SDL/SDLGLGraphicsContext.h @@ -32,7 +32,7 @@ class SDLGLGraphicsContext : public DummyGraphicsContext { } void ThreadStart() override { - renderManager_->ThreadStart(); + renderManager_->ThreadStart(draw_); } bool ThreadFrame() override { diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 002464cf2779..0701ffa4aac4 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -458,7 +458,7 @@ void WindowsGLContext::Resize() { } void WindowsGLContext::ThreadStart() { - renderManager_->ThreadStart(); + renderManager_->ThreadStart(draw_); } bool WindowsGLContext::ThreadFrame() { diff --git a/android/jni/AndroidEGLContext.h b/android/jni/AndroidEGLContext.h index 35ae334294c5..45b33f82410b 100644 --- a/android/jni/AndroidEGLContext.h +++ b/android/jni/AndroidEGLContext.h @@ -21,7 +21,7 @@ class AndroidEGLGraphicsContext : public AndroidGraphicsContext { } void ThreadStart() override { - renderManager_->ThreadStart(); + renderManager_->ThreadStart(draw_); } bool ThreadFrame() override { diff --git a/android/jni/AndroidJavaGLContext.h b/android/jni/AndroidJavaGLContext.h index 99db77dfcb24..05d3966896bb 100644 --- a/android/jni/AndroidJavaGLContext.h +++ b/android/jni/AndroidJavaGLContext.h @@ -34,7 +34,7 @@ class AndroidJavaEGLGraphicsContext : public AndroidGraphicsContext { } void ThreadStart() override { - renderManager_->ThreadStart(); + renderManager_->ThreadStart(draw_); } bool ThreadFrame() override { diff --git a/ext/native/gfx_es2/gpu_features.cpp b/ext/native/gfx_es2/gpu_features.cpp index 35b1e421c9ff..c6b71021affa 100644 --- a/ext/native/gfx_es2/gpu_features.cpp +++ b/ext/native/gfx_es2/gpu_features.cpp @@ -114,13 +114,6 @@ void ProcessGPUFeatures() { WLOG("GL DRIVER BUG: PVR with bad precision"); gl_extensions.bugs |= BUG_PVR_SHADER_PRECISION_BAD; } - gl_extensions.bugs |= BUG_PVR_GENMIPMAP_HEIGHT_GREATER; - } - - // TODO: Make this check more lenient. Disabled for all right now - // because it murders performance on Mali. - if (gl_extensions.gpuVendor != GPU_VENDOR_NVIDIA) { - gl_extensions.bugs |= BUG_ANY_MAP_BUFFER_RANGE_SLOW; } } diff --git a/ext/native/gfx_es2/gpu_features.h b/ext/native/gfx_es2/gpu_features.h index 6764d08105d0..80cbc906bd06 100644 --- a/ext/native/gfx_es2/gpu_features.h +++ b/ext/native/gfx_es2/gpu_features.h @@ -22,8 +22,6 @@ enum { BUG_FBO_UNUSABLE = 1, BUG_PVR_SHADER_PRECISION_BAD = 2, BUG_PVR_SHADER_PRECISION_TERRIBLE = 4, - BUG_PVR_GENMIPMAP_HEIGHT_GREATER = 8, - BUG_ANY_MAP_BUFFER_RANGE_SLOW = 16, }; // Extensions to look at using: diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index bc9defccadc2..b7585b7a033c 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -2,6 +2,7 @@ #include "GLRenderManager.h" #include "gfx_es2/gpu_features.h" +#include "thin3d/thin3d.h" #include "thread/threadutil.h" #include "base/logging.h" #include "GPU/GPUState.h" @@ -89,12 +90,13 @@ GLRenderManager::~GLRenderManager() { _assert_(deleter_.IsEmpty()); } -void GLRenderManager::ThreadStart() { +void GLRenderManager::ThreadStart(Draw::DrawContext *draw) { queueRunner_.CreateDeviceObjects(); threadFrame_ = threadInitFrame_; renderThreadId = std::this_thread::get_id(); - bool mapBuffers = (gl_extensions.bugs & BUG_ANY_MAP_BUFFER_RANGE_SLOW) == 0; + // Don't save draw, we don't want any thread safety confusion. + bool mapBuffers = draw->GetBugs().Has(Draw::Bugs::ANY_MAP_BUFFER_RANGE_SLOW); bool hasBufferStorage = gl_extensions.ARB_buffer_storage || gl_extensions.EXT_buffer_storage; if (!gl_extensions.VersionGEThan(3, 0, 0) && gl_extensions.IsGLES && !hasBufferStorage) { // Force disable if it wouldn't work anyway. diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 719ad156e6ac..7b38c024e86d 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -19,6 +19,10 @@ class GLRInputLayout; class GLPushBuffer; +namespace Draw { +class DrawContext; +} + class GLRTexture { public: ~GLRTexture() { @@ -365,7 +369,7 @@ class GLRenderManager { GLRenderManager(); ~GLRenderManager(); - void ThreadStart(); + void ThreadStart(Draw::DrawContext *draw); void ThreadEnd(); bool ThreadFrame(); // Returns false to request exiting the loop. diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 8e8f5eb81de4..1d0e28a98389 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -327,6 +327,8 @@ class Bugs { enum : uint32_t { NO_DEPTH_CANNOT_DISCARD_STENCIL = 0, DUAL_SOURCE_BLENDING_BROKEN = 1, + ANY_MAP_BUFFER_RANGE_SLOW = 2, + PVR_GENMIPMAP_HEIGHT_GREATER = 3, }; protected: diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index e3668b8b9756..1d812ce4966d 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -568,6 +568,18 @@ OpenGLContext::OpenGLContext() { } } } + + // TODO: Make this check more lenient. Disabled for all right now + // because it murders performance on Mali. + if (caps_.vendor != GPUVendor::VENDOR_NVIDIA) { + bugs_.Infest(Bugs::ANY_MAP_BUFFER_RANGE_SLOW); + } + + if (caps_.vendor == GPUVendor::VENDOR_IMGTEC) { + // See https://github.com/hrydgard/ppsspp/commit/8974cd675e538f4445955e3eac572a9347d84232 + // TODO: Should this workaround be removed for newer devices/drivers? + bugs_.Infest(Bugs::PVR_GENMIPMAP_HEIGHT_GREATER); + } } OpenGLContext::~OpenGLContext() { diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp index 1545a53f9cec..c5702eabc414 100644 --- a/headless/SDLHeadlessHost.cpp +++ b/headless/SDLHeadlessHost.cpp @@ -76,7 +76,7 @@ class GLDummyGraphicsContext : public DummyGraphicsContext { } void ThreadStart() override { - renderManager_->ThreadStart(); + renderManager_->ThreadStart(draw_); } bool ThreadFrame() override { diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 61c2eee554e3..0c5c5ae5dad8 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -51,7 +51,7 @@ return draw_; } void ThreadStart() override { - renderManager_->ThreadStart(); + renderManager_->ThreadStart(draw_); } bool ThreadFrame() override { diff --git a/libretro/LibretroGLContext.h b/libretro/LibretroGLContext.h index 8a91044fdd0a..b85c8affb026 100644 --- a/libretro/LibretroGLContext.h +++ b/libretro/LibretroGLContext.h @@ -26,7 +26,7 @@ class LibretroGLContext : public LibretroHWRenderContext { g_defaultFBO = hw_render_.get_current_framebuffer(); } - void ThreadStart() override { renderManager_->ThreadStart(); } + void ThreadStart() override { renderManager_->ThreadStart(draw_); } bool ThreadFrame() override { return renderManager_->ThreadFrame(); } void ThreadEnd() override { renderManager_->ThreadEnd(); } void StopThread() override { From 58ef662a65ecff21dbd742b397669fafcad53c33 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2018 12:47:06 -0800 Subject: [PATCH 5/5] GLES: Remove FBO_UNUSABLE bug check. Was no longer affecting behavior... --- ext/native/gfx_es2/gpu_features.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ext/native/gfx_es2/gpu_features.cpp b/ext/native/gfx_es2/gpu_features.cpp index c6b71021affa..9ff80a51dea6 100644 --- a/ext/native/gfx_es2/gpu_features.cpp +++ b/ext/native/gfx_es2/gpu_features.cpp @@ -98,11 +98,6 @@ void ProcessGPUFeatures() { DLOG("Checking for GL driver bugs... vendor=%i model='%s'", (int)gl_extensions.gpuVendor, gl_extensions.model); - // Should be table driven instead, this is a quick hack for Galaxy Y - if (System_GetProperty(SYSPROP_NAME) == "samsung:GT-S5360") { - gl_extensions.bugs |= BUG_FBO_UNUSABLE; - } - if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { if (!strcmp(gl_extensions.model, "PowerVR SGX 543") || !strcmp(gl_extensions.model, "PowerVR SGX 540") ||