summaryrefslogtreecommitdiff
path: root/src/shader_recompiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp18
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp18
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp12
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.cpp13
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.h1
-rw-r--r--src/shader_recompiler/environment.h10
-rw-r--r--src/shader_recompiler/frontend/ir/attribute.cpp6
-rw-r--r--src/shader_recompiler/frontend/ir/attribute.h5
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp8
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.h2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate_program.cpp2
-rw-r--r--src/shader_recompiler/ir_opt/constant_propagation_pass.cpp76
-rw-r--r--src/shader_recompiler/ir_opt/passes.h2
-rw-r--r--src/shader_recompiler/shader_info.h6
-rw-r--r--src/shader_recompiler/varying_state.h2
16 files changed, 176 insertions, 7 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
index f0bd84ab2..c7d7d5fef 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
@@ -137,6 +137,15 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal
137 case IR::Attribute::VertexId: 137 case IR::Attribute::VertexId:
138 ctx.Add("MOV.F {}.x,{}.id;", inst, ctx.attrib_name); 138 ctx.Add("MOV.F {}.x,{}.id;", inst, ctx.attrib_name);
139 break; 139 break;
140 case IR::Attribute::BaseInstance:
141 ctx.Add("MOV.F {}.x,{}.baseInstance;", inst, ctx.attrib_name);
142 break;
143 case IR::Attribute::BaseVertex:
144 ctx.Add("MOV.F {}.x,{}.baseVertex;", inst, ctx.attrib_name);
145 break;
146 case IR::Attribute::DrawID:
147 ctx.Add("MOV.F {}.x,{}.draw.id;", inst, ctx.attrib_name);
148 break;
140 case IR::Attribute::FrontFace: 149 case IR::Attribute::FrontFace:
141 ctx.Add("CMP.F {}.x,{}.facing.x,0,-1;", inst, ctx.attrib_name); 150 ctx.Add("CMP.F {}.x,{}.facing.x,0,-1;", inst, ctx.attrib_name);
142 break; 151 break;
@@ -156,6 +165,15 @@ void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, S
156 case IR::Attribute::VertexId: 165 case IR::Attribute::VertexId:
157 ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.attrib_name); 166 ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.attrib_name);
158 break; 167 break;
168 case IR::Attribute::BaseInstance:
169 ctx.Add("MOV.S {}.x,{}.baseInstance;", inst, ctx.attrib_name);
170 break;
171 case IR::Attribute::BaseVertex:
172 ctx.Add("MOV.S {}.x,{}.baseVertex;", inst, ctx.attrib_name);
173 break;
174 case IR::Attribute::DrawID:
175 ctx.Add("MOV.S {}.x,{}.draw.id;", inst, ctx.attrib_name);
176 break;
159 default: 177 default:
160 throw NotImplementedException("Get U32 attribute {}", attr); 178 throw NotImplementedException("Get U32 attribute {}", attr);
161 } 179 }
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
index e8a4390f6..d91e04446 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
@@ -219,7 +219,7 @@ std::string EmitGLSL(const Profile& profile, const RuntimeInfo& runtime_info, IR
219 EmitContext ctx{program, bindings, profile, runtime_info}; 219 EmitContext ctx{program, bindings, profile, runtime_info};
220 Precolor(program); 220 Precolor(program);
221 EmitCode(ctx, program); 221 EmitCode(ctx, program);
222 const std::string version{fmt::format("#version 450{}\n", GlslVersionSpecifier(ctx))}; 222 const std::string version{fmt::format("#version 460{}\n", GlslVersionSpecifier(ctx))};
223 ctx.header.insert(0, version); 223 ctx.header.insert(0, version);
224 if (program.shared_memory_size > 0) { 224 if (program.shared_memory_size > 0) {
225 const auto requested_size{program.shared_memory_size}; 225 const auto requested_size{program.shared_memory_size};
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
index 39579cf5d..2e369ed72 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
@@ -234,6 +234,15 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
234 case IR::Attribute::FrontFace: 234 case IR::Attribute::FrontFace:
235 ctx.AddF32("{}=itof(gl_FrontFacing?-1:0);", inst); 235 ctx.AddF32("{}=itof(gl_FrontFacing?-1:0);", inst);
236 break; 236 break;
237 case IR::Attribute::BaseInstance:
238 ctx.AddF32("{}=itof(gl_BaseInstance);", inst);
239 break;
240 case IR::Attribute::BaseVertex:
241 ctx.AddF32("{}=itof(gl_BaseVertex);", inst);
242 break;
243 case IR::Attribute::DrawID:
244 ctx.AddF32("{}=itof(gl_DrawID);", inst);
245 break;
237 default: 246 default:
238 throw NotImplementedException("Get attribute {}", attr); 247 throw NotImplementedException("Get attribute {}", attr);
239 } 248 }
@@ -250,6 +259,15 @@ void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, s
250 case IR::Attribute::VertexId: 259 case IR::Attribute::VertexId:
251 ctx.AddU32("{}=uint(gl_VertexID);", inst); 260 ctx.AddU32("{}=uint(gl_VertexID);", inst);
252 break; 261 break;
262 case IR::Attribute::BaseInstance:
263 ctx.AddU32("{}=uint(gl_BaseInstance);", inst);
264 break;
265 case IR::Attribute::BaseVertex:
266 ctx.AddU32("{}=uint(gl_BaseVertex);", inst);
267 break;
268 case IR::Attribute::DrawID:
269 ctx.AddU32("{}=uint(gl_DrawID);", inst);
270 break;
253 default: 271 default:
254 throw NotImplementedException("Get U32 attribute {}", attr); 272 throw NotImplementedException("Get U32 attribute {}", attr);
255 } 273 }
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index 73b67f0af..db9c94ce8 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -339,6 +339,12 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
339 const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)}; 339 const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)};
340 return ctx.OpBitcast(ctx.F32[1], ctx.OpISub(ctx.U32[1], index, base)); 340 return ctx.OpBitcast(ctx.F32[1], ctx.OpISub(ctx.U32[1], index, base));
341 } 341 }
342 case IR::Attribute::BaseInstance:
343 return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.base_instance));
344 case IR::Attribute::BaseVertex:
345 return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.base_vertex));
346 case IR::Attribute::DrawID:
347 return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.draw_index));
342 case IR::Attribute::FrontFace: 348 case IR::Attribute::FrontFace:
343 return ctx.OpSelect(ctx.F32[1], ctx.OpLoad(ctx.U1, ctx.front_face), 349 return ctx.OpSelect(ctx.F32[1], ctx.OpLoad(ctx.U1, ctx.front_face),
344 ctx.OpBitcast(ctx.F32[1], ctx.Const(std::numeric_limits<u32>::max())), 350 ctx.OpBitcast(ctx.F32[1], ctx.Const(std::numeric_limits<u32>::max())),
@@ -380,6 +386,12 @@ Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, Id) {
380 const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)}; 386 const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)};
381 return ctx.OpISub(ctx.U32[1], index, base); 387 return ctx.OpISub(ctx.U32[1], index, base);
382 } 388 }
389 case IR::Attribute::BaseInstance:
390 return ctx.OpLoad(ctx.U32[1], ctx.base_instance);
391 case IR::Attribute::BaseVertex:
392 return ctx.OpLoad(ctx.U32[1], ctx.base_vertex);
393 case IR::Attribute::DrawID:
394 return ctx.OpLoad(ctx.U32[1], ctx.draw_index);
383 default: 395 default:
384 throw NotImplementedException("Read U32 attribute {}", attr); 396 throw NotImplementedException("Read U32 attribute {}", attr);
385 } 397 }
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
index 41dc6d031..ecb2db494 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
@@ -1379,18 +1379,31 @@ void EmitContext::DefineInputs(const IR::Program& program) {
1379 if (loads[IR::Attribute::InstanceId]) { 1379 if (loads[IR::Attribute::InstanceId]) {
1380 if (profile.support_vertex_instance_id) { 1380 if (profile.support_vertex_instance_id) {
1381 instance_id = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceId); 1381 instance_id = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceId);
1382 if (loads[IR::Attribute::BaseInstance]) {
1383 base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex);
1384 }
1382 } else { 1385 } else {
1383 instance_index = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceIndex); 1386 instance_index = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceIndex);
1384 base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance); 1387 base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance);
1385 } 1388 }
1389 } else if (loads[IR::Attribute::BaseInstance]) {
1390 base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance);
1386 } 1391 }
1387 if (loads[IR::Attribute::VertexId]) { 1392 if (loads[IR::Attribute::VertexId]) {
1388 if (profile.support_vertex_instance_id) { 1393 if (profile.support_vertex_instance_id) {
1389 vertex_id = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexId); 1394 vertex_id = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexId);
1395 if (loads[IR::Attribute::BaseVertex]) {
1396 base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex);
1397 }
1390 } else { 1398 } else {
1391 vertex_index = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexIndex); 1399 vertex_index = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexIndex);
1392 base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); 1400 base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex);
1393 } 1401 }
1402 } else if (loads[IR::Attribute::BaseVertex]) {
1403 base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex);
1404 }
1405 if (loads[IR::Attribute::DrawID]) {
1406 draw_index = DefineInput(*this, U32[1], true, spv::BuiltIn::DrawIndex);
1394 } 1407 }
1395 if (loads[IR::Attribute::FrontFace]) { 1408 if (loads[IR::Attribute::FrontFace]) {
1396 front_face = DefineInput(*this, U1, true, spv::BuiltIn::FrontFacing); 1409 front_face = DefineInput(*this, U1, true, spv::BuiltIn::FrontFacing);
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
index dde45b4bc..4414a5169 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
@@ -218,6 +218,7 @@ public:
218 Id base_instance{}; 218 Id base_instance{};
219 Id vertex_id{}; 219 Id vertex_id{};
220 Id vertex_index{}; 220 Id vertex_index{};
221 Id draw_index{};
221 Id base_vertex{}; 222 Id base_vertex{};
222 Id front_face{}; 223 Id front_face{};
223 Id point_coord{}; 224 Id point_coord{};
diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h
index 402f2664f..26e8307c1 100644
--- a/src/shader_recompiler/environment.h
+++ b/src/shader_recompiler/environment.h
@@ -34,6 +34,11 @@ public:
34 34
35 [[nodiscard]] virtual std::array<u32, 3> WorkgroupSize() const = 0; 35 [[nodiscard]] virtual std::array<u32, 3> WorkgroupSize() const = 0;
36 36
37 [[nodiscard]] virtual bool HasHLEMacroState() const = 0;
38
39 [[nodiscard]] virtual std::optional<ReplaceConstant> GetReplaceConstBuffer(u32 bank,
40 u32 offset) = 0;
41
37 virtual void Dump(u64 hash) = 0; 42 virtual void Dump(u64 hash) = 0;
38 43
39 [[nodiscard]] const ProgramHeader& SPH() const noexcept { 44 [[nodiscard]] const ProgramHeader& SPH() const noexcept {
@@ -52,11 +57,16 @@ public:
52 return start_address; 57 return start_address;
53 } 58 }
54 59
60 [[nodiscard]] bool IsPropietaryDriver() const noexcept {
61 return is_propietary_driver;
62 }
63
55protected: 64protected:
56 ProgramHeader sph{}; 65 ProgramHeader sph{};
57 std::array<u32, 8> gp_passthrough_mask{}; 66 std::array<u32, 8> gp_passthrough_mask{};
58 Stage stage{}; 67 Stage stage{};
59 u32 start_address{}; 68 u32 start_address{};
69 bool is_propietary_driver{};
60}; 70};
61 71
62} // namespace Shader 72} // namespace Shader
diff --git a/src/shader_recompiler/frontend/ir/attribute.cpp b/src/shader_recompiler/frontend/ir/attribute.cpp
index 7d3d882e4..1bf9db935 100644
--- a/src/shader_recompiler/frontend/ir/attribute.cpp
+++ b/src/shader_recompiler/frontend/ir/attribute.cpp
@@ -446,6 +446,12 @@ std::string NameOf(Attribute attribute) {
446 return "ViewportMask"; 446 return "ViewportMask";
447 case Attribute::FrontFace: 447 case Attribute::FrontFace:
448 return "FrontFace"; 448 return "FrontFace";
449 case Attribute::BaseInstance:
450 return "BaseInstance";
451 case Attribute::BaseVertex:
452 return "BaseVertex";
453 case Attribute::DrawID:
454 return "DrawID";
449 } 455 }
450 return fmt::format("<reserved attribute {}>", static_cast<int>(attribute)); 456 return fmt::format("<reserved attribute {}>", static_cast<int>(attribute));
451} 457}
diff --git a/src/shader_recompiler/frontend/ir/attribute.h b/src/shader_recompiler/frontend/ir/attribute.h
index 6ee3947b1..5f039b6f6 100644
--- a/src/shader_recompiler/frontend/ir/attribute.h
+++ b/src/shader_recompiler/frontend/ir/attribute.h
@@ -219,6 +219,11 @@ enum class Attribute : u64 {
219 FixedFncTexture9Q = 231, 219 FixedFncTexture9Q = 231,
220 ViewportMask = 232, 220 ViewportMask = 232,
221 FrontFace = 255, 221 FrontFace = 255,
222
223 // Implementation attributes
224 BaseInstance = 256,
225 BaseVertex = 257,
226 DrawID = 258,
222}; 227};
223 228
224constexpr size_t NUM_GENERICS = 32; 229constexpr size_t NUM_GENERICS = 32;
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index 0cdac0eff..eb2e49a68 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -294,6 +294,14 @@ F32 IREmitter::GetAttribute(IR::Attribute attribute, const U32& vertex) {
294 return Inst<F32>(Opcode::GetAttribute, attribute, vertex); 294 return Inst<F32>(Opcode::GetAttribute, attribute, vertex);
295} 295}
296 296
297U32 IREmitter::GetAttributeU32(IR::Attribute attribute) {
298 return GetAttributeU32(attribute, Imm32(0));
299}
300
301U32 IREmitter::GetAttributeU32(IR::Attribute attribute, const U32& vertex) {
302 return Inst<U32>(Opcode::GetAttributeU32, attribute, vertex);
303}
304
297void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex) { 305void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex) {
298 Inst(Opcode::SetAttribute, attribute, value, vertex); 306 Inst(Opcode::SetAttribute, attribute, value, vertex);
299} 307}
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index 2df992feb..7aaaa4ab0 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -74,6 +74,8 @@ public:
74 74
75 [[nodiscard]] F32 GetAttribute(IR::Attribute attribute); 75 [[nodiscard]] F32 GetAttribute(IR::Attribute attribute);
76 [[nodiscard]] F32 GetAttribute(IR::Attribute attribute, const U32& vertex); 76 [[nodiscard]] F32 GetAttribute(IR::Attribute attribute, const U32& vertex);
77 [[nodiscard]] U32 GetAttributeU32(IR::Attribute attribute);
78 [[nodiscard]] U32 GetAttributeU32(IR::Attribute attribute, const U32& vertex);
77 void SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex); 79 void SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex);
78 80
79 [[nodiscard]] F32 GetAttributeIndexed(const U32& phys_address); 81 [[nodiscard]] F32 GetAttributeIndexed(const U32& phys_address);
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
index 3adbd2b16..ac159d24b 100644
--- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
@@ -219,7 +219,7 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
219 } 219 }
220 Optimization::SsaRewritePass(program); 220 Optimization::SsaRewritePass(program);
221 221
222 Optimization::ConstantPropagationPass(program); 222 Optimization::ConstantPropagationPass(env, program);
223 223
224 Optimization::PositionPass(env, program); 224 Optimization::PositionPass(env, program);
225 225
diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
index 826f9a54a..4d81e9336 100644
--- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
+++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
@@ -7,6 +7,7 @@
7#include <type_traits> 7#include <type_traits>
8 8
9#include "common/bit_cast.h" 9#include "common/bit_cast.h"
10#include "shader_recompiler/environment.h"
10#include "shader_recompiler/exception.h" 11#include "shader_recompiler/exception.h"
11#include "shader_recompiler/frontend/ir/ir_emitter.h" 12#include "shader_recompiler/frontend/ir/ir_emitter.h"
12#include "shader_recompiler/frontend/ir/value.h" 13#include "shader_recompiler/frontend/ir/value.h"
@@ -515,6 +516,9 @@ void FoldBitCast(IR::Inst& inst, IR::Opcode reverse) {
515 case IR::Attribute::PrimitiveId: 516 case IR::Attribute::PrimitiveId:
516 case IR::Attribute::InstanceId: 517 case IR::Attribute::InstanceId:
517 case IR::Attribute::VertexId: 518 case IR::Attribute::VertexId:
519 case IR::Attribute::BaseVertex:
520 case IR::Attribute::BaseInstance:
521 case IR::Attribute::DrawID:
518 break; 522 break;
519 default: 523 default:
520 return; 524 return;
@@ -644,7 +648,63 @@ void FoldFSwizzleAdd(IR::Block& block, IR::Inst& inst) {
644 } 648 }
645} 649}
646 650
647void ConstantPropagation(IR::Block& block, IR::Inst& inst) { 651void FoldConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst) {
652 const IR::Value bank{inst.Arg(0)};
653 const IR::Value offset{inst.Arg(1)};
654 if (!bank.IsImmediate() || !offset.IsImmediate()) {
655 return;
656 }
657 const auto bank_value = bank.U32();
658 const auto offset_value = offset.U32();
659 auto replacement = env.GetReplaceConstBuffer(bank_value, offset_value);
660 if (!replacement) {
661 return;
662 }
663 const auto new_attribute = [replacement]() {
664 switch (*replacement) {
665 case ReplaceConstant::BaseInstance:
666 return IR::Attribute::BaseInstance;
667 case ReplaceConstant::BaseVertex:
668 return IR::Attribute::BaseVertex;
669 case ReplaceConstant::DrawID:
670 return IR::Attribute::DrawID;
671 default:
672 throw NotImplementedException("Not implemented replacement variable {}", *replacement);
673 }
674 }();
675 IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
676 if (inst.GetOpcode() == IR::Opcode::GetCbufU32) {
677 inst.ReplaceUsesWith(ir.GetAttributeU32(new_attribute));
678 } else {
679 inst.ReplaceUsesWith(ir.GetAttribute(new_attribute));
680 }
681}
682
683void FoldDriverConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst, u32 which_bank,
684 u32 offset_start = 0, u32 offset_end = std::numeric_limits<u16>::max()) {
685 const IR::Value bank{inst.Arg(0)};
686 const IR::Value offset{inst.Arg(1)};
687 if (!bank.IsImmediate() || !offset.IsImmediate()) {
688 return;
689 }
690 const auto bank_value = bank.U32();
691 if (bank_value != which_bank) {
692 return;
693 }
694 const auto offset_value = offset.U32();
695 if (offset_value < offset_start || offset_value >= offset_end) {
696 return;
697 }
698 IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
699 if (inst.GetOpcode() == IR::Opcode::GetCbufU32) {
700 inst.ReplaceUsesWith(IR::Value{env.ReadCbufValue(bank_value, offset_value)});
701 } else {
702 inst.ReplaceUsesWith(
703 IR::Value{Common::BitCast<f32>(env.ReadCbufValue(bank_value, offset_value))});
704 }
705}
706
707void ConstantPropagation(Environment& env, IR::Block& block, IR::Inst& inst) {
648 switch (inst.GetOpcode()) { 708 switch (inst.GetOpcode()) {
649 case IR::Opcode::GetRegister: 709 case IR::Opcode::GetRegister:
650 return FoldGetRegister(inst); 710 return FoldGetRegister(inst);
@@ -789,18 +849,28 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
789 IR::Opcode::CompositeInsertF16x4); 849 IR::Opcode::CompositeInsertF16x4);
790 case IR::Opcode::FSwizzleAdd: 850 case IR::Opcode::FSwizzleAdd:
791 return FoldFSwizzleAdd(block, inst); 851 return FoldFSwizzleAdd(block, inst);
852 case IR::Opcode::GetCbufF32:
853 case IR::Opcode::GetCbufU32:
854 if (env.HasHLEMacroState()) {
855 FoldConstBuffer(env, block, inst);
856 }
857 if (env.IsPropietaryDriver()) {
858 FoldDriverConstBuffer(env, block, inst, 1);
859 }
860 break;
792 default: 861 default:
793 break; 862 break;
794 } 863 }
795} 864}
865
796} // Anonymous namespace 866} // Anonymous namespace
797 867
798void ConstantPropagationPass(IR::Program& program) { 868void ConstantPropagationPass(Environment& env, IR::Program& program) {
799 const auto end{program.post_order_blocks.rend()}; 869 const auto end{program.post_order_blocks.rend()};
800 for (auto it = program.post_order_blocks.rbegin(); it != end; ++it) { 870 for (auto it = program.post_order_blocks.rbegin(); it != end; ++it) {
801 IR::Block* const block{*it}; 871 IR::Block* const block{*it};
802 for (IR::Inst& inst : block->Instructions()) { 872 for (IR::Inst& inst : block->Instructions()) {
803 ConstantPropagation(*block, inst); 873 ConstantPropagation(env, *block, inst);
804 } 874 }
805 } 875 }
806} 876}
diff --git a/src/shader_recompiler/ir_opt/passes.h b/src/shader_recompiler/ir_opt/passes.h
index 11bfe801a..1f8f2ba95 100644
--- a/src/shader_recompiler/ir_opt/passes.h
+++ b/src/shader_recompiler/ir_opt/passes.h
@@ -13,7 +13,7 @@ struct HostTranslateInfo;
13namespace Shader::Optimization { 13namespace Shader::Optimization {
14 14
15void CollectShaderInfoPass(Environment& env, IR::Program& program); 15void CollectShaderInfoPass(Environment& env, IR::Program& program);
16void ConstantPropagationPass(IR::Program& program); 16void ConstantPropagationPass(Environment& env, IR::Program& program);
17void DeadCodeEliminationPass(IR::Program& program); 17void DeadCodeEliminationPass(IR::Program& program);
18void GlobalMemoryToStorageBufferPass(IR::Program& program); 18void GlobalMemoryToStorageBufferPass(IR::Program& program);
19void IdentityRemovalPass(IR::Program& program); 19void IdentityRemovalPass(IR::Program& program);
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h
index d9c6e92db..44236b6b1 100644
--- a/src/shader_recompiler/shader_info.h
+++ b/src/shader_recompiler/shader_info.h
@@ -16,6 +16,12 @@
16 16
17namespace Shader { 17namespace Shader {
18 18
19enum class ReplaceConstant : u32 {
20 BaseInstance,
21 BaseVertex,
22 DrawID,
23};
24
19enum class TextureType : u32 { 25enum class TextureType : u32 {
20 Color1D, 26 Color1D,
21 ColorArray1D, 27 ColorArray1D,
diff --git a/src/shader_recompiler/varying_state.h b/src/shader_recompiler/varying_state.h
index 7b28a285f..18a9aaf50 100644
--- a/src/shader_recompiler/varying_state.h
+++ b/src/shader_recompiler/varying_state.h
@@ -11,7 +11,7 @@
11namespace Shader { 11namespace Shader {
12 12
13struct VaryingState { 13struct VaryingState {
14 std::bitset<256> mask{}; 14 std::bitset<512> mask{};
15 15
16 void Set(IR::Attribute attribute, bool state = true) { 16 void Set(IR::Attribute attribute, bool state = true) {
17 mask[static_cast<size_t>(attribute)] = state; 17 mask[static_cast<size_t>(attribute)] = state;