From eb5861e0a22851cd2b2ca38136bfc7870790836e Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Mon, 2 Mar 2020 01:54:00 -0300
Subject: [PATCH] engines/maxwell_3d: Add TFB registers and store them in
 shader registry

---
 src/video_core/engines/maxwell_3d.h           | 34 +++++++++++++++++--
 .../renderer_opengl/gl_shader_disk_cache.cpp  |  2 +-
 src/video_core/shader/registry.cpp            |  3 ++
 src/video_core/shader/registry.h              | 12 +++++--
 4 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 491cff370..7000b0589 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -67,6 +67,7 @@ public:
         static constexpr std::size_t NumVaryings = 31;
         static constexpr std::size_t NumImages = 8; // TODO(Rodrigo): Investigate this number
         static constexpr std::size_t NumClipDistances = 8;
+        static constexpr std::size_t NumTransformFeedbackBuffers = 4;
         static constexpr std::size_t MaxShaderProgram = 6;
         static constexpr std::size_t MaxShaderStage = 5;
         // Maximum number of const buffers per shader stage.
@@ -621,6 +622,22 @@ public:
             float depth_range_far;
         };
 
+        struct alignas(32) TransformFeedbackBinding {
+            u32 buffer_enable;
+            u32 address_high;
+            u32 address_low;
+            s32 buffer_size;
+            s32 buffer_offset;
+        };
+        static_assert(sizeof(TransformFeedbackBinding) == 32);
+
+        struct alignas(16) TransformFeedbackLayout {
+            u32 stream;
+            u32 varying_count;
+            u32 stride;
+        };
+        static_assert(sizeof(TransformFeedbackLayout) == 16);
+
         bool IsShaderConfigEnabled(std::size_t index) const {
             // The VertexB is always enabled.
             if (index == static_cast<std::size_t>(Regs::ShaderProgram::VertexB)) {
@@ -677,7 +694,13 @@ public:
 
                 u32 rasterize_enable;
 
-                INSERT_UNION_PADDING_WORDS(0xF1);
+                std::array<TransformFeedbackBinding, NumTransformFeedbackBuffers> tfb_bindings;
+
+                INSERT_UNION_PADDING_WORDS(0xC0);
+
+                std::array<TransformFeedbackLayout, NumTransformFeedbackBuffers> tfb_layouts;
+
+                INSERT_UNION_PADDING_WORDS(0x1);
 
                 u32 tfb_enabled;
 
@@ -1187,7 +1210,11 @@ public:
 
                 u32 tex_cb_index;
 
-                INSERT_UNION_PADDING_WORDS(0x395);
+                INSERT_UNION_PADDING_WORDS(0x7D);
+
+                std::array<std::array<u8, 128>, NumTransformFeedbackBuffers> tfb_varying_locs;
+
+                INSERT_UNION_PADDING_WORDS(0x298);
 
                 struct {
                     /// Compressed address of a buffer that holds information about bound SSBOs.
@@ -1413,6 +1440,8 @@ ASSERT_REG_POSITION(tess_mode, 0xC8);
 ASSERT_REG_POSITION(tess_level_outer, 0xC9);
 ASSERT_REG_POSITION(tess_level_inner, 0xCD);
 ASSERT_REG_POSITION(rasterize_enable, 0xDF);
+ASSERT_REG_POSITION(tfb_bindings, 0xE0);
+ASSERT_REG_POSITION(tfb_layouts, 0x1C0);
 ASSERT_REG_POSITION(tfb_enabled, 0x1D1);
 ASSERT_REG_POSITION(rt, 0x200);
 ASSERT_REG_POSITION(viewport_transform, 0x280);
@@ -1508,6 +1537,7 @@ ASSERT_REG_POSITION(firmware, 0x8C0);
 ASSERT_REG_POSITION(const_buffer, 0x8E0);
 ASSERT_REG_POSITION(cb_bind[0], 0x904);
 ASSERT_REG_POSITION(tex_cb_index, 0x982);
+ASSERT_REG_POSITION(tfb_varying_locs, 0xA00);
 ASSERT_REG_POSITION(ssbo_info, 0xD18);
 ASSERT_REG_POSITION(tex_info_buffers.address[0], 0xD2A);
 ASSERT_REG_POSITION(tex_info_buffers.size[0], 0xD2F);
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
index 3b0db5393..9e95a122b 100644
--- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
@@ -48,7 +48,7 @@ struct BindlessSamplerKey {
     Tegra::Engines::SamplerDescriptor sampler;
 };
 
-constexpr u32 NativeVersion = 19;
+constexpr u32 NativeVersion = 20;
 
 ShaderCacheVersionHash GetShaderCacheVersionHash() {
     ShaderCacheVersionHash hash{};
diff --git a/src/video_core/shader/registry.cpp b/src/video_core/shader/registry.cpp
index 4a1e16c1e..af70b3f35 100644
--- a/src/video_core/shader/registry.cpp
+++ b/src/video_core/shader/registry.cpp
@@ -27,9 +27,12 @@ GraphicsInfo MakeGraphicsInfo(ShaderType shader_stage, ConstBufferEngineInterfac
     auto& graphics = static_cast<Tegra::Engines::Maxwell3D&>(engine);
 
     GraphicsInfo info;
+    info.tfb_layouts = graphics.regs.tfb_layouts;
+    info.tfb_varying_locs = graphics.regs.tfb_varying_locs;
     info.primitive_topology = graphics.regs.draw.topology;
     info.tessellation_primitive = graphics.regs.tess_mode.prim;
     info.tessellation_spacing = graphics.regs.tess_mode.spacing;
+    info.tfb_enabled = graphics.regs.tfb_enabled;
     info.tessellation_clockwise = graphics.regs.tess_mode.cw;
     return info;
 }
diff --git a/src/video_core/shader/registry.h b/src/video_core/shader/registry.h
index 07998c4db..0c80d35fd 100644
--- a/src/video_core/shader/registry.h
+++ b/src/video_core/shader/registry.h
@@ -25,9 +25,15 @@ using BindlessSamplerMap =
     std::unordered_map<std::pair<u32, u32>, Tegra::Engines::SamplerDescriptor, Common::PairHash>;
 
 struct GraphicsInfo {
-    Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology primitive_topology{};
-    Tegra::Engines::Maxwell3D::Regs::TessellationPrimitive tessellation_primitive{};
-    Tegra::Engines::Maxwell3D::Regs::TessellationSpacing tessellation_spacing{};
+    using Maxwell = Tegra::Engines::Maxwell3D::Regs;
+
+    std::array<Maxwell::TransformFeedbackLayout, Maxwell::NumTransformFeedbackBuffers>
+        tfb_layouts{};
+    std::array<std::array<u8, 128>, Maxwell::NumTransformFeedbackBuffers> tfb_varying_locs{};
+    Maxwell::PrimitiveTopology primitive_topology{};
+    Maxwell::TessellationPrimitive tessellation_primitive{};
+    Maxwell::TessellationSpacing tessellation_spacing{};
+    bool tfb_enabled = false;
     bool tessellation_clockwise = false;
 };
 static_assert(std::is_trivially_copyable_v<GraphicsInfo> &&