From cfeb161c7ebf93bf6ac39e430fc998dc13abfc66 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sat, 31 Jul 2021 03:04:08 -0300
Subject: glsl/glasm: Pass and use scaling parameters in shaders

---
 src/shader_recompiler/backend/glasm/emit_glasm.cpp |  3 ++
 .../backend/glasm/emit_glasm_image.cpp             |  5 +--
 .../backend/glasm/emit_glasm_not_implemented.cpp   |  2 +-
 .../backend/glsl/emit_context.cpp                  |  2 +-
 .../backend/glsl/emit_glsl_context_get_set.cpp     |  2 +-
 .../backend/glsl/emit_glsl_image.cpp               |  4 +--
 .../renderer_opengl/gl_compute_pipeline.cpp        | 23 +++++++++-----
 .../renderer_opengl/gl_graphics_pipeline.cpp       | 36 ++++++++++++++--------
 src/video_core/renderer_opengl/gl_texture_cache.h  |  2 +-
 9 files changed, 51 insertions(+), 28 deletions(-)

(limited to 'src')

diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
index 4ce1c4f548..004658546b 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
@@ -448,6 +448,9 @@ std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, I
         header += fmt::format("SHARED_MEMORY {};", program.shared_memory_size);
         header += fmt::format("SHARED shared_mem[]={{program.sharedmem}};");
     }
+    if (program.info.uses_rescaling_uniform) {
+        header += "PARAM scaling[1]={program.local[0..0]};";
+    }
     header += "TEMP ";
     for (size_t index = 0; index < ctx.reg_alloc.NumUsedRegisters(); ++index) {
         header += fmt::format("R{},", index);
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
index 583ed3cf2a..05e88cd979 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
@@ -612,8 +612,9 @@ void EmitIsTextureScaled(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde
     if (!index.IsImmediate()) {
         throw NotImplementedException("Non-constant texture rescaling");
     }
-    UNIMPLEMENTED();
-    ctx.Add("MOV.S {}.x,-1;", inst);
+    ctx.Add("AND.U RC.x,scaling[0].x,{};"
+            "SNE.S {},RC.x,0;",
+            1u << index.U32(), ctx.reg_alloc.Define(inst));
 }
 
 void EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord,
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
index 77ee6dc0e0..c0f8ddcad6 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
@@ -211,7 +211,7 @@ void EmitYDirection(EmitContext& ctx, IR::Inst& inst) {
 }
 
 void EmitResolutionDownFactor(EmitContext& ctx, IR::Inst& inst) {
-    ctx.Add("MOV.F {}.x,program.env[0].x;", inst);
+    ctx.Add("MOV.F {}.x,scaling[0].y;", inst);
 }
 
 void EmitUndefU1(EmitContext& ctx, IR::Inst& inst) {
diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index 7c9ed9159c..97bd593027 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -394,7 +394,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
         }
     }
     if (info.uses_rescaling_uniform) {
-        header += "layout(location=0) uniform float down_factor;";
+        header += "layout(location=0) uniform vec4 scaling;";
     }
     DefineConstantBuffers(bindings);
     DefineStorageBuffers(bindings);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
index 3db3083f9d..542a792304 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
@@ -446,7 +446,7 @@ void EmitYDirection(EmitContext& ctx, IR::Inst& inst) {
 }
 
 void EmitResolutionDownFactor(EmitContext& ctx, IR::Inst& inst) {
-    ctx.AddF32("{}=down_factor;", inst);
+    ctx.AddF32("{}=scaling.y;", inst);
 }
 
 void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, std::string_view word_offset) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
index 099e0160b6..82b6f0d772 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
@@ -616,8 +616,8 @@ void EmitIsTextureScaled(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde
     if (!index.IsImmediate()) {
         throw NotImplementedException("Non-constant texture rescaling");
     }
-    UNIMPLEMENTED();
-    ctx.AddU1("{}=true;", inst);
+    const u32 image_index{index.U32()};
+    ctx.AddU1("{}=(ftou(scaling.x)&{})!=0;", inst, 1u << image_index);
 }
 
 void EmitBindlessImageSampleImplicitLod(EmitContext&) {
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
index a11bd5a02e..12093c3c44 100644
--- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
@@ -148,14 +148,8 @@ void ComputePipeline::Configure() {
     const f32 down_factor{is_rescaling ? config_down_factor : 1.0f};
     if (assembly_program.handle != 0) {
         program_manager.BindComputeAssemblyProgram(assembly_program.handle);
-        if (info.uses_rescaling_uniform) {
-            glProgramEnvParameter4fARB(GL_COMPUTE_PROGRAM_NV, 0, down_factor, 0.0f, 0.0f, 1.0f);
-        }
     } else {
         program_manager.BindComputeProgram(source_program.handle);
-        if (info.uses_rescaling_uniform) {
-            glProgramUniform1f(source_program.handle, 0, down_factor);
-        }
     }
     buffer_cache.UnbindComputeTextureBuffers();
     size_t texbuf_index{};
@@ -187,10 +181,16 @@ void ComputePipeline::Configure() {
     texture_binding += num_texture_buffers;
     image_binding += num_image_buffers;
 
+    u32 scaling_mask{};
     for (const auto& desc : info.texture_descriptors) {
         for (u32 index = 0; index < desc.count; ++index) {
             ImageView& image_view{texture_cache.GetImageView((views_it++)->id)};
-            textures[texture_binding++] = image_view.Handle(desc.type);
+            textures[texture_binding] = image_view.Handle(desc.type);
+            if (True(texture_cache.GetImage(image_view.image_id).flags &
+                     VideoCommon::ImageFlagBits::Rescaled)) {
+                scaling_mask |= 1u << texture_binding;
+            }
+            ++texture_binding;
         }
     }
     for (const auto& desc : info.image_descriptors) {
@@ -202,6 +202,15 @@ void ComputePipeline::Configure() {
             images[image_binding++] = image_view.StorageView(desc.type, desc.format);
         }
     }
+    if (info.uses_rescaling_uniform) {
+        const f32 float_scaling_mask{Common::BitCast<f32>(scaling_mask)};
+        if (assembly_program.handle != 0) {
+            glProgramLocalParameter4fARB(GL_COMPUTE_PROGRAM_NV, 0, float_scaling_mask, 0.0f, 0.0f,
+                                         0.0f);
+        } else {
+            glProgramUniform4f(source_program.handle, 0, float_scaling_mask, 0.0f, 0.0f, 0.0f);
+        }
+    }
     if (texture_binding != 0) {
         ASSERT(texture_binding == sampler_binding);
         glBindTextures(0, texture_binding, textures.data());
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
index 92fda9af01..01aa2897a2 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
@@ -444,23 +444,11 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
         WaitForBuild();
     }
     const bool use_assembly{assembly_programs[0].handle != 0};
-    const bool is_rescaling{texture_cache.IsRescaling()};
-    const f32 config_down_factor{Settings::values.resolution_info.down_factor};
-    const f32 down_factor{is_rescaling ? config_down_factor : 1.0f};
     if (use_assembly) {
         program_manager.BindAssemblyPrograms(assembly_programs, enabled_stages_mask);
     } else {
         program_manager.BindSourcePrograms(source_programs);
     }
-    for (size_t stage = 0; stage < source_programs.size(); ++stage) {
-        if (stage_infos[stage].uses_rescaling_uniform) {
-            if (use_assembly) {
-                glProgramEnvParameter4fARB(AssemblyStage(stage), 0, down_factor, 0.0f, 0.0f, 1.0f);
-            } else {
-                glProgramUniform1f(source_programs[stage].handle, 0, down_factor);
-            }
-        }
-    }
     const VideoCommon::ImageViewInOut* views_it{views.data()};
     GLsizei texture_binding = 0;
     GLsizei image_binding = 0;
@@ -476,11 +464,20 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
         views_it += num_texture_buffers[stage];
         views_it += num_image_buffers[stage];
 
+        u32 scaling_mask{};
+        u32 stage_texture_binding{};
+
         const auto& info{stage_infos[stage]};
         for (const auto& desc : info.texture_descriptors) {
             for (u32 index = 0; index < desc.count; ++index) {
                 ImageView& image_view{texture_cache.GetImageView((views_it++)->id)};
-                textures[texture_binding++] = image_view.Handle(desc.type);
+                textures[texture_binding] = image_view.Handle(desc.type);
+                if (True(texture_cache.GetImage(image_view.image_id).flags &
+                         VideoCommon::ImageFlagBits::Rescaled)) {
+                    scaling_mask |= 1u << stage_texture_binding;
+                }
+                ++texture_binding;
+                ++stage_texture_binding;
             }
         }
         for (const auto& desc : info.image_descriptors) {
@@ -492,6 +489,19 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
                 images[image_binding++] = image_view.StorageView(desc.type, desc.format);
             }
         }
+        if (info.uses_rescaling_uniform) {
+            const f32 float_scaling_mask{Common::BitCast<f32>(scaling_mask)};
+            const bool is_rescaling{texture_cache.IsRescaling()};
+            const f32 config_down_factor{Settings::values.resolution_info.down_factor};
+            const f32 down_factor{is_rescaling ? config_down_factor : 1.0f};
+            if (use_assembly) {
+                glProgramLocalParameter4fARB(AssemblyStage(stage), 0, float_scaling_mask,
+                                             down_factor, 0.0f, 0.0f);
+            } else {
+                glProgramUniform4f(source_programs[stage].handle, 0, float_scaling_mask,
+                                   down_factor, 0.0f, 0.0f);
+            }
+        }
     }};
     if constexpr (Spec::enabled_stages[0]) {
         prepare_stage(0);
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index e76ec522a8..28c91b368d 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -210,7 +210,7 @@ private:
     GLenum gl_internal_format = GL_NONE;
     GLenum gl_format = GL_NONE;
     GLenum gl_type = GL_NONE;
-    TextureCacheRuntime* runtime;
+    TextureCacheRuntime* runtime{};
 };
 
 class ImageView : public VideoCommon::ImageViewBase {
-- 
cgit v1.2.3-70-g09d2