summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-04-15 22:46:11 -0300
committerGravatar ameerj2021-07-22 21:51:27 -0400
commit183855e396cc6918d36fbf3e38ea426e934b4e3e (patch)
treea665794753520c09a1d34d8a086352894ec1cb72 /src/shader_recompiler/frontend
parentshader: Mark atomic instructions as writes (diff)
downloadyuzu-183855e396cc6918d36fbf3e38ea426e934b4e3e.tar.gz
yuzu-183855e396cc6918d36fbf3e38ea426e934b4e3e.tar.xz
yuzu-183855e396cc6918d36fbf3e38ea426e934b4e3e.zip
shader: Implement tessellation shaders, polygon mode and invocation id
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp12
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.h4
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.cpp1
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.cpp1
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.inc3
-rw-r--r--src/shader_recompiler/frontend/ir/patch.cpp28
-rw-r--r--src/shader_recompiler/frontend/ir/patch.h149
-rw-r--r--src/shader_recompiler/frontend/ir/type.h41
-rw-r--r--src/shader_recompiler/frontend/ir/value.cpp9
-rw-r--r--src/shader_recompiler/frontend/ir/value.h4
-rw-r--r--src/shader_recompiler/frontend/maxwell/program.cpp5
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp33
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp2
13 files changed, 259 insertions, 33 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index d66eb17a6..b821d9f47 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -331,6 +331,14 @@ void IREmitter::SetAttributeIndexed(const U32& phys_address, const F32& value, c
331 Inst(Opcode::SetAttributeIndexed, phys_address, value, vertex); 331 Inst(Opcode::SetAttributeIndexed, phys_address, value, vertex);
332} 332}
333 333
334F32 IREmitter::GetPatch(Patch patch) {
335 return Inst<F32>(Opcode::GetPatch, patch);
336}
337
338void IREmitter::SetPatch(Patch patch, const F32& value) {
339 Inst(Opcode::SetPatch, patch, value);
340}
341
334void IREmitter::SetFragColor(u32 index, u32 component, const F32& value) { 342void IREmitter::SetFragColor(u32 index, u32 component, const F32& value) {
335 Inst(Opcode::SetFragColor, Imm32(index), Imm32(component), value); 343 Inst(Opcode::SetFragColor, Imm32(index), Imm32(component), value);
336} 344}
@@ -363,6 +371,10 @@ U32 IREmitter::LocalInvocationIdZ() {
363 return U32{CompositeExtract(Inst(Opcode::LocalInvocationId), 2)}; 371 return U32{CompositeExtract(Inst(Opcode::LocalInvocationId), 2)};
364} 372}
365 373
374U32 IREmitter::InvocationId() {
375 return Inst<U32>(Opcode::InvocationId);
376}
377
366U1 IREmitter::IsHelperInvocation() { 378U1 IREmitter::IsHelperInvocation() {
367 return Inst<U1>(Opcode::IsHelperInvocation); 379 return Inst<U1>(Opcode::IsHelperInvocation);
368} 380}
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index e70359eb1..7f8f1ad42 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -84,6 +84,9 @@ public:
84 [[nodiscard]] F32 GetAttributeIndexed(const U32& phys_address, const U32& vertex); 84 [[nodiscard]] F32 GetAttributeIndexed(const U32& phys_address, const U32& vertex);
85 void SetAttributeIndexed(const U32& phys_address, const F32& value, const U32& vertex); 85 void SetAttributeIndexed(const U32& phys_address, const F32& value, const U32& vertex);
86 86
87 [[nodiscard]] F32 GetPatch(Patch patch);
88 void SetPatch(Patch patch, const F32& value);
89
87 void SetFragColor(u32 index, u32 component, const F32& value); 90 void SetFragColor(u32 index, u32 component, const F32& value);
88 void SetFragDepth(const F32& value); 91 void SetFragDepth(const F32& value);
89 92
@@ -95,6 +98,7 @@ public:
95 [[nodiscard]] U32 LocalInvocationIdY(); 98 [[nodiscard]] U32 LocalInvocationIdY();
96 [[nodiscard]] U32 LocalInvocationIdZ(); 99 [[nodiscard]] U32 LocalInvocationIdZ();
97 100
101 [[nodiscard]] U32 InvocationId();
98 [[nodiscard]] U1 IsHelperInvocation(); 102 [[nodiscard]] U1 IsHelperInvocation();
99 103
100 [[nodiscard]] U32 LaneId(); 104 [[nodiscard]] U32 LaneId();
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index 204c55fa8..b2d7573d9 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -73,6 +73,7 @@ bool Inst::MayHaveSideEffects() const noexcept {
73 case Opcode::EndPrimitive: 73 case Opcode::EndPrimitive:
74 case Opcode::SetAttribute: 74 case Opcode::SetAttribute:
75 case Opcode::SetAttributeIndexed: 75 case Opcode::SetAttributeIndexed:
76 case Opcode::SetPatch:
76 case Opcode::SetFragColor: 77 case Opcode::SetFragColor:
77 case Opcode::SetFragDepth: 78 case Opcode::SetFragDepth:
78 case Opcode::WriteGlobalU8: 79 case Opcode::WriteGlobalU8:
diff --git a/src/shader_recompiler/frontend/ir/opcodes.cpp b/src/shader_recompiler/frontend/ir/opcodes.cpp
index 7d3e0b2ab..7f04b647b 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.cpp
+++ b/src/shader_recompiler/frontend/ir/opcodes.cpp
@@ -24,6 +24,7 @@ constexpr Type Label{Type::Label};
24constexpr Type Reg{Type::Reg}; 24constexpr Type Reg{Type::Reg};
25constexpr Type Pred{Type::Pred}; 25constexpr Type Pred{Type::Pred};
26constexpr Type Attribute{Type::Attribute}; 26constexpr Type Attribute{Type::Attribute};
27constexpr Type Patch{Type::Patch};
27constexpr Type U1{Type::U1}; 28constexpr Type U1{Type::U1};
28constexpr Type U8{Type::U8}; 29constexpr Type U8{Type::U8};
29constexpr Type U16{Type::U16}; 30constexpr Type U16{Type::U16};
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index 7a21fe746..a86542cd8 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.inc
+++ b/src/shader_recompiler/frontend/ir/opcodes.inc
@@ -48,6 +48,8 @@ OPCODE(GetAttribute, F32, Attr
48OPCODE(SetAttribute, Void, Attribute, F32, U32, ) 48OPCODE(SetAttribute, Void, Attribute, F32, U32, )
49OPCODE(GetAttributeIndexed, F32, U32, U32, ) 49OPCODE(GetAttributeIndexed, F32, U32, U32, )
50OPCODE(SetAttributeIndexed, Void, U32, F32, U32, ) 50OPCODE(SetAttributeIndexed, Void, U32, F32, U32, )
51OPCODE(GetPatch, F32, Patch, )
52OPCODE(SetPatch, Void, Patch, F32, )
51OPCODE(SetFragColor, Void, U32, U32, F32, ) 53OPCODE(SetFragColor, Void, U32, U32, F32, )
52OPCODE(SetFragDepth, Void, F32, ) 54OPCODE(SetFragDepth, Void, F32, )
53OPCODE(GetZFlag, U1, Void, ) 55OPCODE(GetZFlag, U1, Void, )
@@ -60,6 +62,7 @@ OPCODE(SetCFlag, Void, U1,
60OPCODE(SetOFlag, Void, U1, ) 62OPCODE(SetOFlag, Void, U1, )
61OPCODE(WorkgroupId, U32x3, ) 63OPCODE(WorkgroupId, U32x3, )
62OPCODE(LocalInvocationId, U32x3, ) 64OPCODE(LocalInvocationId, U32x3, )
65OPCODE(InvocationId, U32, )
63OPCODE(IsHelperInvocation, U1, ) 66OPCODE(IsHelperInvocation, U1, )
64 67
65// Undefined 68// Undefined
diff --git a/src/shader_recompiler/frontend/ir/patch.cpp b/src/shader_recompiler/frontend/ir/patch.cpp
new file mode 100644
index 000000000..1f770bc48
--- /dev/null
+++ b/src/shader_recompiler/frontend/ir/patch.cpp
@@ -0,0 +1,28 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "shader_recompiler/frontend/ir/patch.h"
6#include "shader_recompiler/exception.h"
7
8namespace Shader::IR {
9
10bool IsGeneric(Patch patch) noexcept {
11 return patch >= Patch::Component0 && patch <= Patch::Component119;
12}
13
14u32 GenericPatchIndex(Patch patch) {
15 if (!IsGeneric(patch)) {
16 throw InvalidArgument("Patch {} is not generic", patch);
17 }
18 return (static_cast<u32>(patch) - static_cast<u32>(Patch::Component0)) / 4;
19}
20
21u32 GenericPatchElement(Patch patch) {
22 if (!IsGeneric(patch)) {
23 throw InvalidArgument("Patch {} is not generic", patch);
24 }
25 return (static_cast<u32>(patch) - static_cast<u32>(Patch::Component0)) % 4;
26}
27
28} // namespace Shader::IR
diff --git a/src/shader_recompiler/frontend/ir/patch.h b/src/shader_recompiler/frontend/ir/patch.h
new file mode 100644
index 000000000..6d66ff0d6
--- /dev/null
+++ b/src/shader_recompiler/frontend/ir/patch.h
@@ -0,0 +1,149 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9namespace Shader::IR {
10
11enum class Patch : u64 {
12 TessellationLodLeft,
13 TessellationLodTop,
14 TessellationLodRight,
15 TessellationLodBottom,
16 TessellationLodInteriorU,
17 TessellationLodInteriorV,
18 ComponentPadding0,
19 ComponentPadding1,
20 Component0,
21 Component1,
22 Component2,
23 Component3,
24 Component4,
25 Component5,
26 Component6,
27 Component7,
28 Component8,
29 Component9,
30 Component10,
31 Component11,
32 Component12,
33 Component13,
34 Component14,
35 Component15,
36 Component16,
37 Component17,
38 Component18,
39 Component19,
40 Component20,
41 Component21,
42 Component22,
43 Component23,
44 Component24,
45 Component25,
46 Component26,
47 Component27,
48 Component28,
49 Component29,
50 Component30,
51 Component31,
52 Component32,
53 Component33,
54 Component34,
55 Component35,
56 Component36,
57 Component37,
58 Component38,
59 Component39,
60 Component40,
61 Component41,
62 Component42,
63 Component43,
64 Component44,
65 Component45,
66 Component46,
67 Component47,
68 Component48,
69 Component49,
70 Component50,
71 Component51,
72 Component52,
73 Component53,
74 Component54,
75 Component55,
76 Component56,
77 Component57,
78 Component58,
79 Component59,
80 Component60,
81 Component61,
82 Component62,
83 Component63,
84 Component64,
85 Component65,
86 Component66,
87 Component67,
88 Component68,
89 Component69,
90 Component70,
91 Component71,
92 Component72,
93 Component73,
94 Component74,
95 Component75,
96 Component76,
97 Component77,
98 Component78,
99 Component79,
100 Component80,
101 Component81,
102 Component82,
103 Component83,
104 Component84,
105 Component85,
106 Component86,
107 Component87,
108 Component88,
109 Component89,
110 Component90,
111 Component91,
112 Component92,
113 Component93,
114 Component94,
115 Component95,
116 Component96,
117 Component97,
118 Component98,
119 Component99,
120 Component100,
121 Component101,
122 Component102,
123 Component103,
124 Component104,
125 Component105,
126 Component106,
127 Component107,
128 Component108,
129 Component109,
130 Component110,
131 Component111,
132 Component112,
133 Component113,
134 Component114,
135 Component115,
136 Component116,
137 Component117,
138 Component118,
139 Component119,
140};
141static_assert(static_cast<u64>(Patch::Component119) == 127);
142
143[[nodiscard]] bool IsGeneric(Patch patch) noexcept;
144
145[[nodiscard]] u32 GenericPatchIndex(Patch patch);
146
147[[nodiscard]] u32 GenericPatchElement(Patch patch);
148
149} // namespace Shader::IR
diff --git a/src/shader_recompiler/frontend/ir/type.h b/src/shader_recompiler/frontend/ir/type.h
index 9a32ca1e8..8b3b33852 100644
--- a/src/shader_recompiler/frontend/ir/type.h
+++ b/src/shader_recompiler/frontend/ir/type.h
@@ -20,26 +20,27 @@ enum class Type {
20 Reg = 1 << 2, 20 Reg = 1 << 2,
21 Pred = 1 << 3, 21 Pred = 1 << 3,
22 Attribute = 1 << 4, 22 Attribute = 1 << 4,
23 U1 = 1 << 5, 23 Patch = 1 << 5,
24 U8 = 1 << 6, 24 U1 = 1 << 6,
25 U16 = 1 << 7, 25 U8 = 1 << 7,
26 U32 = 1 << 8, 26 U16 = 1 << 8,
27 U64 = 1 << 9, 27 U32 = 1 << 9,
28 F16 = 1 << 10, 28 U64 = 1 << 10,
29 F32 = 1 << 11, 29 F16 = 1 << 11,
30 F64 = 1 << 12, 30 F32 = 1 << 12,
31 U32x2 = 1 << 13, 31 F64 = 1 << 13,
32 U32x3 = 1 << 14, 32 U32x2 = 1 << 14,
33 U32x4 = 1 << 15, 33 U32x3 = 1 << 15,
34 F16x2 = 1 << 16, 34 U32x4 = 1 << 16,
35 F16x3 = 1 << 17, 35 F16x2 = 1 << 17,
36 F16x4 = 1 << 18, 36 F16x3 = 1 << 18,
37 F32x2 = 1 << 19, 37 F16x4 = 1 << 19,
38 F32x3 = 1 << 20, 38 F32x2 = 1 << 20,
39 F32x4 = 1 << 21, 39 F32x3 = 1 << 21,
40 F64x2 = 1 << 22, 40 F32x4 = 1 << 22,
41 F64x3 = 1 << 23, 41 F64x2 = 1 << 23,
42 F64x4 = 1 << 24, 42 F64x3 = 1 << 24,
43 F64x4 = 1 << 25,
43}; 44};
44DECLARE_ENUM_FLAG_OPERATORS(Type) 45DECLARE_ENUM_FLAG_OPERATORS(Type)
45 46
diff --git a/src/shader_recompiler/frontend/ir/value.cpp b/src/shader_recompiler/frontend/ir/value.cpp
index 1e7ffb86d..bf5f8c0c2 100644
--- a/src/shader_recompiler/frontend/ir/value.cpp
+++ b/src/shader_recompiler/frontend/ir/value.cpp
@@ -18,6 +18,8 @@ Value::Value(IR::Pred value) noexcept : type{Type::Pred}, pred{value} {}
18 18
19Value::Value(IR::Attribute value) noexcept : type{Type::Attribute}, attribute{value} {} 19Value::Value(IR::Attribute value) noexcept : type{Type::Attribute}, attribute{value} {}
20 20
21Value::Value(IR::Patch value) noexcept : type{Type::Patch}, patch{value} {}
22
21Value::Value(bool value) noexcept : type{Type::U1}, imm_u1{value} {} 23Value::Value(bool value) noexcept : type{Type::U1}, imm_u1{value} {}
22 24
23Value::Value(u8 value) noexcept : type{Type::U8}, imm_u8{value} {} 25Value::Value(u8 value) noexcept : type{Type::U8}, imm_u8{value} {}
@@ -109,6 +111,11 @@ IR::Attribute Value::Attribute() const {
109 return attribute; 111 return attribute;
110} 112}
111 113
114IR::Patch Value::Patch() const {
115 ValidateAccess(Type::Patch);
116 return patch;
117}
118
112bool Value::U1() const { 119bool Value::U1() const {
113 if (IsIdentity()) { 120 if (IsIdentity()) {
114 return inst->Arg(0).U1(); 121 return inst->Arg(0).U1();
@@ -182,6 +189,8 @@ bool Value::operator==(const Value& other) const {
182 return pred == other.pred; 189 return pred == other.pred;
183 case Type::Attribute: 190 case Type::Attribute:
184 return attribute == other.attribute; 191 return attribute == other.attribute;
192 case Type::Patch:
193 return patch == other.patch;
185 case Type::U1: 194 case Type::U1:
186 return imm_u1 == other.imm_u1; 195 return imm_u1 == other.imm_u1;
187 case Type::U8: 196 case Type::U8:
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h
index a0962863d..303745563 100644
--- a/src/shader_recompiler/frontend/ir/value.h
+++ b/src/shader_recompiler/frontend/ir/value.h
@@ -9,6 +9,7 @@
9#include "shader_recompiler/frontend/ir/attribute.h" 9#include "shader_recompiler/frontend/ir/attribute.h"
10#include "shader_recompiler/frontend/ir/pred.h" 10#include "shader_recompiler/frontend/ir/pred.h"
11#include "shader_recompiler/frontend/ir/reg.h" 11#include "shader_recompiler/frontend/ir/reg.h"
12#include "shader_recompiler/frontend/ir/patch.h"
12#include "shader_recompiler/frontend/ir/type.h" 13#include "shader_recompiler/frontend/ir/type.h"
13 14
14namespace Shader::IR { 15namespace Shader::IR {
@@ -24,6 +25,7 @@ public:
24 explicit Value(IR::Reg value) noexcept; 25 explicit Value(IR::Reg value) noexcept;
25 explicit Value(IR::Pred value) noexcept; 26 explicit Value(IR::Pred value) noexcept;
26 explicit Value(IR::Attribute value) noexcept; 27 explicit Value(IR::Attribute value) noexcept;
28 explicit Value(IR::Patch value) noexcept;
27 explicit Value(bool value) noexcept; 29 explicit Value(bool value) noexcept;
28 explicit Value(u8 value) noexcept; 30 explicit Value(u8 value) noexcept;
29 explicit Value(u16 value) noexcept; 31 explicit Value(u16 value) noexcept;
@@ -46,6 +48,7 @@ public:
46 [[nodiscard]] IR::Reg Reg() const; 48 [[nodiscard]] IR::Reg Reg() const;
47 [[nodiscard]] IR::Pred Pred() const; 49 [[nodiscard]] IR::Pred Pred() const;
48 [[nodiscard]] IR::Attribute Attribute() const; 50 [[nodiscard]] IR::Attribute Attribute() const;
51 [[nodiscard]] IR::Patch Patch() const;
49 [[nodiscard]] bool U1() const; 52 [[nodiscard]] bool U1() const;
50 [[nodiscard]] u8 U8() const; 53 [[nodiscard]] u8 U8() const;
51 [[nodiscard]] u16 U16() const; 54 [[nodiscard]] u16 U16() const;
@@ -67,6 +70,7 @@ private:
67 IR::Reg reg; 70 IR::Reg reg;
68 IR::Pred pred; 71 IR::Pred pred;
69 IR::Attribute attribute; 72 IR::Attribute attribute;
73 IR::Patch patch;
70 bool imm_u1; 74 bool imm_u1;
71 u8 imm_u8; 75 u8 imm_u8;
72 u16 imm_u16; 76 u16 imm_u16;
diff --git a/src/shader_recompiler/frontend/maxwell/program.cpp b/src/shader_recompiler/frontend/maxwell/program.cpp
index ab67446c8..20a1d61cc 100644
--- a/src/shader_recompiler/frontend/maxwell/program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/program.cpp
@@ -70,6 +70,11 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
70 program.stage = env.ShaderStage(); 70 program.stage = env.ShaderStage();
71 program.local_memory_size = env.LocalMemorySize(); 71 program.local_memory_size = env.LocalMemorySize();
72 switch (program.stage) { 72 switch (program.stage) {
73 case Stage::TessellationControl: {
74 const ProgramHeader& sph{env.SPH()};
75 program.invocations = sph.common2.threads_per_input_primitive;
76 break;
77 }
73 case Stage::Geometry: { 78 case Stage::Geometry: {
74 const ProgramHeader& sph{env.SPH()}; 79 const ProgramHeader& sph{env.SPH()};
75 program.output_topology = sph.common3.output_topology; 80 program.output_topology = sph.common3.output_topology;
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp
index eb6a80de2..7d7dcc3cb 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp
@@ -70,12 +70,6 @@ void TranslatorVisitor::ALD(u64 insn) {
70 BitField<47, 2, Size> size; 70 BitField<47, 2, Size> size;
71 } const ald{insn}; 71 } const ald{insn};
72 72
73 if (ald.o != 0) {
74 throw NotImplementedException("O");
75 }
76 if (ald.patch != 0) {
77 throw NotImplementedException("P");
78 }
79 const u64 offset{ald.absolute_offset.Value()}; 73 const u64 offset{ald.absolute_offset.Value()};
80 if (offset % 4 != 0) { 74 if (offset % 4 != 0) {
81 throw NotImplementedException("Unaligned absolute offset {}", offset); 75 throw NotImplementedException("Unaligned absolute offset {}", offset);
@@ -84,11 +78,19 @@ void TranslatorVisitor::ALD(u64 insn) {
84 const u32 num_elements{NumElements(ald.size)}; 78 const u32 num_elements{NumElements(ald.size)};
85 if (ald.index_reg == IR::Reg::RZ) { 79 if (ald.index_reg == IR::Reg::RZ) {
86 for (u32 element = 0; element < num_elements; ++element) { 80 for (u32 element = 0; element < num_elements; ++element) {
87 const IR::Attribute attr{offset / 4 + element}; 81 if (ald.patch != 0) {
88 F(ald.dest_reg + element, ir.GetAttribute(attr, vertex)); 82 const IR::Patch patch{offset / 4 + element};
83 F(ald.dest_reg + element, ir.GetPatch(patch));
84 } else {
85 const IR::Attribute attr{offset / 4 + element};
86 F(ald.dest_reg + element, ir.GetAttribute(attr, vertex));
87 }
89 } 88 }
90 return; 89 return;
91 } 90 }
91 if (ald.patch != 0) {
92 throw NotImplementedException("Indirect patch read");
93 }
92 HandleIndexed(*this, ald.index_reg, num_elements, [&](u32 element, IR::U32 final_offset) { 94 HandleIndexed(*this, ald.index_reg, num_elements, [&](u32 element, IR::U32 final_offset) {
93 F(ald.dest_reg + element, ir.GetAttributeIndexed(final_offset, vertex)); 95 F(ald.dest_reg + element, ir.GetAttributeIndexed(final_offset, vertex));
94 }); 96 });
@@ -106,9 +108,6 @@ void TranslatorVisitor::AST(u64 insn) {
106 BitField<47, 2, Size> size; 108 BitField<47, 2, Size> size;
107 } const ast{insn}; 109 } const ast{insn};
108 110
109 if (ast.patch != 0) {
110 throw NotImplementedException("P");
111 }
112 if (ast.index_reg != IR::Reg::RZ) { 111 if (ast.index_reg != IR::Reg::RZ) {
113 throw NotImplementedException("Indexed store"); 112 throw NotImplementedException("Indexed store");
114 } 113 }
@@ -120,11 +119,19 @@ void TranslatorVisitor::AST(u64 insn) {
120 const u32 num_elements{NumElements(ast.size)}; 119 const u32 num_elements{NumElements(ast.size)};
121 if (ast.index_reg == IR::Reg::RZ) { 120 if (ast.index_reg == IR::Reg::RZ) {
122 for (u32 element = 0; element < num_elements; ++element) { 121 for (u32 element = 0; element < num_elements; ++element) {
123 const IR::Attribute attr{offset / 4 + element}; 122 if (ast.patch != 0) {
124 ir.SetAttribute(attr, F(ast.src_reg + element), vertex); 123 const IR::Patch patch{offset / 4 + element};
124 ir.SetPatch(patch, F(ast.src_reg + element));
125 } else {
126 const IR::Attribute attr{offset / 4 + element};
127 ir.SetAttribute(attr, F(ast.src_reg + element), vertex);
128 }
125 } 129 }
126 return; 130 return;
127 } 131 }
132 if (ast.patch != 0) {
133 throw NotImplementedException("Indexed tessellation patch store");
134 }
128 HandleIndexed(*this, ast.index_reg, num_elements, [&](u32 element, IR::U32 final_offset) { 135 HandleIndexed(*this, ast.index_reg, num_elements, [&](u32 element, IR::U32 final_offset) {
129 ir.SetAttributeIndexed(final_offset, F(ast.src_reg + element), vertex); 136 ir.SetAttributeIndexed(final_offset, F(ast.src_reg + element), vertex);
130 }); 137 });
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp
index bc822d585..660b84c20 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp
@@ -113,6 +113,8 @@ enum class SpecialRegister : u64 {
113 113
114[[nodiscard]] IR::U32 Read(IR::IREmitter& ir, SpecialRegister special_register) { 114[[nodiscard]] IR::U32 Read(IR::IREmitter& ir, SpecialRegister special_register) {
115 switch (special_register) { 115 switch (special_register) {
116 case SpecialRegister::SR_INVOCATION_ID:
117 return ir.InvocationId();
116 case SpecialRegister::SR_THREAD_KILL: 118 case SpecialRegister::SR_THREAD_KILL:
117 return IR::U32{ir.Select(ir.IsHelperInvocation(), ir.Imm32(-1), ir.Imm32(0))}; 119 return IR::U32{ir.Select(ir.IsHelperInvocation(), ir.Imm32(-1), ir.Imm32(0))};
118 case SpecialRegister::SR_INVOCATION_INFO: 120 case SpecialRegister::SR_INVOCATION_INFO: