From 947e14d3be0f7c5e4b6f77df204ec675b8e9e719 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Fri, 27 Dec 2019 22:16:14 -0300
Subject: [PATCH] Reimplement limited bindless textures support

---
 Ryujinx.Graphics.Gpu/Engine/Compute.cs        |  9 ++++++-
 Ryujinx.Graphics.Gpu/Engine/Methods.cs        |  9 ++++++-
 .../Image/TextureBindingInfo.cs               | 21 ++++++++++++++++
 .../Image/TextureBindingsManager.cs           | 25 ++++++++++++++++++-
 .../CodeGen/Glsl/Declarations.cs              |  2 ++
 Ryujinx.Graphics.Shader/TextureDescriptor.cs  |  4 +--
 6 files changed, 65 insertions(+), 5 deletions(-)

diff --git a/Ryujinx.Graphics.Gpu/Engine/Compute.cs b/Ryujinx.Graphics.Gpu/Engine/Compute.cs
index bbf1eeaae..d0df85a0b 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Compute.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Compute.cs
@@ -97,7 +97,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
                 Target target = GetTarget(descriptor.Type);
 
-                textureBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex);
+                if (descriptor.IsBindless)
+                {
+                    textureBindings[index] = new TextureBindingInfo(target, descriptor.CbufOffset, descriptor.CbufSlot);
+                }
+                else
+                {
+                    textureBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex);
+                }
             }
 
             _textureManager.SetComputeTextures(textureBindings);
diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
index 76b407cc2..0c103e0d8 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
@@ -694,7 +694,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
                     Target target = GetTarget(descriptor.Type);
 
-                    textureBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex);
+                    if (descriptor.IsBindless)
+                    {
+                        textureBindings[index] = new TextureBindingInfo(target, descriptor.CbufSlot, descriptor.CbufOffset);
+                    }
+                    else
+                    {
+                        textureBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex);
+                    }
                 }
 
                 _textureManager.SetGraphicsTextures(stage, textureBindings);
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs
index 19090ab33..042635eeb 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs
@@ -8,10 +8,31 @@ namespace Ryujinx.Graphics.Gpu.Image
 
         public int Handle { get; }
 
+        public bool IsBindless { get; }
+
+        public int CbufSlot   { get; }
+        public int CbufOffset { get; }
+
         public TextureBindingInfo(Target target, int handle)
         {
             Target = target;
             Handle = handle;
+
+            IsBindless = false;
+
+            CbufSlot   = 0;
+            CbufOffset = 0;
+        }
+
+        public TextureBindingInfo(Target target, int cbufSlot, int cbufOffset)
+        {
+            Target = target;
+            Handle = 0;
+
+            IsBindless = true;
+
+            CbufSlot   = cbufSlot;
+            CbufOffset = cbufOffset;
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
index ce58e5c54..0c09661fe 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
@@ -2,6 +2,7 @@ using Ryujinx.Graphics.GAL;
 using Ryujinx.Graphics.Gpu.State;
 using Ryujinx.Graphics.Shader;
 using System;
+using System.Runtime.InteropServices;
 
 namespace Ryujinx.Graphics.Gpu.Image
 {
@@ -133,7 +134,29 @@ namespace Ryujinx.Graphics.Gpu.Image
             {
                 TextureBindingInfo binding = _textureBindings[stageIndex][index];
 
-                int packedId = ReadPackedId(stageIndex, binding.Handle);
+                int packedId;
+
+                if (binding.IsBindless)
+                {
+                    ulong address;
+
+                    var bufferManager = _context.Methods.BufferManager;
+
+                    if (_isCompute)
+                    {
+                        address = bufferManager.GetComputeUniformBufferAddress(binding.CbufSlot);
+                    }
+                    else
+                    {
+                        address = bufferManager.GetGraphicsUniformBufferAddress(stageIndex, binding.CbufSlot);
+                    }
+
+                    packedId = MemoryMarshal.Cast<byte, int>(_context.PhysicalMemory.Read(address + (ulong)binding.CbufOffset * 4, 4))[0];
+                }
+                else
+                {
+                    packedId = ReadPackedId(stageIndex, binding.Handle);
+                }
 
                 int textureId = UnpackTextureId(packedId);
                 int samplerId;
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index bad5c00c7..200569c48 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -272,6 +272,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
                     AstOperand operand = texOp.GetSource(0) as AstOperand;
 
                     desc = new TextureDescriptor(samplerName, texOp.Type, operand.CbufSlot, operand.CbufOffset);
+
+                    context.TextureDescriptors.Add(desc);
                 }
                 else if ((texOp.Type & SamplerType.Indexed) != 0)
                 {
diff --git a/Ryujinx.Graphics.Shader/TextureDescriptor.cs b/Ryujinx.Graphics.Shader/TextureDescriptor.cs
index bfcdde590..fae9b58c3 100644
--- a/Ryujinx.Graphics.Shader/TextureDescriptor.cs
+++ b/Ryujinx.Graphics.Shader/TextureDescriptor.cs
@@ -13,11 +13,11 @@ namespace Ryujinx.Graphics.Shader
         public int CbufSlot   { get; }
         public int CbufOffset { get; }
 
-        public TextureDescriptor(string name, SamplerType type, int hIndex)
+        public TextureDescriptor(string name, SamplerType type, int handleIndex)
         {
             Name        = name;
             Type        = type;
-            HandleIndex = hIndex;
+            HandleIndex = handleIndex;
 
             IsBindless = false;