From 28d267b7c0238e4430a60859406fbdb5f9cf960e Mon Sep 17 00:00:00 2001
From: Francisco Casas <fcasas@codeweavers.com>
Date: Fri, 3 May 2024 02:51:44 -0400
Subject: [PATCH] vkd3d-shader/hlsl: Allocate SM1 numeric uniforms in
 decreasing bind count.

---
 libs/vkd3d-shader/hlsl_codegen.c            | 36 +++++++++++++++++++++
 tests/hlsl/sm1-const-allocation.shader_test |  8 ++---
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index de77800027..2617904208 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -4553,11 +4553,47 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx,
     }
 }
 
+static void sort_uniform_by_numeric_bind_count(struct list *sorted, struct hlsl_ir_var *to_sort)
+{
+    struct hlsl_ir_var *var;
+
+    list_remove(&to_sort->extern_entry);
+
+    LIST_FOR_EACH_ENTRY(var, sorted, struct hlsl_ir_var, extern_entry)
+    {
+        uint32_t to_sort_size = to_sort->bind_count[HLSL_REGSET_NUMERIC];
+        uint32_t var_size = var->bind_count[HLSL_REGSET_NUMERIC];
+
+        if (to_sort_size > var_size)
+        {
+            list_add_before(&var->extern_entry, &to_sort->extern_entry);
+            return;
+        }
+    }
+
+    list_add_tail(sorted, &to_sort->extern_entry);
+}
+
+static void sort_uniforms_by_numeric_bind_count(struct hlsl_ctx *ctx)
+{
+    struct list sorted = LIST_INIT(sorted);
+    struct hlsl_ir_var *var, *next;
+
+    LIST_FOR_EACH_ENTRY_SAFE(var, next, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
+    {
+        if (var->is_uniform)
+            sort_uniform_by_numeric_bind_count(&sorted, var);
+    }
+    list_move_tail(&ctx->extern_vars, &sorted);
+}
+
 static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
 {
     struct register_allocator allocator = {0};
     struct hlsl_ir_var *var;
 
+    sort_uniforms_by_numeric_bind_count(ctx);
+
     LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
     {
         unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC];
diff --git a/tests/hlsl/sm1-const-allocation.shader_test b/tests/hlsl/sm1-const-allocation.shader_test
index e8a602551d..3b14c42a8c 100644
--- a/tests/hlsl/sm1-const-allocation.shader_test
+++ b/tests/hlsl/sm1-const-allocation.shader_test
@@ -50,7 +50,7 @@ uniform 0 float4 1 2 3 4
 uniform 4 float4 11 12 13 14
 uniform 8 float4 21 22 23 24
 draw quad
-todo probe all rgba (21, 22, 23, 11)
+probe all rgba (21, 22, 23, 11)
 
 
 [pixel shader]
@@ -76,7 +76,7 @@ uniform 8 float4 21 22 23 24
 uniform 12 float4 31 32 33 34
 uniform 16 float4 41 42 43 44
 draw quad
-todo probe all rgba (41, 21, 0, 0)
+probe all rgba (41, 21, 0, 0)
 
 
 [pixel shader]
@@ -224,7 +224,7 @@ uniform 20 float4 51 52 53 54
 uniform 24 float4 61 62 63 64
 uniform 28 float4 71 72 73 74
 draw quad
-todo probe all rgba (74, 31, 63, 0)
+probe all rgba (74, 31, 63, 0)
 
 
 [pixel shader]
@@ -253,7 +253,7 @@ uniform 0 float4 1 2 3 4
 uniform 4 float4 11 12 13 14
 uniform 8 float4 21 22 23 24
 draw quad
-todo probe all rgba (21, 22, 1, 11)
+probe all rgba (21, 22, 1, 11)
 
 
 [pixel shader]
-- 
GitLab