summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp20
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.h1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.h13
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp30
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp38
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp12
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.h4
-rw-r--r--src/shader_recompiler/frontend/ir/modifiers.h5
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.inc1
-rw-r--r--src/shader_recompiler/frontend/ir/value.cpp14
-rw-r--r--src/shader_recompiler/frontend/ir/value.h1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp28
-rw-r--r--src/shader_recompiler/ir_opt/constant_propagation_pass.cpp22
-rw-r--r--src/shader_recompiler/profile.h1
14 files changed, 67 insertions, 123 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index 7d8b938d1..50793b5bf 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -169,7 +169,6 @@ void EmitContext::DefineCommonTypes(const Info& info) {
169 AddCapability(spv::Capability::Float64); 169 AddCapability(spv::Capability::Float64);
170 F64.Define(*this, TypeFloat(64), "f64"); 170 F64.Define(*this, TypeFloat(64), "f64");
171 } 171 }
172 array_U32x2 = Name(TypeArray(U32[2], Constant(U32[1], 4U)), "array-u32x2");
173} 172}
174 173
175void EmitContext::DefineCommonConstants() { 174void EmitContext::DefineCommonConstants() {
@@ -352,20 +351,19 @@ void EmitContext::DefineOutputs(const Info& info) {
352 } 351 }
353 } 352 }
354 if (stage == Stage::Fragment) { 353 if (stage == Stage::Fragment) {
355 for (size_t i = 0; i < 8; ++i) { 354 for (u32 index = 0; index < 8; ++index) {
356 if (!info.stores_frag_color[i]) { 355 if (!info.stores_frag_color[index]) {
357 continue; 356 continue;
358 } 357 }
359 frag_color[i] = DefineOutput(*this, F32[4]); 358 frag_color[index] = DefineOutput(*this, F32[4]);
360 Decorate(frag_color[i], spv::Decoration::Location, static_cast<u32>(i)); 359 Decorate(frag_color[index], spv::Decoration::Location, index);
361 Name(frag_color[i], fmt::format("frag_color{}", i)); 360 Name(frag_color[index], fmt::format("frag_color{}", index));
362 } 361 }
363 if (!info.stores_frag_depth) { 362 if (info.stores_frag_depth) {
364 return; 363 frag_depth = DefineOutput(*this, F32[1]);
364 Decorate(frag_depth, spv::Decoration::BuiltIn, spv::BuiltIn::FragDepth);
365 Name(frag_depth, "frag_depth");
365 } 366 }
366 frag_depth = DefineOutput(*this, F32[1]);
367 Decorate(frag_depth, spv::Decoration::BuiltIn, static_cast<u32>(spv::BuiltIn::FragDepth));
368 Name(frag_depth, "frag_depth");
369 } 367 }
370} 368}
371 369
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h
index 0a1e85408..5ed815c06 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.h
+++ b/src/shader_recompiler/backend/spirv/emit_context.h
@@ -65,7 +65,6 @@ public:
65 VectorTypes U32; 65 VectorTypes U32;
66 VectorTypes F16; 66 VectorTypes F16;
67 VectorTypes F64; 67 VectorTypes F64;
68 Id array_U32x2;
69 68
70 Id true_value{}; 69 Id true_value{};
71 Id false_value{}; 70 Id false_value{};
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h
index cc02f53f1..4da1f3707 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.h
@@ -95,7 +95,7 @@ void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Va
95 Id value); 95 Id value);
96void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, 96void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
97 Id value); 97 Id value);
98Id EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2); 98Id EmitCompositeConstructU32x2(EmitContext& ctx, Id e1, Id e2);
99Id EmitCompositeConstructU32x3(EmitContext& ctx, Id e1, Id e2, Id e3); 99Id EmitCompositeConstructU32x3(EmitContext& ctx, Id e1, Id e2, Id e3);
100Id EmitCompositeConstructU32x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4); 100Id EmitCompositeConstructU32x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4);
101Id EmitCompositeExtractU32x2(EmitContext& ctx, Id composite, u32 index); 101Id EmitCompositeExtractU32x2(EmitContext& ctx, Id composite, u32 index);
@@ -104,7 +104,7 @@ Id EmitCompositeExtractU32x4(EmitContext& ctx, Id composite, u32 index);
104Id EmitCompositeInsertU32x2(EmitContext& ctx, Id composite, Id object, u32 index); 104Id EmitCompositeInsertU32x2(EmitContext& ctx, Id composite, Id object, u32 index);
105Id EmitCompositeInsertU32x3(EmitContext& ctx, Id composite, Id object, u32 index); 105Id EmitCompositeInsertU32x3(EmitContext& ctx, Id composite, Id object, u32 index);
106Id EmitCompositeInsertU32x4(EmitContext& ctx, Id composite, Id object, u32 index); 106Id EmitCompositeInsertU32x4(EmitContext& ctx, Id composite, Id object, u32 index);
107Id EmitCompositeConstructF16x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2); 107Id EmitCompositeConstructF16x2(EmitContext& ctx, Id e1, Id e2);
108Id EmitCompositeConstructF16x3(EmitContext& ctx, Id e1, Id e2, Id e3); 108Id EmitCompositeConstructF16x3(EmitContext& ctx, Id e1, Id e2, Id e3);
109Id EmitCompositeConstructF16x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4); 109Id EmitCompositeConstructF16x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4);
110Id EmitCompositeExtractF16x2(EmitContext& ctx, Id composite, u32 index); 110Id EmitCompositeExtractF16x2(EmitContext& ctx, Id composite, u32 index);
@@ -113,7 +113,7 @@ Id EmitCompositeExtractF16x4(EmitContext& ctx, Id composite, u32 index);
113Id EmitCompositeInsertF16x2(EmitContext& ctx, Id composite, Id object, u32 index); 113Id EmitCompositeInsertF16x2(EmitContext& ctx, Id composite, Id object, u32 index);
114Id EmitCompositeInsertF16x3(EmitContext& ctx, Id composite, Id object, u32 index); 114Id EmitCompositeInsertF16x3(EmitContext& ctx, Id composite, Id object, u32 index);
115Id EmitCompositeInsertF16x4(EmitContext& ctx, Id composite, Id object, u32 index); 115Id EmitCompositeInsertF16x4(EmitContext& ctx, Id composite, Id object, u32 index);
116Id EmitCompositeConstructF32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2); 116Id EmitCompositeConstructF32x2(EmitContext& ctx, Id e1, Id e2);
117Id EmitCompositeConstructF32x3(EmitContext& ctx, Id e1, Id e2, Id e3); 117Id EmitCompositeConstructF32x3(EmitContext& ctx, Id e1, Id e2, Id e3);
118Id EmitCompositeConstructF32x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4); 118Id EmitCompositeConstructF32x4(EmitContext& ctx, Id e1, Id e2, Id e3, Id e4);
119Id EmitCompositeExtractF32x2(EmitContext& ctx, Id composite, u32 index); 119Id EmitCompositeExtractF32x2(EmitContext& ctx, Id composite, u32 index);
@@ -122,7 +122,6 @@ Id EmitCompositeExtractF32x4(EmitContext& ctx, Id composite, u32 index);
122Id EmitCompositeInsertF32x2(EmitContext& ctx, Id composite, Id object, u32 index); 122Id EmitCompositeInsertF32x2(EmitContext& ctx, Id composite, Id object, u32 index);
123Id EmitCompositeInsertF32x3(EmitContext& ctx, Id composite, Id object, u32 index); 123Id EmitCompositeInsertF32x3(EmitContext& ctx, Id composite, Id object, u32 index);
124Id EmitCompositeInsertF32x4(EmitContext& ctx, Id composite, Id object, u32 index); 124Id EmitCompositeInsertF32x4(EmitContext& ctx, Id composite, Id object, u32 index);
125Id EmitCompositeConstructArrayU32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4);
126void EmitCompositeConstructF64x2(EmitContext& ctx); 125void EmitCompositeConstructF64x2(EmitContext& ctx);
127void EmitCompositeConstructF64x3(EmitContext& ctx); 126void EmitCompositeConstructF64x3(EmitContext& ctx);
128void EmitCompositeConstructF64x4(EmitContext& ctx); 127void EmitCompositeConstructF64x4(EmitContext& ctx);
@@ -359,10 +358,10 @@ Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Va
359 Id coords, Id dref, Id bias_lc, Id offset); 358 Id coords, Id dref, Id bias_lc, Id offset);
360Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, 359Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
361 Id coords, Id dref, Id lod_lc, Id offset); 360 Id coords, Id dref, Id lod_lc, Id offset);
362Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, 361Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
363 Id offset2); 362 const IR::Value& offset, const IR::Value& offset2);
364Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 363Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
365 Id offset, Id offset2, Id dref); 364 const IR::Value& offset, const IR::Value& offset2, Id dref);
366Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, 365Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
367 Id lod, Id ms); 366 Id lod, Id ms);
368Id EmitVoteAll(EmitContext& ctx, Id pred); 367Id EmitVoteAll(EmitContext& ctx, Id pred);
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp
index f01d69d91..079e226de 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp
@@ -7,11 +7,7 @@
7 7
8namespace Shader::Backend::SPIRV { 8namespace Shader::Backend::SPIRV {
9 9
10Id EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2) { 10Id EmitCompositeConstructU32x2(EmitContext& ctx, Id e1, Id e2) {
11 const auto info{inst->Flags<IR::CompositeDecoration>()};
12 if (info.is_constant) {
13 return ctx.ConstantComposite(ctx.U32[2], e1, e2);
14 }
15 return ctx.OpCompositeConstruct(ctx.U32[2], e1, e2); 11 return ctx.OpCompositeConstruct(ctx.U32[2], e1, e2);
16} 12}
17 13
@@ -47,12 +43,7 @@ Id EmitCompositeInsertU32x4(EmitContext& ctx, Id composite, Id object, u32 index
47 return ctx.OpCompositeInsert(ctx.U32[4], object, composite, index); 43 return ctx.OpCompositeInsert(ctx.U32[4], object, composite, index);
48} 44}
49 45
50Id EmitCompositeConstructF16x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2) { 46Id EmitCompositeConstructF16x2(EmitContext& ctx, Id e1, Id e2) {
51
52 const auto info{inst->Flags<IR::CompositeDecoration>()};
53 if (info.is_constant) {
54 return ctx.ConstantComposite(ctx.F16[2], e1, e2);
55 }
56 return ctx.OpCompositeConstruct(ctx.F16[2], e1, e2); 47 return ctx.OpCompositeConstruct(ctx.F16[2], e1, e2);
57} 48}
58 49
@@ -88,11 +79,7 @@ Id EmitCompositeInsertF16x4(EmitContext& ctx, Id composite, Id object, u32 index
88 return ctx.OpCompositeInsert(ctx.F16[4], object, composite, index); 79 return ctx.OpCompositeInsert(ctx.F16[4], object, composite, index);
89} 80}
90 81
91Id EmitCompositeConstructF32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2) { 82Id EmitCompositeConstructF32x2(EmitContext& ctx, Id e1, Id e2) {
92 const auto info{inst->Flags<IR::CompositeDecoration>()};
93 if (info.is_constant) {
94 return ctx.ConstantComposite(ctx.F32[2], e1, e2);
95 }
96 return ctx.OpCompositeConstruct(ctx.F32[2], e1, e2); 83 return ctx.OpCompositeConstruct(ctx.F32[2], e1, e2);
97} 84}
98 85
@@ -164,15 +151,4 @@ Id EmitCompositeInsertF64x4(EmitContext& ctx, Id composite, Id object, u32 index
164 return ctx.OpCompositeInsert(ctx.F64[4], object, composite, index); 151 return ctx.OpCompositeInsert(ctx.F64[4], object, composite, index);
165} 152}
166 153
167Id EmitCompositeConstructArrayU32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4) {
168 const auto info{inst->Flags<IR::CompositeDecoration>()};
169 if (info.is_constant) {
170 return ctx.ConstantComposite(ctx.array_U32x2, e1, e2, e3, e4);
171 }
172 if (ctx.profile.support_variadic_ptp) {
173 return ctx.OpCompositeConstruct(ctx.array_U32x2, e1, e2, e3, e4);
174 }
175 return {};
176}
177
178} // namespace Shader::Backend::SPIRV 154} // namespace Shader::Backend::SPIRV
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 13bc8831f..b6e9d3c0c 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -30,16 +30,34 @@ public:
30 } 30 }
31 } 31 }
32 32
33 explicit ImageOperands([[maybe_unused]] EmitContext& ctx, Id offset, Id offset2) { 33 explicit ImageOperands(EmitContext& ctx, const IR::Value& offset, const IR::Value& offset2) {
34 if (Sirit::ValidId(offset)) { 34 if (offset2.IsEmpty()) {
35 Add(spv::ImageOperandsMask::Offset, offset); 35 if (offset.IsEmpty()) {
36 return;
37 }
38 Add(spv::ImageOperandsMask::Offset, ctx.Def(offset));
39 return;
40 }
41 const std::array values{offset.InstRecursive(), offset2.InstRecursive()};
42 if (!values[0]->AreAllArgsImmediates() || !values[1]->AreAllArgsImmediates()) {
43 throw NotImplementedException("Not all arguments in PTP are immediate");
36 } 44 }
37 if (Sirit::ValidId(offset2)) { 45 const IR::Opcode opcode{values[0]->Opcode()};
38 Add(spv::ImageOperandsMask::ConstOffsets, offset2); 46 if (opcode != values[1]->Opcode() || opcode != IR::Opcode::CompositeConstructU32x4) {
47 throw LogicError("Invalid PTP arguments");
39 } 48 }
49 auto read{[&](int a, int b) { return ctx.Constant(ctx.U32[1], values[a]->Arg(b).U32()); }};
50
51 const Id offsets{
52 ctx.ConstantComposite(ctx.TypeArray(ctx.U32[2], ctx.Constant(ctx.U32[1], 4)),
53 ctx.ConstantComposite(ctx.U32[2], read(0, 0), read(0, 1)),
54 ctx.ConstantComposite(ctx.U32[2], read(0, 2), read(0, 3)),
55 ctx.ConstantComposite(ctx.U32[2], read(1, 0), read(1, 1)),
56 ctx.ConstantComposite(ctx.U32[2], read(1, 2), read(1, 3)))};
57 Add(spv::ImageOperandsMask::ConstOffsets, offsets);
40 } 58 }
41 59
42 explicit ImageOperands([[maybe_unused]] EmitContext& ctx, Id offset, Id lod, Id ms) { 60 explicit ImageOperands(Id offset, Id lod, Id ms) {
43 if (Sirit::ValidId(lod)) { 61 if (Sirit::ValidId(lod)) {
44 Add(spv::ImageOperandsMask::Lod, lod); 62 Add(spv::ImageOperandsMask::Lod, lod);
45 } 63 }
@@ -197,8 +215,8 @@ Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Va
197 Texture(ctx, index), coords, dref, operands.Mask(), operands.Span()); 215 Texture(ctx, index), coords, dref, operands.Mask(), operands.Span());
198} 216}
199 217
200Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, 218Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
201 Id offset2) { 219 const IR::Value& offset, const IR::Value& offset2) {
202 const auto info{inst->Flags<IR::TextureInstInfo>()}; 220 const auto info{inst->Flags<IR::TextureInstInfo>()};
203 const ImageOperands operands(ctx, offset, offset2); 221 const ImageOperands operands(ctx, offset, offset2);
204 return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst, 222 return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst,
@@ -208,7 +226,7 @@ Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id
208} 226}
209 227
210Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 228Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
211 Id offset, Id offset2, Id dref) { 229 const IR::Value& offset, const IR::Value& offset2, Id dref) {
212 const auto info{inst->Flags<IR::TextureInstInfo>()}; 230 const auto info{inst->Flags<IR::TextureInstInfo>()};
213 const ImageOperands operands(ctx, offset, offset2); 231 const ImageOperands operands(ctx, offset, offset2);
214 return Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, ctx, inst, 232 return Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, ctx, inst,
@@ -218,7 +236,7 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
218Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, 236Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
219 Id lod, Id ms) { 237 Id lod, Id ms) {
220 const auto info{inst->Flags<IR::TextureInstInfo>()}; 238 const auto info{inst->Flags<IR::TextureInstInfo>()};
221 const ImageOperands operands(ctx, offset, lod, ms); 239 const ImageOperands operands(offset, lod, ms);
222 return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], 240 return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4],
223 Texture(ctx, index), coords, operands.Mask(), operands.Span()); 241 Texture(ctx, index), coords, operands.Mask(), operands.Span());
224} 242}
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index b8d36f362..0296f8773 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -398,16 +398,15 @@ Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2) {
398 if (e1.Type() != e2.Type()) { 398 if (e1.Type() != e2.Type()) {
399 throw InvalidArgument("Mismatching types {} and {}", e1.Type(), e2.Type()); 399 throw InvalidArgument("Mismatching types {} and {}", e1.Type(), e2.Type());
400 } 400 }
401 CompositeDecoration decor{};
402 switch (e1.Type()) { 401 switch (e1.Type()) {
403 case Type::U32: 402 case Type::U32:
404 return Inst(Opcode::CompositeConstructU32x2, Flags{decor}, e1, e2); 403 return Inst(Opcode::CompositeConstructU32x2, e1, e2);
405 case Type::F16: 404 case Type::F16:
406 return Inst(Opcode::CompositeConstructF16x2, Flags{decor}, e1, e2); 405 return Inst(Opcode::CompositeConstructF16x2, e1, e2);
407 case Type::F32: 406 case Type::F32:
408 return Inst(Opcode::CompositeConstructF32x2, Flags{decor}, e1, e2); 407 return Inst(Opcode::CompositeConstructF32x2, e1, e2);
409 case Type::F64: 408 case Type::F64:
410 return Inst(Opcode::CompositeConstructF64x2, Flags{decor}, e1, e2); 409 return Inst(Opcode::CompositeConstructF64x2, e1, e2);
411 default: 410 default:
412 ThrowInvalidType(e1.Type()); 411 ThrowInvalidType(e1.Type());
413 } 412 }
@@ -437,7 +436,6 @@ Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2, const Valu
437 throw InvalidArgument("Mismatching types {}, {}, {}, and {}", e1.Type(), e2.Type(), 436 throw InvalidArgument("Mismatching types {}, {}, {}, and {}", e1.Type(), e2.Type(),
438 e3.Type(), e4.Type()); 437 e3.Type(), e4.Type());
439 } 438 }
440 CompositeDecoration decor{};
441 switch (e1.Type()) { 439 switch (e1.Type()) {
442 case Type::U32: 440 case Type::U32:
443 return Inst(Opcode::CompositeConstructU32x4, e1, e2, e3, e4); 441 return Inst(Opcode::CompositeConstructU32x4, e1, e2, e3, e4);
@@ -447,8 +445,6 @@ Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2, const Valu
447 return Inst(Opcode::CompositeConstructF32x4, e1, e2, e3, e4); 445 return Inst(Opcode::CompositeConstructF32x4, e1, e2, e3, e4);
448 case Type::F64: 446 case Type::F64:
449 return Inst(Opcode::CompositeConstructF64x4, e1, e2, e3, e4); 447 return Inst(Opcode::CompositeConstructF64x4, e1, e2, e3, e4);
450 case Type::U32x2:
451 return Inst(Opcode::CompositeConstructArrayU32x2, Flags{decor}, e1, e2, e3, e4);
452 default: 448 default:
453 ThrowInvalidType(e1.Type()); 449 ThrowInvalidType(e1.Type());
454 } 450 }
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.h b/src/shader_recompiler/frontend/ir/microinstruction.h
index 77296cfa4..6658dc674 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.h
+++ b/src/shader_recompiler/frontend/ir/microinstruction.h
@@ -101,8 +101,8 @@ public:
101 101
102 template <typename FlagsType> 102 template <typename FlagsType>
103 requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>) 103 requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>)
104 [[nodiscard]] void SetFlags(FlagsType& new_val) noexcept { 104 [[nodiscard]] void SetFlags(FlagsType value) noexcept {
105 std::memcpy(&flags, &new_val, sizeof(new_val)); 105 std::memcpy(&flags, &value, sizeof(value));
106 } 106 }
107 107
108 /// Intrusively store the host definition of this instruction. 108 /// Intrusively store the host definition of this instruction.
diff --git a/src/shader_recompiler/frontend/ir/modifiers.h b/src/shader_recompiler/frontend/ir/modifiers.h
index 20fb14fea..4f09a4b39 100644
--- a/src/shader_recompiler/frontend/ir/modifiers.h
+++ b/src/shader_recompiler/frontend/ir/modifiers.h
@@ -32,11 +32,6 @@ struct FpControl {
32}; 32};
33static_assert(sizeof(FpControl) <= sizeof(u32)); 33static_assert(sizeof(FpControl) <= sizeof(u32));
34 34
35struct CompositeDecoration {
36 bool is_constant{false};
37};
38static_assert(sizeof(CompositeDecoration) <= sizeof(u32));
39
40union TextureInstInfo { 35union TextureInstInfo {
41 u32 raw; 36 u32 raw;
42 BitField<0, 8, TextureType> type; 37 BitField<0, 8, TextureType> type;
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index 3dacd7b6b..e12b92c47 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.inc
+++ b/src/shader_recompiler/frontend/ir/opcodes.inc
@@ -126,7 +126,6 @@ OPCODE(CompositeExtractF64x4, F64, F64x
126OPCODE(CompositeInsertF64x2, F64x2, F64x2, F64, U32, ) 126OPCODE(CompositeInsertF64x2, F64x2, F64x2, F64, U32, )
127OPCODE(CompositeInsertF64x3, F64x3, F64x3, F64, U32, ) 127OPCODE(CompositeInsertF64x3, F64x3, F64x3, F64, U32, )
128OPCODE(CompositeInsertF64x4, F64x4, F64x4, F64, U32, ) 128OPCODE(CompositeInsertF64x4, F64x4, F64x4, F64, U32, )
129OPCODE(CompositeConstructArrayU32x2, Opaque, U32x2, U32x2, U32x2, U32x2, )
130 129
131// Select operations 130// Select operations
132OPCODE(SelectU1, U1, U1, U1, U1, ) 131OPCODE(SelectU1, U1, U1, U1, U1, )
diff --git a/src/shader_recompiler/frontend/ir/value.cpp b/src/shader_recompiler/frontend/ir/value.cpp
index 7671fc3d8..e8e4662e7 100644
--- a/src/shader_recompiler/frontend/ir/value.cpp
+++ b/src/shader_recompiler/frontend/ir/value.cpp
@@ -44,20 +44,6 @@ bool Value::IsEmpty() const noexcept {
44 return type == Type::Void; 44 return type == Type::Void;
45} 45}
46 46
47bool Value::IsConstantContainer() const {
48 if (IsImmediate()) {
49 return true;
50 }
51 ValidateAccess(Type::Opaque);
52 auto num_args = inst->NumArgs();
53 for (size_t i = 0; i < num_args; i++) {
54 if (!inst->Arg(i).IsConstantContainer()) {
55 return false;
56 }
57 }
58 return true;
59}
60
61bool Value::IsImmediate() const noexcept { 47bool Value::IsImmediate() const noexcept {
62 if (IsIdentity()) { 48 if (IsIdentity()) {
63 return inst->Arg(0).IsImmediate(); 49 return inst->Arg(0).IsImmediate();
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h
index 5d6e74c14..b27601e70 100644
--- a/src/shader_recompiler/frontend/ir/value.h
+++ b/src/shader_recompiler/frontend/ir/value.h
@@ -38,7 +38,6 @@ public:
38 [[nodiscard]] bool IsImmediate() const noexcept; 38 [[nodiscard]] bool IsImmediate() const noexcept;
39 [[nodiscard]] bool IsLabel() const noexcept; 39 [[nodiscard]] bool IsLabel() const noexcept;
40 [[nodiscard]] IR::Type Type() const noexcept; 40 [[nodiscard]] IR::Type Type() const noexcept;
41 [[nodiscard]] bool IsConstantContainer() const;
42 41
43 [[nodiscard]] IR::Inst* Inst() const; 42 [[nodiscard]] IR::Inst* Inst() const;
44 [[nodiscard]] IR::Block* Label() const; 43 [[nodiscard]] IR::Block* Label() const;
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp
index cdf5cb5c4..b2f9cda46 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp
@@ -106,17 +106,17 @@ IR::Value MakeOffset(TranslatorVisitor& v, IR::Reg& reg, TextureType type) {
106 throw NotImplementedException("Invalid texture type {}", type); 106 throw NotImplementedException("Invalid texture type {}", type);
107} 107}
108 108
109IR::Value MakeOffsetPTP(TranslatorVisitor& v, IR::Reg& reg) { 109std::pair<IR::Value, IR::Value> MakeOffsetPTP(TranslatorVisitor& v, IR::Reg& reg) {
110 const IR::U32 value1{v.X(reg++)}; 110 const IR::U32 value1{v.X(reg++)};
111 const IR::U32 value2{v.X(reg++)}; 111 const IR::U32 value2{v.X(reg++)};
112 const IR::U32 bitsize = v.ir.Imm32(6); 112 const IR::U32 bitsize{v.ir.Imm32(6)};
113 const auto getVector = ([&v, &bitsize](const IR::U32& value, u32 base) { 113 const auto make_vector{[&v, &bitsize](const IR::U32& value) {
114 return v.ir.CompositeConstruct( 114 return v.ir.CompositeConstruct(v.ir.BitFieldExtract(value, v.ir.Imm32(0), bitsize, true),
115 v.ir.BitFieldExtract(value, v.ir.Imm32(base + 0), bitsize, true), 115 v.ir.BitFieldExtract(value, v.ir.Imm32(8), bitsize, true),
116 v.ir.BitFieldExtract(value, v.ir.Imm32(base + 8), bitsize, true)); 116 v.ir.BitFieldExtract(value, v.ir.Imm32(16), bitsize, true),
117 }); 117 v.ir.BitFieldExtract(value, v.ir.Imm32(24), bitsize, true));
118 return v.ir.CompositeConstruct(getVector(value1, 0), getVector(value1, 16), 118 }};
119 getVector(value2, 0), getVector(value2, 16)); 119 return {make_vector(value1), make_vector(value2)};
120} 120}
121 121
122void Impl(TranslatorVisitor& v, u64 insn, ComponentType component_type, OffsetType offset_type, 122void Impl(TranslatorVisitor& v, u64 insn, ComponentType component_type, OffsetType offset_type,
@@ -150,14 +150,12 @@ void Impl(TranslatorVisitor& v, u64 insn, ComponentType component_type, OffsetTy
150 switch (offset_type) { 150 switch (offset_type) {
151 case OffsetType::None: 151 case OffsetType::None:
152 break; 152 break;
153 case OffsetType::AOFFI: { 153 case OffsetType::AOFFI:
154 offset = MakeOffset(v, meta_reg, tld4.type); 154 offset = MakeOffset(v, meta_reg, tld4.type);
155 break; 155 break;
156 } 156 case OffsetType::PTP:
157 case OffsetType::PTP: { 157 std::tie(offset, offset2) = MakeOffsetPTP(v, meta_reg);
158 offset2 = MakeOffsetPTP(v, meta_reg);
159 break; 158 break;
160 }
161 default: 159 default:
162 throw NotImplementedException("Invalid offset type {}", offset_type); 160 throw NotImplementedException("Invalid offset type {}", offset_type);
163 } 161 }
@@ -167,7 +165,7 @@ void Impl(TranslatorVisitor& v, u64 insn, ComponentType component_type, OffsetTy
167 IR::TextureInstInfo info{}; 165 IR::TextureInstInfo info{};
168 info.type.Assign(GetType(tld4.type, tld4.dc != 0)); 166 info.type.Assign(GetType(tld4.type, tld4.dc != 0));
169 info.gather_component.Assign(static_cast<u32>(component_type)); 167 info.gather_component.Assign(static_cast<u32>(component_type));
170 const IR::Value sample{[&]() -> IR::Value { 168 const IR::Value sample{[&] {
171 if (tld4.dc == 0) { 169 if (tld4.dc == 0) {
172 return v.ir.ImageGather(handle, coords, offset, offset2, info); 170 return v.ir.ImageGather(handle, coords, offset, offset2, info);
173 } 171 }
diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
index 12159e738..052f1609b 100644
--- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
+++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
@@ -355,17 +355,6 @@ void FoldBranchConditional(IR::Inst& inst) {
355 } 355 }
356} 356}
357 357
358void FoldConstantComposite(IR::Inst& inst, size_t amount = 2) {
359 for (size_t i = 0; i < amount; i++) {
360 if (!inst.Arg(i).IsConstantContainer()) {
361 return;
362 }
363 }
364 auto info{inst.Flags<IR::CompositeDecoration>()};
365 info.is_constant = true;
366 inst.SetFlags(info);
367}
368
369void ConstantPropagation(IR::Block& block, IR::Inst& inst) { 358void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
370 switch (inst.Opcode()) { 359 switch (inst.Opcode()) {
371 case IR::Opcode::GetRegister: 360 case IR::Opcode::GetRegister:
@@ -391,13 +380,6 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
391 case IR::Opcode::SelectF32: 380 case IR::Opcode::SelectF32:
392 case IR::Opcode::SelectF64: 381 case IR::Opcode::SelectF64:
393 return FoldSelect(inst); 382 return FoldSelect(inst);
394 case IR::Opcode::CompositeConstructU32x2:
395 case IR::Opcode::CompositeConstructF16x2:
396 case IR::Opcode::CompositeConstructF32x2:
397 case IR::Opcode::CompositeConstructF64x2:
398 return FoldConstantComposite(inst, 2);
399 case IR::Opcode::CompositeConstructArrayU32x2:
400 return FoldConstantComposite(inst, 4);
401 case IR::Opcode::FPMul32: 383 case IR::Opcode::FPMul32:
402 return FoldFPMul32(inst); 384 return FoldFPMul32(inst);
403 case IR::Opcode::LogicalAnd: 385 case IR::Opcode::LogicalAnd:
@@ -423,12 +405,12 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
423 return; 405 return;
424 case IR::Opcode::BitFieldSExtract: 406 case IR::Opcode::BitFieldSExtract:
425 FoldWhenAllImmediates(inst, [](s32 base, u32 shift, u32 count) { 407 FoldWhenAllImmediates(inst, [](s32 base, u32 shift, u32 count) {
426 const size_t back_shift = static_cast<size_t>(shift) + static_cast<size_t>(count); 408 const size_t back_shift{static_cast<size_t>(shift) + static_cast<size_t>(count)};
427 if (back_shift > Common::BitSize<s32>()) { 409 if (back_shift > Common::BitSize<s32>()) {
428 throw LogicError("Undefined result in {}({}, {}, {})", IR::Opcode::BitFieldSExtract, 410 throw LogicError("Undefined result in {}({}, {}, {})", IR::Opcode::BitFieldSExtract,
429 base, shift, count); 411 base, shift, count);
430 } 412 }
431 const size_t left_shift = Common::BitSize<s32>() - back_shift; 413 const size_t left_shift{Common::BitSize<s32>() - back_shift};
432 return static_cast<u32>(static_cast<s32>(base << left_shift) >> 414 return static_cast<u32>(static_cast<s32>(base << left_shift) >>
433 static_cast<size_t>(Common::BitSize<s32>() - count)); 415 static_cast<size_t>(Common::BitSize<s32>() - count));
434 }); 416 });
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h
index 64031f49c..41550bfc6 100644
--- a/src/shader_recompiler/profile.h
+++ b/src/shader_recompiler/profile.h
@@ -30,7 +30,6 @@ struct Profile {
30 bool support_fp32_signed_zero_nan_preserve{}; 30 bool support_fp32_signed_zero_nan_preserve{};
31 bool support_fp64_signed_zero_nan_preserve{}; 31 bool support_fp64_signed_zero_nan_preserve{};
32 bool support_vote{}; 32 bool support_vote{};
33 bool support_variadic_ptp{};
34 bool warp_size_potentially_larger_than_guest{}; 33 bool warp_size_potentially_larger_than_guest{};
35 34
36 // FClamp is broken and OpFMax + OpFMin should be used instead 35 // FClamp is broken and OpFMax + OpFMin should be used instead