From fb166b5ff4b42279b2c63c69f5b5a35feafa259e Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Wed, 23 Jun 2021 01:39:21 -0300
Subject: [PATCH] shader: Emulate 64-bit integers when not supported

Useful for mobile and Intel Xe devices.
---
 src/shader_recompiler/frontend/maxwell/translate_program.cpp | 3 +++
 src/video_core/renderer_opengl/gl_device.cpp                 | 1 +
 src/video_core/renderer_opengl/gl_device.h                   | 5 +++++
 src/video_core/renderer_opengl/gl_shader_cache.cpp           | 2 +-
 src/video_core/renderer_vulkan/vk_pipeline_cache.cpp         | 2 +-
 src/video_core/vulkan_common/vulkan_device.h                 | 5 +++++
 6 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
index e728b43cc..c084f3400 100644
--- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
@@ -154,6 +154,9 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
     if (!host_info.support_float16) {
         Optimization::LowerFp16ToFp32(program);
     }
+    if (!host_info.support_int64) {
+        Optimization::LowerInt64ToInt32(program);
+    }
     Optimization::SsaRewritePass(program);
 
     Optimization::GlobalMemoryToStorageBufferPass(program);
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index 5838fc02f..b1b5ba1ab 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -159,6 +159,7 @@ Device::Device() {
     has_debugging_tool_attached = IsDebugToolAttached(extensions);
     has_depth_buffer_float = HasExtension(extensions, "GL_NV_depth_buffer_float");
     has_nv_gpu_shader_5 = GLAD_GL_NV_gpu_shader5;
+    has_shader_int64 = HasExtension(extensions, "GL_ARB_gpu_shader_int64");
     has_amd_shader_half_float = GLAD_GL_AMD_gpu_shader_half_float;
     has_sparse_texture_2 = GLAD_GL_ARB_sparse_texture2;
     warp_size_potentially_larger_than_guest = !is_nvidia && !is_intel;
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index 0c9d6fe31..0bd277d38 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -124,6 +124,10 @@ public:
         return has_nv_gpu_shader_5;
     }
 
+    bool HasShaderInt64() const {
+        return has_shader_int64;
+    }
+
     bool HasAmdShaderHalfFloat() const {
         return has_amd_shader_half_float;
     }
@@ -172,6 +176,7 @@ private:
     bool use_driver_cache{};
     bool has_depth_buffer_float{};
     bool has_nv_gpu_shader_5{};
+    bool has_shader_int64{};
     bool has_amd_shader_half_float{};
     bool has_sparse_texture_2{};
     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 c36b0d8cf..f2f18b18a 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -211,7 +211,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
       },
       host_info{
           .support_float16 = false,
-          .support_int64 = true,
+          .support_int64 = device.HasShaderInt64(),
       } {
     if (use_asynchronous_shaders) {
         workers = CreateWorkers();
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index e83628c13..ec06b124f 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -315,7 +315,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxw
     };
     host_info = Shader::HostTranslateInfo{
         .support_float16 = device.IsFloat16Supported(),
-        .support_int64 = true,
+        .support_int64 = device.IsShaderInt64Supported(),
     };
 }
 
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index 49605752d..40d00a52f 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -164,6 +164,11 @@ public:
         return is_formatless_image_load_supported;
     }
 
+    /// Returns true if shader int64 is supported.
+    bool IsShaderInt64Supported() const {
+        return is_shader_int64_supported;
+    }
+
     /// Returns true if shader int16 is supported.
     bool IsShaderInt16Supported() const {
         return is_shader_int16_supported;