From 3b339fbbf65a50ec2ec8baacd175ca7577c3b8bd Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Mon, 14 Jun 2021 23:33:26 -0400
Subject: glsl: Conditionally use fine/coarse derivatives based on device
 support

---
 .../backend/glsl/emit_context.cpp                  |  3 +++
 .../backend/glsl/emit_glsl_warp.cpp                | 28 ++++++++++++++++++----
 src/shader_recompiler/profile.h                    |  1 +
 src/video_core/renderer_opengl/gl_shader_cache.cpp |  1 +
 4 files changed, 29 insertions(+), 4 deletions(-)

(limited to 'src')

diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index e18f8257ea..0e8fe017d2 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -395,6 +395,9 @@ void EmitContext::SetupExtensions() {
     if (info.uses_typeless_image_reads || info.uses_typeless_image_writes) {
         header += "#extension GL_EXT_shader_image_load_formatted : enable\n";
     }
+    if (info.uses_derivatives && profile.support_gl_derivative_control) {
+        header += "#extension GL_ARB_derivative_control : enable\n";
+    }
 }
 
 void EmitContext::DefineConstantBuffers(Bindings& bindings) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
index 4d418cbbc7..a982dd8a27 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
@@ -180,18 +180,38 @@ void EmitFSwizzleAdd(EmitContext& ctx, IR::Inst& inst, std::string_view op_a, st
 }
 
 void EmitDPdxFine(EmitContext& ctx, IR::Inst& inst, std::string_view op_a) {
-    ctx.AddF32("{}=dFdxFine({});", inst, op_a);
+    if (ctx.profile.support_gl_derivative_control) {
+        ctx.AddF32("{}=dFdxFine({});", inst, op_a);
+    } else {
+        LOG_WARNING(Shader_GLSL, "Device does not support dFdxFine, fallback to dFdx");
+        ctx.AddF32("{}=dFdx({});", inst, op_a);
+    }
 }
 
 void EmitDPdyFine(EmitContext& ctx, IR::Inst& inst, std::string_view op_a) {
-    ctx.AddF32("{}=dFdyFine({});", inst, op_a);
+    if (ctx.profile.support_gl_derivative_control) {
+        ctx.AddF32("{}=dFdyFine({});", inst, op_a);
+    } else {
+        LOG_WARNING(Shader_GLSL, "Device does not support dFdyFine, fallback to dFdy");
+        ctx.AddF32("{}=dFdy({});", inst, op_a);
+    }
 }
 
 void EmitDPdxCoarse(EmitContext& ctx, IR::Inst& inst, std::string_view op_a) {
-    ctx.AddF32("{}=dFdxCoarse({});", inst, op_a);
+    if (ctx.profile.support_gl_derivative_control) {
+        ctx.AddF32("{}=dFdxCoarse({});", inst, op_a);
+    } else {
+        LOG_WARNING(Shader_GLSL, "Device does not support dFdxCoarse, fallback to dFdx");
+        ctx.AddF32("{}=dFdx({});", inst, op_a);
+    }
 }
 
 void EmitDPdyCoarse(EmitContext& ctx, IR::Inst& inst, std::string_view op_a) {
-    ctx.AddF32("{}=dFdyCoarse({});", inst, op_a);
+    if (ctx.profile.support_gl_derivative_control) {
+        ctx.AddF32("{}=dFdyCoarse({});", inst, op_a);
+    } else {
+        LOG_WARNING(Shader_GLSL, "Device does not support dFdyCoarse, fallback to dFdy");
+        ctx.AddF32("{}=dFdy({});", inst, op_a);
+    }
 }
 } // namespace Shader::Backend::GLSL
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h
index 6db794e910..e8cfc03af3 100644
--- a/src/shader_recompiler/profile.h
+++ b/src/shader_recompiler/profile.h
@@ -89,6 +89,7 @@ struct Profile {
     bool support_gl_warp_intrinsics{};
     bool support_gl_variable_aoffi{};
     bool support_gl_sparse_textures{};
+    bool support_gl_derivative_control{};
 
     bool warp_size_potentially_larger_than_guest{};
 
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 5ffe28d45d..fedbce2f05 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -187,6 +187,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
           .support_gl_warp_intrinsics = false,
           .support_gl_variable_aoffi = device.HasVariableAoffi(),
           .support_gl_sparse_textures = device.HasSparseTexture2(),
+          .support_gl_derivative_control = device.HasDerivativeControl(),
 
           .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyLargerThanGuest(),
 
-- 
cgit v1.2.3-70-g09d2