From 675a82416d7775dc7a252a5d8f5b704e6b8f2326 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sat, 27 Mar 2021 03:08:31 -0300
Subject: [PATCH] spirv: Remove dependencies on Environment when generating
 SPIR-V

---
 src/shader_recompiler/backend/spirv/emit_spirv.cpp   | 11 +++++------
 src/shader_recompiler/backend/spirv/emit_spirv.h     |  5 ++---
 src/shader_recompiler/frontend/ir/program.h          |  2 ++
 src/shader_recompiler/frontend/maxwell/program.cpp   |  3 +++
 src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 10 +++-------
 5 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
index 4bed16e7b2..2e7e6bb0c9 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
@@ -126,12 +126,12 @@ Id DefineMain(EmitContext& ctx, IR::Program& program) {
     return main;
 }
 
-void DefineEntryPoint(Environment& env, const IR::Program& program, EmitContext& ctx, Id main) {
+void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) {
     const std::span interfaces(ctx.interfaces.data(), ctx.interfaces.size());
     spv::ExecutionModel execution_model{};
     switch (program.stage) {
     case Shader::Stage::Compute: {
-        const std::array<u32, 3> workgroup_size{env.WorkgroupSize()};
+        const std::array<u32, 3> workgroup_size{program.workgroup_size};
         execution_model = spv::ExecutionModel::GLCompute;
         ctx.AddExecutionMode(main, spv::ExecutionMode::LocalSize, workgroup_size[0],
                              workgroup_size[1], workgroup_size[2]);
@@ -148,7 +148,7 @@ void DefineEntryPoint(Environment& env, const IR::Program& program, EmitContext&
         }
         break;
     default:
-        throw NotImplementedException("Stage {}", env.ShaderStage());
+        throw NotImplementedException("Stage {}", program.stage);
     }
     ctx.AddEntryPoint(execution_model, main, "main", interfaces);
 }
@@ -267,11 +267,10 @@ Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) {
 }
 } // Anonymous namespace
 
-std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program,
-                           u32& binding) {
+std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program, u32& binding) {
     EmitContext ctx{profile, program, binding};
     const Id main{DefineMain(ctx, program)};
-    DefineEntryPoint(env, program, ctx, main);
+    DefineEntryPoint(program, ctx, main);
     if (profile.support_float_controls) {
         ctx.AddExtension("SPV_KHR_float_controls");
         SetupDenormControl(profile, program, ctx, main);
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h
index b82b16e9d0..837f0e858e 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.h
@@ -8,15 +8,14 @@
 
 #include "common/common_types.h"
 #include "shader_recompiler/backend/spirv/emit_context.h"
-#include "shader_recompiler/environment.h"
 #include "shader_recompiler/frontend/ir/microinstruction.h"
 #include "shader_recompiler/frontend/ir/program.h"
 #include "shader_recompiler/profile.h"
 
 namespace Shader::Backend::SPIRV {
 
-[[nodiscard]] std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env,
-                                         IR::Program& program, u32& binding);
+[[nodiscard]] std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program,
+                                         u32& binding);
 
 // Microinstruction emitters
 Id EmitPhi(EmitContext& ctx, IR::Inst* inst);
diff --git a/src/shader_recompiler/frontend/ir/program.h b/src/shader_recompiler/frontend/ir/program.h
index 733513c8b1..0162e919cb 100644
--- a/src/shader_recompiler/frontend/ir/program.h
+++ b/src/shader_recompiler/frontend/ir/program.h
@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include <array>
 #include <string>
 
 #include <boost/container/small_vector.hpp>
@@ -19,6 +20,7 @@ struct Program {
     BlockList post_order_blocks;
     Info info;
     Stage stage{};
+    std::array<u32, 3> workgroup_size{};
 };
 
 [[nodiscard]] std::string DumpProgram(const Program& program);
diff --git a/src/shader_recompiler/frontend/maxwell/program.cpp b/src/shader_recompiler/frontend/maxwell/program.cpp
index 0074eb89b6..6efaf6ee08 100644
--- a/src/shader_recompiler/frontend/maxwell/program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/program.cpp
@@ -33,6 +33,9 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
     program.blocks = VisitAST(inst_pool, block_pool, env, cfg);
     program.post_order_blocks = PostOrder(program.blocks);
     program.stage = env.ShaderStage();
+    if (program.stage == Stage::Compute) {
+        program.workgroup_size = env.WorkgroupSize();
+    }
     RemoveUnreachableBlocks(program);
 
     // Replace instructions before the SSA rewrite
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 51c1550776..251559b16a 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -680,7 +680,6 @@ GraphicsPipeline PipelineCache::CreateGraphicsPipeline(ShaderPools& pools,
     std::array<vk::ShaderModule, Maxwell::MaxShaderStage> modules;
 
     u32 binding{0};
-    env_index = 0;
     for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
         if (key.unique_hashes[index] == u128{}) {
             continue;
@@ -691,11 +690,8 @@ GraphicsPipeline PipelineCache::CreateGraphicsPipeline(ShaderPools& pools,
         const size_t stage_index{index - 1};
         infos[stage_index] = &program.info;
 
-        Shader::Environment& env{*envs[env_index]};
-        ++env_index;
-
-        const Shader::Profile profile{MakeProfile(key, env.ShaderStage())};
-        const std::vector<u32> code{EmitSPIRV(profile, env, program, binding)};
+        const Shader::Profile profile{MakeProfile(key, program.stage)};
+        const std::vector<u32> code{EmitSPIRV(profile, program, binding)};
         modules[stage_index] = BuildShader(device, code);
     }
     return GraphicsPipeline(maxwell3d, gpu_memory, scheduler, buffer_cache, texture_cache, device,
@@ -753,7 +749,7 @@ ComputePipeline PipelineCache::CreateComputePipeline(ShaderPools& pools,
     Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()};
     Shader::IR::Program program{TranslateProgram(pools.inst, pools.block, env, cfg)};
     u32 binding{0};
-    std::vector<u32> code{EmitSPIRV(base_profile, env, program, binding)};
+    std::vector<u32> code{EmitSPIRV(base_profile, program, binding)};
     return ComputePipeline{device, descriptor_pool, update_descriptor_queue, program.info,
                            BuildShader(device, code)};
 }