From e926757c8f7d8d1fc90e62c2b891a65fe1119173 Mon Sep 17 00:00:00 2001
From: FernandoS27 <fsahmkow27@gmail.com>
Date: Mon, 10 Sep 2018 21:00:55 -0400
Subject: [PATCH] Implemented (Partialy) Shader Header

---
 src/video_core/CMakeLists.txt                 |  1 +
 src/video_core/engines/shader_header.h        | 97 +++++++++++++++++++
 .../renderer_opengl/gl_shader_decompiler.cpp  |  6 +-
 3 files changed, 102 insertions(+), 2 deletions(-)
 create mode 100644 src/video_core/engines/shader_header.h

diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 65b5f57c3a..ac4ec36de6 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -12,6 +12,7 @@ add_library(video_core STATIC
     engines/maxwell_dma.cpp
     engines/maxwell_dma.h
     engines/shader_bytecode.h
+    engines/shader_header.h
     gpu.cpp
     gpu.h
     macro_interpreter.cpp
diff --git a/src/video_core/engines/shader_header.h b/src/video_core/engines/shader_header.h
new file mode 100644
index 0000000000..4663377ede
--- /dev/null
+++ b/src/video_core/engines/shader_header.h
@@ -0,0 +1,97 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/bit_field.h"
+#include "common/common_types.h"
+#include "common/common_funcs.h"
+
+namespace Tegra::Shader {
+
+enum class OutputTopology : u32 {
+    PointList = 1,
+    LineStrip = 6,
+    TriangleStrip = 7,
+};
+
+// Documentation in:
+// http://download.nvidia.com/open-gpu-doc/Shader-Program-Header/1/Shader-Program-Header.html#ImapTexture
+struct Header {
+    union {
+        BitField<0, 5, u32> sph_type;
+        BitField<5, 5, u32> version;
+        BitField<10, 4, u32> shader_type;
+        BitField<14, 1, u32> mrt_enable;
+        BitField<15, 1, u32> kills_pixels;
+        BitField<16, 1, u32> does_global_store;
+        BitField<17, 4, u32> sass_version;
+        BitField<21, 5, u32> reserved;
+        BitField<26, 1, u32> does_load_or_store;
+        BitField<27, 1, u32> does_fp64;
+        BitField<28, 4, u32> stream_out_mask;
+    } common0;
+
+    union {
+        BitField<0, 24, u32> shader_local_memory_low_size;
+        BitField<24, 8, u32> per_patch_attribute_count;
+    } common1;
+
+    union {
+        BitField<0, 24, u32> shader_local_memory_high_size;
+        BitField<24, 8, u32> threads_per_input_primitive;
+    } common2;
+
+    union {
+        BitField<0, 24, u32> shader_local_memory_crs_size;
+        BitField<24, 4, OutputTopology> output_topology;
+        BitField<28, 4, u32> reserved;
+    } common3;
+
+    union {
+        BitField<0, 12, u32> max_output_vertices;
+        BitField<12, 8, u32> store_req_start; // NOTE: not used by geometry shaders.
+        BitField<24, 4, u32> reserved;
+        BitField<12, 8, u32> store_req_end; // NOTE: not used by geometry shaders.
+    } common4;
+
+    union {
+        struct {
+            INSERT_PADDING_BYTES(3);  // ImapSystemValuesA
+            INSERT_PADDING_BYTES(1);  // ImapSystemValuesB
+            INSERT_PADDING_BYTES(16); // ImapGenericVector[32]
+            INSERT_PADDING_BYTES(2);  // ImapColor
+            INSERT_PADDING_BYTES(2);  // ImapSystemValuesC
+            INSERT_PADDING_BYTES(5);  // ImapFixedFncTexture[10]
+            INSERT_PADDING_BYTES(1);  // ImapReserved
+            INSERT_PADDING_BYTES(3);  // OmapSystemValuesA
+            INSERT_PADDING_BYTES(1);  // OmapSystemValuesB
+            INSERT_PADDING_BYTES(16); // OmapGenericVector[32]
+            INSERT_PADDING_BYTES(2);  // OmapColor
+            INSERT_PADDING_BYTES(2);  // OmapSystemValuesC
+            INSERT_PADDING_BYTES(5);  // OmapFixedFncTexture[10]
+            INSERT_PADDING_BYTES(1);  // OmapReserved
+        } ps;
+
+        struct {
+            INSERT_PADDING_BYTES(3);  // ImapSystemValuesA
+            INSERT_PADDING_BYTES(1);  // ImapSystemValuesB
+            INSERT_PADDING_BYTES(32); // ImapGenericVector[32]
+            INSERT_PADDING_BYTES(2);  // ImapColor
+            INSERT_PADDING_BYTES(2);  // ImapSystemValuesC
+            INSERT_PADDING_BYTES(10); // ImapFixedFncTexture[10]
+            INSERT_PADDING_BYTES(2);  // ImapReserved
+            INSERT_PADDING_BYTES(4);  // OmapTarget[8]
+            union {
+                BitField<0, 1, u32> omap_sample_mask;
+                BitField<1, 1, u32> omap_depth;
+                BitField<2, 30, u32> omap_reserved;
+            } omap;
+        } vtg;
+    } sph;
+};
+
+static_assert(sizeof(Header) == 0x50, "Incorrect structure size");
+
+} // namespace Tegra::Shader
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index e350113f12..d826d98eb5 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -12,6 +12,7 @@
 #include "common/assert.h"
 #include "common/common_types.h"
 #include "video_core/engines/shader_bytecode.h"
+#include "video_core/engines/shader_header.h"
 #include "video_core/renderer_opengl/gl_rasterizer.h"
 #include "video_core/renderer_opengl/gl_shader_decompiler.h"
 
@@ -26,7 +27,7 @@ using Tegra::Shader::Sampler;
 using Tegra::Shader::SubOp;
 
 constexpr u32 PROGRAM_END = MAX_PROGRAM_CODE_LENGTH;
-constexpr u32 PROGRAM_HEADER_SIZE = 0x50;
+constexpr u32 PROGRAM_HEADER_SIZE = sizeof(Tegra::Shader::Header);
 
 class DecompileFail : public std::runtime_error {
 public:
@@ -674,7 +675,7 @@ public:
                   u32 main_offset, Maxwell3D::Regs::ShaderStage stage, const std::string& suffix)
         : subroutines(subroutines), program_code(program_code), main_offset(main_offset),
           stage(stage), suffix(suffix) {
-
+        std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header));
         Generate(suffix);
     }
 
@@ -2502,6 +2503,7 @@ private:
 private:
     const std::set<Subroutine>& subroutines;
     const ProgramCode& program_code;
+    Tegra::Shader::Header header;
     const u32 main_offset;
     Maxwell3D::Regs::ShaderStage stage;
     const std::string& suffix;