summaryrefslogtreecommitdiff
path: root/src/shader_recompiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler')
-rw-r--r--src/shader_recompiler/CMakeLists.txt1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp35
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.h10
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.h2
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp69
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_special.cpp35
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp8
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.h3
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.cpp2
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.inc4
-rw-r--r--src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp7
-rw-r--r--src/shader_recompiler/profile.h13
12 files changed, 149 insertions, 40 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt
index 086bdf8d0..028e8b2d2 100644
--- a/src/shader_recompiler/CMakeLists.txt
+++ b/src/shader_recompiler/CMakeLists.txt
@@ -14,6 +14,7 @@ add_library(shader_recompiler STATIC
14 backend/spirv/emit_spirv_logical.cpp 14 backend/spirv/emit_spirv_logical.cpp
15 backend/spirv/emit_spirv_memory.cpp 15 backend/spirv/emit_spirv_memory.cpp
16 backend/spirv/emit_spirv_select.cpp 16 backend/spirv/emit_spirv_select.cpp
17 backend/spirv/emit_spirv_special.cpp
17 backend/spirv/emit_spirv_undefined.cpp 18 backend/spirv/emit_spirv_undefined.cpp
18 backend/spirv/emit_spirv_vote.cpp 19 backend/spirv/emit_spirv_vote.cpp
19 environment.h 20 environment.h
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index 36f130781..ea46af244 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -67,6 +67,18 @@ Id DefineInput(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin =
67Id DefineOutput(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin = std::nullopt) { 67Id DefineOutput(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin = std::nullopt) {
68 return DefineVariable(ctx, type, builtin, spv::StorageClass::Output); 68 return DefineVariable(ctx, type, builtin, spv::StorageClass::Output);
69} 69}
70
71Id GetAttributeType(EmitContext& ctx, AttributeType type) {
72 switch (type) {
73 case AttributeType::Float:
74 return ctx.F32[4];
75 case AttributeType::SignedInt:
76 return ctx.TypeVector(ctx.TypeInt(32, true), 4);
77 case AttributeType::UnsignedInt:
78 return ctx.U32[4];
79 }
80 throw InvalidArgument("Invalid attribute type {}", type);
81}
70} // Anonymous namespace 82} // Anonymous namespace
71 83
72void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) { 84void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) {
@@ -82,11 +94,11 @@ void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_vie
82} 94}
83 95
84EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& binding) 96EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& binding)
85 : Sirit::Module(0x00010000), profile{profile_} { 97 : Sirit::Module(0x00010000), profile{profile_}, stage{program.stage} {
86 AddCapability(spv::Capability::Shader); 98 AddCapability(spv::Capability::Shader);
87 DefineCommonTypes(program.info); 99 DefineCommonTypes(program.info);
88 DefineCommonConstants(); 100 DefineCommonConstants();
89 DefineInterfaces(program.info, program.stage); 101 DefineInterfaces(program.info);
90 DefineConstantBuffers(program.info, binding); 102 DefineConstantBuffers(program.info, binding);
91 DefineStorageBuffers(program.info, binding); 103 DefineStorageBuffers(program.info, binding);
92 DefineTextures(program.info, binding); 104 DefineTextures(program.info, binding);
@@ -130,6 +142,9 @@ void EmitContext::DefineCommonTypes(const Info& info) {
130 U32.Define(*this, TypeInt(32, false), "u32"); 142 U32.Define(*this, TypeInt(32, false), "u32");
131 143
132 input_f32 = Name(TypePointer(spv::StorageClass::Input, F32[1]), "input_f32"); 144 input_f32 = Name(TypePointer(spv::StorageClass::Input, F32[1]), "input_f32");
145 input_u32 = Name(TypePointer(spv::StorageClass::Input, U32[1]), "input_u32");
146 input_s32 = Name(TypePointer(spv::StorageClass::Input, TypeInt(32, true)), "input_s32");
147
133 output_f32 = Name(TypePointer(spv::StorageClass::Output, F32[1]), "output_f32"); 148 output_f32 = Name(TypePointer(spv::StorageClass::Output, F32[1]), "output_f32");
134 149
135 if (info.uses_int8) { 150 if (info.uses_int8) {
@@ -162,9 +177,9 @@ void EmitContext::DefineCommonConstants() {
162 u32_zero_value = Constant(U32[1], 0U); 177 u32_zero_value = Constant(U32[1], 0U);
163} 178}
164 179
165void EmitContext::DefineInterfaces(const Info& info, Stage stage) { 180void EmitContext::DefineInterfaces(const Info& info) {
166 DefineInputs(info, stage); 181 DefineInputs(info);
167 DefineOutputs(info, stage); 182 DefineOutputs(info);
168} 183}
169 184
170void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) { 185void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) {
@@ -252,7 +267,7 @@ void EmitContext::DefineLabels(IR::Program& program) {
252 } 267 }
253} 268}
254 269
255void EmitContext::DefineInputs(const Info& info, Stage stage) { 270void EmitContext::DefineInputs(const Info& info) {
256 if (info.uses_workgroup_id) { 271 if (info.uses_workgroup_id) {
257 workgroup_id = DefineInput(*this, U32[3], spv::BuiltIn::WorkgroupId); 272 workgroup_id = DefineInput(*this, U32[3], spv::BuiltIn::WorkgroupId);
258 } 273 }
@@ -288,8 +303,8 @@ void EmitContext::DefineInputs(const Info& info, Stage stage) {
288 if (!info.loads_generics[index]) { 303 if (!info.loads_generics[index]) {
289 continue; 304 continue;
290 } 305 }
291 // FIXME: Declare size from input 306 const Id type{GetAttributeType(*this, profile.generic_input_types[index])};
292 const Id id{DefineInput(*this, F32[4])}; 307 const Id id{DefineInput(*this, type)};
293 Decorate(id, spv::Decoration::Location, static_cast<u32>(index)); 308 Decorate(id, spv::Decoration::Location, static_cast<u32>(index));
294 Name(id, fmt::format("in_attr{}", index)); 309 Name(id, fmt::format("in_attr{}", index));
295 input_generics[index] = id; 310 input_generics[index] = id;
@@ -323,8 +338,8 @@ void EmitContext::DefineConstantBuffers(const Info& info, Id UniformDefinitions:
323 } 338 }
324} 339}
325 340
326void EmitContext::DefineOutputs(const Info& info, Stage stage) { 341void EmitContext::DefineOutputs(const Info& info) {
327 if (info.stores_position) { 342 if (info.stores_position || stage == Stage::VertexB) {
328 output_position = DefineOutput(*this, F32[4], spv::BuiltIn::Position); 343 output_position = DefineOutput(*this, F32[4], spv::BuiltIn::Position);
329 } 344 }
330 for (size_t i = 0; i < info.stores_generics.size(); ++i) { 345 for (size_t i = 0; i < info.stores_generics.size(); ++i) {
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h
index 6e64360bf..5ed815c06 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.h
+++ b/src/shader_recompiler/backend/spirv/emit_context.h
@@ -52,6 +52,7 @@ public:
52 [[nodiscard]] Id Def(const IR::Value& value); 52 [[nodiscard]] Id Def(const IR::Value& value);
53 53
54 const Profile& profile; 54 const Profile& profile;
55 Stage stage{};
55 56
56 Id void_id{}; 57 Id void_id{};
57 Id U1{}; 58 Id U1{};
@@ -72,6 +73,9 @@ public:
72 UniformDefinitions uniform_types; 73 UniformDefinitions uniform_types;
73 74
74 Id input_f32{}; 75 Id input_f32{};
76 Id input_u32{};
77 Id input_s32{};
78
75 Id output_f32{}; 79 Id output_f32{};
76 80
77 Id storage_u32{}; 81 Id storage_u32{};
@@ -104,7 +108,7 @@ public:
104private: 108private:
105 void DefineCommonTypes(const Info& info); 109 void DefineCommonTypes(const Info& info);
106 void DefineCommonConstants(); 110 void DefineCommonConstants();
107 void DefineInterfaces(const Info& info, Stage stage); 111 void DefineInterfaces(const Info& info);
108 void DefineConstantBuffers(const Info& info, u32& binding); 112 void DefineConstantBuffers(const Info& info, u32& binding);
109 void DefineStorageBuffers(const Info& info, u32& binding); 113 void DefineStorageBuffers(const Info& info, u32& binding);
110 void DefineTextures(const Info& info, u32& binding); 114 void DefineTextures(const Info& info, u32& binding);
@@ -113,8 +117,8 @@ private:
113 void DefineConstantBuffers(const Info& info, Id UniformDefinitions::*member_type, u32 binding, 117 void DefineConstantBuffers(const Info& info, Id UniformDefinitions::*member_type, u32 binding,
114 Id type, char type_char, u32 element_size); 118 Id type, char type_char, u32 element_size);
115 119
116 void DefineInputs(const Info& info, Stage stage); 120 void DefineInputs(const Info& info);
117 void DefineOutputs(const Info& info, Stage stage); 121 void DefineOutputs(const Info& info);
118}; 122};
119 123
120} // namespace Shader::Backend::SPIRV 124} // namespace Shader::Backend::SPIRV
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h
index ce23200f2..7fefcf2f2 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.h
@@ -28,6 +28,8 @@ void EmitLoopMerge(EmitContext& ctx, Id merge_label, Id continue_label);
28void EmitSelectionMerge(EmitContext& ctx, Id merge_label); 28void EmitSelectionMerge(EmitContext& ctx, Id merge_label);
29void EmitReturn(EmitContext& ctx); 29void EmitReturn(EmitContext& ctx);
30void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label); 30void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label);
31void EmitPrologue(EmitContext& ctx);
32void EmitEpilogue(EmitContext& ctx);
31void EmitGetRegister(EmitContext& ctx); 33void EmitGetRegister(EmitContext& ctx);
32void EmitSetRegister(EmitContext& ctx); 34void EmitSetRegister(EmitContext& ctx);
33void EmitGetPred(EmitContext& ctx); 35void EmitGetPred(EmitContext& ctx);
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 052b84151..8fc040f8b 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
@@ -2,30 +2,26 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <tuple>
6
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 7#include "shader_recompiler/backend/spirv/emit_spirv.h"
6 8
9#pragma optimize("", off)
10
7namespace Shader::Backend::SPIRV { 11namespace Shader::Backend::SPIRV {
8namespace { 12namespace {
9Id InputAttrPointer(EmitContext& ctx, IR::Attribute attr) { 13std::tuple<Id, Id, bool> AttrTypes(EmitContext& ctx, u32 index) {
10 const u32 element{static_cast<u32>(attr) % 4}; 14 const bool is_first_reader{ctx.stage == Stage::VertexB};
11 const auto element_id{[&] { return ctx.Constant(ctx.U32[1], element); }}; 15 const AttributeType type{ctx.profile.generic_input_types.at(index)};
12 if (IR::IsGeneric(attr)) { 16 switch (type) {
13 const u32 index{IR::GenericAttributeIndex(attr)}; 17 case AttributeType::Float:
14 return ctx.OpAccessChain(ctx.input_f32, ctx.input_generics.at(index), element_id()); 18 return {ctx.input_f32, ctx.F32[1], false};
15 } 19 case AttributeType::UnsignedInt:
16 switch (attr) { 20 return {ctx.input_u32, ctx.U32[1], true};
17 case IR::Attribute::PositionX: 21 case AttributeType::SignedInt:
18 case IR::Attribute::PositionY: 22 return {ctx.input_s32, ctx.TypeInt(32, true), true};
19 case IR::Attribute::PositionZ:
20 case IR::Attribute::PositionW:
21 return ctx.OpAccessChain(ctx.input_f32, ctx.input_position, element_id());
22 case IR::Attribute::InstanceId:
23 return ctx.OpLoad(ctx.U32[1], ctx.instance_id);
24 case IR::Attribute::VertexId:
25 return ctx.OpLoad(ctx.U32[1], ctx.vertex_id);
26 default:
27 throw NotImplementedException("Read attribute {}", attr);
28 } 23 }
24 throw InvalidArgument("Invalid attribute type {}", type);
29} 25}
30 26
31Id OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { 27Id OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
@@ -129,19 +125,40 @@ Id EmitGetCbufU64(EmitContext& ctx, const IR::Value& binding, const IR::Value& o
129} 125}
130 126
131Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr) { 127Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr) {
132 if (!ctx.profile.support_vertex_instance_id) { 128 const u32 element{static_cast<u32>(attr) % 4};
133 switch (attr) { 129 const auto element_id{[&] { return ctx.Constant(ctx.U32[1], element); }};
134 case IR::Attribute::InstanceId: 130 if (IR::IsGeneric(attr)) {
131 const u32 index{IR::GenericAttributeIndex(attr)};
132 const auto [pointer_type, type, needs_cast]{AttrTypes(ctx, index)};
133 const Id generic_id{ctx.input_generics.at(index)};
134 const Id pointer{ctx.OpAccessChain(pointer_type, generic_id, element_id())};
135 const Id value{ctx.OpLoad(type, pointer)};
136 return needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value;
137 }
138 switch (attr) {
139 case IR::Attribute::PositionX:
140 case IR::Attribute::PositionY:
141 case IR::Attribute::PositionZ:
142 case IR::Attribute::PositionW:
143 return ctx.OpLoad(ctx.F32[1],
144 ctx.OpAccessChain(ctx.input_f32, ctx.input_position, element_id()));
145 case IR::Attribute::InstanceId:
146 if (ctx.profile.support_vertex_instance_id) {
147 return ctx.OpLoad(ctx.U32[1], ctx.instance_id);
148 } else {
135 return ctx.OpISub(ctx.U32[1], ctx.OpLoad(ctx.U32[1], ctx.instance_index), 149 return ctx.OpISub(ctx.U32[1], ctx.OpLoad(ctx.U32[1], ctx.instance_index),
136 ctx.OpLoad(ctx.U32[1], ctx.base_instance)); 150 ctx.OpLoad(ctx.U32[1], ctx.base_instance));
137 case IR::Attribute::VertexId: 151 }
152 case IR::Attribute::VertexId:
153 if (ctx.profile.support_vertex_instance_id) {
154 return ctx.OpLoad(ctx.U32[1], ctx.vertex_id);
155 } else {
138 return ctx.OpISub(ctx.U32[1], ctx.OpLoad(ctx.U32[1], ctx.vertex_index), 156 return ctx.OpISub(ctx.U32[1], ctx.OpLoad(ctx.U32[1], ctx.vertex_index),
139 ctx.OpLoad(ctx.U32[1], ctx.base_vertex)); 157 ctx.OpLoad(ctx.U32[1], ctx.base_vertex));
140 default:
141 break;
142 } 158 }
159 default:
160 throw NotImplementedException("Read attribute {}", attr);
143 } 161 }
144 return ctx.OpLoad(ctx.F32[1], InputAttrPointer(ctx, attr));
145} 162}
146 163
147void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value) { 164void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value) {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp
new file mode 100644
index 000000000..70ae7b51e
--- /dev/null
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp
@@ -0,0 +1,35 @@
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/backend/spirv/emit_spirv.h"
6
7namespace Shader::Backend::SPIRV {
8
9void EmitPrologue(EmitContext& ctx) {
10 if (ctx.stage == Stage::VertexB) {
11 const Id zero{ctx.Constant(ctx.F32[1], 0.0f)};
12 const Id one{ctx.Constant(ctx.F32[1], 1.0f)};
13 const Id null_vector{ctx.ConstantComposite(ctx.F32[4], zero, zero, zero, zero)};
14 ctx.OpStore(ctx.output_position, ctx.ConstantComposite(ctx.F32[4], zero, zero, zero, one));
15 for (const Id generic_id : ctx.output_generics) {
16 if (Sirit::ValidId(generic_id)) {
17 ctx.OpStore(generic_id, null_vector);
18 }
19 }
20 }
21}
22
23void EmitEpilogue(EmitContext& ctx) {
24 if (ctx.profile.convert_depth_mode) {
25 const Id type{ctx.F32[1]};
26 const Id position{ctx.OpLoad(ctx.F32[4], ctx.output_position)};
27 const Id z{ctx.OpCompositeExtract(type, position, 2u)};
28 const Id w{ctx.OpCompositeExtract(type, position, 3u)};
29 const Id screen_depth{ctx.OpFMul(type, ctx.OpFAdd(type, z, w), ctx.Constant(type, 0.5f))};
30 const Id vector{ctx.OpCompositeInsert(ctx.F32[4], screen_depth, position, 2u)};
31 ctx.OpStore(ctx.output_position, vector);
32 }
33}
34
35} // namespace Shader::Backend::SPIRV
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index ff2970125..ce610799a 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -92,6 +92,14 @@ void IREmitter::DemoteToHelperInvocation(Block* continue_label) {
92 Inst(Opcode::DemoteToHelperInvocation, continue_label); 92 Inst(Opcode::DemoteToHelperInvocation, continue_label);
93} 93}
94 94
95void IREmitter::Prologue() {
96 Inst(Opcode::Prologue);
97}
98
99void IREmitter::Epilogue() {
100 Inst(Opcode::Epilogue);
101}
102
95U32 IREmitter::GetReg(IR::Reg reg) { 103U32 IREmitter::GetReg(IR::Reg reg) {
96 return Inst<U32>(Opcode::GetRegister, reg); 104 return Inst<U32>(Opcode::GetRegister, reg);
97} 105}
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index 1708be3ef..39109b0de 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -39,6 +39,9 @@ public:
39 void Return(); 39 void Return();
40 void DemoteToHelperInvocation(Block* continue_label); 40 void DemoteToHelperInvocation(Block* continue_label);
41 41
42 void Prologue();
43 void Epilogue();
44
42 [[nodiscard]] U32 GetReg(IR::Reg reg); 45 [[nodiscard]] U32 GetReg(IR::Reg reg);
43 void SetReg(IR::Reg reg, const U32& value); 46 void SetReg(IR::Reg reg, const U32& value);
44 47
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index 21b7d8a9f..ba3968056 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -56,6 +56,8 @@ bool Inst::MayHaveSideEffects() const noexcept {
56 case Opcode::SelectionMerge: 56 case Opcode::SelectionMerge:
57 case Opcode::Return: 57 case Opcode::Return:
58 case Opcode::DemoteToHelperInvocation: 58 case Opcode::DemoteToHelperInvocation:
59 case Opcode::Prologue:
60 case Opcode::Epilogue:
59 case Opcode::SetAttribute: 61 case Opcode::SetAttribute:
60 case Opcode::SetAttributeIndexed: 62 case Opcode::SetAttributeIndexed:
61 case Opcode::SetFragColor: 63 case Opcode::SetFragColor:
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index fe888b8b2..8945c7b04 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.inc
+++ b/src/shader_recompiler/frontend/ir/opcodes.inc
@@ -15,6 +15,10 @@ OPCODE(SelectionMerge, Void, Labe
15OPCODE(Return, Void, ) 15OPCODE(Return, Void, )
16OPCODE(DemoteToHelperInvocation, Void, Label, ) 16OPCODE(DemoteToHelperInvocation, Void, Label, )
17 17
18// Special operations
19OPCODE(Prologue, Void, )
20OPCODE(Epilogue, Void, )
21
18// Context getters/setters 22// Context getters/setters
19OPCODE(GetRegister, U32, Reg, ) 23OPCODE(GetRegister, U32, Reg, )
20OPCODE(SetRegister, Void, Reg, U32, ) 24OPCODE(SetRegister, Void, Reg, U32, )
diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
index cec03e73e..fdac1c95a 100644
--- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
+++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
@@ -634,6 +634,9 @@ public:
634 : stmt_pool{stmt_pool_}, inst_pool{inst_pool_}, block_pool{block_pool_}, env{env_}, 634 : stmt_pool{stmt_pool_}, inst_pool{inst_pool_}, block_pool{block_pool_}, env{env_},
635 block_list{block_list_} { 635 block_list{block_list_} {
636 Visit(root_stmt, nullptr, nullptr); 636 Visit(root_stmt, nullptr, nullptr);
637
638 IR::IREmitter ir{*block_list.front()};
639 ir.Prologue();
637 } 640 }
638 641
639private: 642private:
@@ -734,7 +737,9 @@ private:
734 current_block = block_pool.Create(inst_pool); 737 current_block = block_pool.Create(inst_pool);
735 block_list.push_back(current_block); 738 block_list.push_back(current_block);
736 } 739 }
737 IR::IREmitter{*current_block}.Return(); 740 IR::IREmitter ir{*current_block};
741 ir.Epilogue();
742 ir.Return();
738 current_block = nullptr; 743 current_block = nullptr;
739 break; 744 break;
740 } 745 }
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h
index b57cbc310..41550bfc6 100644
--- a/src/shader_recompiler/profile.h
+++ b/src/shader_recompiler/profile.h
@@ -4,8 +4,18 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8
9#include "common/common_types.h"
10
7namespace Shader { 11namespace Shader {
8 12
13enum class AttributeType : u8 {
14 Float,
15 SignedInt,
16 UnsignedInt,
17};
18
9struct Profile { 19struct Profile {
10 bool unified_descriptor_binding{}; 20 bool unified_descriptor_binding{};
11 bool support_vertex_instance_id{}; 21 bool support_vertex_instance_id{};
@@ -24,6 +34,9 @@ struct Profile {
24 34
25 // FClamp is broken and OpFMax + OpFMin should be used instead 35 // FClamp is broken and OpFMax + OpFMin should be used instead
26 bool has_broken_spirv_clamp{}; 36 bool has_broken_spirv_clamp{};
37
38 std::array<AttributeType, 32> generic_input_types{};
39 bool convert_depth_mode{};
27}; 40};
28 41
29} // namespace Shader 42} // namespace Shader