diff options
| author | 2021-05-21 02:12:32 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:33 -0400 | |
| commit | 9e7b6622c25aa858b96bf0f1c7f94223a2f449a2 (patch) | |
| tree | 48c62889aeb79d6f0f01a467ba0d1ac01dec512b /src/shader_recompiler | |
| parent | emit_glasm_context_get_and_set.cpp: Add missing semicolons (diff) | |
| download | yuzu-9e7b6622c25aa858b96bf0f1c7f94223a2f449a2.tar.gz yuzu-9e7b6622c25aa858b96bf0f1c7f94223a2f449a2.tar.xz yuzu-9e7b6622c25aa858b96bf0f1c7f94223a2f449a2.zip | |
shader: Split profile and runtime information in separate structs
Diffstat (limited to 'src/shader_recompiler')
11 files changed, 88 insertions, 71 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index e42f186c1..659ff6d17 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp | |||
| @@ -23,23 +23,25 @@ std::string_view InterpDecorator(Interpolation interp) { | |||
| 23 | } | 23 | } |
| 24 | } // Anonymous namespace | 24 | } // Anonymous namespace |
| 25 | 25 | ||
| 26 | EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_) | 26 | EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, |
| 27 | : info{program.info}, profile{profile_} { | 27 | const RuntimeInfo& runtime_info_) |
| 28 | : profile{profile_}, runtime_info{runtime_info_} { | ||
| 28 | // FIXME: Temporary partial implementation | 29 | // FIXME: Temporary partial implementation |
| 30 | const auto& info{program.info}; | ||
| 29 | u32 cbuf_index{}; | 31 | u32 cbuf_index{}; |
| 30 | for (const auto& desc : program.info.constant_buffer_descriptors) { | 32 | for (const auto& desc : info.constant_buffer_descriptors) { |
| 31 | if (desc.count != 1) { | 33 | if (desc.count != 1) { |
| 32 | throw NotImplementedException("Constant buffer descriptor array"); | 34 | throw NotImplementedException("Constant buffer descriptor array"); |
| 33 | } | 35 | } |
| 34 | Add("CBUFFER c{}[]={{program.buffer[{}]}};", desc.index, cbuf_index); | 36 | Add("CBUFFER c{}[]={{program.buffer[{}]}};", desc.index, cbuf_index); |
| 35 | ++cbuf_index; | 37 | ++cbuf_index; |
| 36 | } | 38 | } |
| 37 | for (const auto& desc : program.info.storage_buffers_descriptors) { | 39 | for (const auto& desc : info.storage_buffers_descriptors) { |
| 38 | if (desc.count != 1) { | 40 | if (desc.count != 1) { |
| 39 | throw NotImplementedException("Storage buffer descriptor array"); | 41 | throw NotImplementedException("Storage buffer descriptor array"); |
| 40 | } | 42 | } |
| 41 | } | 43 | } |
| 42 | if (const size_t num = program.info.storage_buffers_descriptors.size(); num > 0) { | 44 | if (const size_t num = info.storage_buffers_descriptors.size(); num > 0) { |
| 43 | Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); | 45 | Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); |
| 44 | } | 46 | } |
| 45 | stage = program.stage; | 47 | stage = program.stage; |
| @@ -67,8 +69,8 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile | |||
| 67 | break; | 69 | break; |
| 68 | } | 70 | } |
| 69 | const std::string_view attr_stage{stage == Stage::Fragment ? "fragment" : "vertex"}; | 71 | const std::string_view attr_stage{stage == Stage::Fragment ? "fragment" : "vertex"}; |
| 70 | for (size_t index = 0; index < program.info.input_generics.size(); ++index) { | 72 | for (size_t index = 0; index < info.input_generics.size(); ++index) { |
| 71 | const auto& generic{program.info.input_generics[index]}; | 73 | const auto& generic{info.input_generics[index]}; |
| 72 | if (generic.used) { | 74 | if (generic.used) { |
| 73 | Add("{}ATTRIB in_attr{}[]={{{}.attrib[{}..{}]}};", | 75 | Add("{}ATTRIB in_attr{}[]={{{}.attrib[{}..{}]}};", |
| 74 | InterpDecorator(generic.interpolation), index, attr_stage, index, index); | 76 | InterpDecorator(generic.interpolation), index, attr_stage, index, index); |
| @@ -101,8 +103,8 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile | |||
| 101 | index, index); | 103 | index, index); |
| 102 | } | 104 | } |
| 103 | } | 105 | } |
| 104 | for (size_t index = 0; index < program.info.stores_frag_color.size(); ++index) { | 106 | for (size_t index = 0; index < info.stores_frag_color.size(); ++index) { |
| 105 | if (!program.info.stores_frag_color[index]) { | 107 | if (!info.stores_frag_color[index]) { |
| 106 | continue; | 108 | continue; |
| 107 | } | 109 | } |
| 108 | if (index == 0) { | 110 | if (index == 0) { |
| @@ -111,28 +113,28 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile | |||
| 111 | Add("OUTPUT frag_color{}=result.color[{}];", index, index); | 113 | Add("OUTPUT frag_color{}=result.color[{}];", index, index); |
| 112 | } | 114 | } |
| 113 | } | 115 | } |
| 114 | for (size_t index = 0; index < program.info.stores_generics.size(); ++index) { | 116 | for (size_t index = 0; index < info.stores_generics.size(); ++index) { |
| 115 | if (program.info.stores_generics[index]) { | 117 | if (info.stores_generics[index]) { |
| 116 | Add("OUTPUT out_attr{}[]={{result.attrib[{}..{}]}};", index, index, index); | 118 | Add("OUTPUT out_attr{}[]={{result.attrib[{}..{}]}};", index, index, index); |
| 117 | } | 119 | } |
| 118 | } | 120 | } |
| 119 | image_buffer_bindings.reserve(program.info.image_buffer_descriptors.size()); | 121 | image_buffer_bindings.reserve(info.image_buffer_descriptors.size()); |
| 120 | for (const auto& desc : program.info.image_buffer_descriptors) { | 122 | for (const auto& desc : info.image_buffer_descriptors) { |
| 121 | image_buffer_bindings.push_back(bindings.image); | 123 | image_buffer_bindings.push_back(bindings.image); |
| 122 | bindings.image += desc.count; | 124 | bindings.image += desc.count; |
| 123 | } | 125 | } |
| 124 | image_bindings.reserve(program.info.image_descriptors.size()); | 126 | image_bindings.reserve(info.image_descriptors.size()); |
| 125 | for (const auto& desc : program.info.image_descriptors) { | 127 | for (const auto& desc : info.image_descriptors) { |
| 126 | image_bindings.push_back(bindings.image); | 128 | image_bindings.push_back(bindings.image); |
| 127 | bindings.image += desc.count; | 129 | bindings.image += desc.count; |
| 128 | } | 130 | } |
| 129 | texture_buffer_bindings.reserve(program.info.texture_buffer_descriptors.size()); | 131 | texture_buffer_bindings.reserve(info.texture_buffer_descriptors.size()); |
| 130 | for (const auto& desc : program.info.texture_buffer_descriptors) { | 132 | for (const auto& desc : info.texture_buffer_descriptors) { |
| 131 | texture_buffer_bindings.push_back(bindings.texture); | 133 | texture_buffer_bindings.push_back(bindings.texture); |
| 132 | bindings.texture += desc.count; | 134 | bindings.texture += desc.count; |
| 133 | } | 135 | } |
| 134 | texture_bindings.reserve(program.info.texture_descriptors.size()); | 136 | texture_bindings.reserve(info.texture_descriptors.size()); |
| 135 | for (const auto& desc : program.info.texture_descriptors) { | 137 | for (const auto& desc : info.texture_descriptors) { |
| 136 | texture_bindings.push_back(bindings.texture); | 138 | texture_bindings.push_back(bindings.texture); |
| 137 | bindings.texture += desc.count; | 139 | bindings.texture += desc.count; |
| 138 | } | 140 | } |
diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index e76ed1d7c..1f057fdd5 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | namespace Shader { | 16 | namespace Shader { |
| 17 | struct Info; | 17 | struct Info; |
| 18 | struct Profile; | 18 | struct Profile; |
| 19 | struct RuntimeInfo; | ||
| 19 | } // namespace Shader | 20 | } // namespace Shader |
| 20 | 21 | ||
| 21 | namespace Shader::Backend { | 22 | namespace Shader::Backend { |
| @@ -31,7 +32,8 @@ namespace Shader::Backend::GLASM { | |||
| 31 | 32 | ||
| 32 | class EmitContext { | 33 | class EmitContext { |
| 33 | public: | 34 | public: |
| 34 | explicit EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_); | 35 | explicit EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, |
| 36 | const RuntimeInfo& runtime_info_); | ||
| 35 | 37 | ||
| 36 | template <typename... Args> | 38 | template <typename... Args> |
| 37 | void Add(const char* format_str, IR::Inst& inst, Args&&... args) { | 39 | void Add(const char* format_str, IR::Inst& inst, Args&&... args) { |
| @@ -56,8 +58,8 @@ public: | |||
| 56 | 58 | ||
| 57 | std::string code; | 59 | std::string code; |
| 58 | RegAlloc reg_alloc{*this}; | 60 | RegAlloc reg_alloc{*this}; |
| 59 | const Info& info; | ||
| 60 | const Profile& profile; | 61 | const Profile& profile; |
| 62 | const RuntimeInfo& runtime_info; | ||
| 61 | 63 | ||
| 62 | std::vector<u32> texture_buffer_bindings; | 64 | std::vector<u32> texture_buffer_bindings; |
| 63 | std::vector<u32> image_buffer_bindings; | 65 | std::vector<u32> image_buffer_bindings; |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index f110fd7f8..edff04a44 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp | |||
| @@ -374,8 +374,9 @@ std::string_view GetTessSpacing(TessSpacing spacing) { | |||
| 374 | } | 374 | } |
| 375 | } // Anonymous namespace | 375 | } // Anonymous namespace |
| 376 | 376 | ||
| 377 | std::string EmitGLASM(const Profile& profile, IR::Program& program, Bindings& bindings) { | 377 | std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, IR::Program& program, |
| 378 | EmitContext ctx{program, bindings, profile}; | 378 | Bindings& bindings) { |
| 379 | EmitContext ctx{program, bindings, profile, runtime_info}; | ||
| 379 | Precolor(ctx, program); | 380 | Precolor(ctx, program); |
| 380 | EmitCode(ctx, program); | 381 | EmitCode(ctx, program); |
| 381 | std::string header{StageHeader(program.stage)}; | 382 | std::string header{StageHeader(program.stage)}; |
| @@ -385,18 +386,18 @@ std::string EmitGLASM(const Profile& profile, IR::Program& program, Bindings& bi | |||
| 385 | header += fmt::format("VERTICES_OUT {};", program.invocations); | 386 | header += fmt::format("VERTICES_OUT {};", program.invocations); |
| 386 | break; | 387 | break; |
| 387 | case Stage::TessellationEval: | 388 | case Stage::TessellationEval: |
| 388 | header += | 389 | header += fmt::format("TESS_MODE {};" |
| 389 | fmt::format("TESS_MODE {};" | 390 | "TESS_SPACING {};" |
| 390 | "TESS_SPACING {};" | 391 | "TESS_VERTEX_ORDER {};", |
| 391 | "TESS_VERTEX_ORDER {};", | 392 | GetTessMode(runtime_info.tess_primitive), |
| 392 | GetTessMode(profile.tess_primitive), GetTessSpacing(profile.tess_spacing), | 393 | GetTessSpacing(runtime_info.tess_spacing), |
| 393 | profile.tess_clockwise ? "CW" : "CCW"); | 394 | runtime_info.tess_clockwise ? "CW" : "CCW"); |
| 394 | break; | 395 | break; |
| 395 | case Stage::Geometry: | 396 | case Stage::Geometry: |
| 396 | header += fmt::format("PRIMITIVE_IN {};" | 397 | header += fmt::format("PRIMITIVE_IN {};" |
| 397 | "PRIMITIVE_OUT {};" | 398 | "PRIMITIVE_OUT {};" |
| 398 | "VERTICES_OUT {};", | 399 | "VERTICES_OUT {};", |
| 399 | InputPrimitive(profile.input_topology), | 400 | InputPrimitive(runtime_info.input_topology), |
| 400 | OutputPrimitive(program.output_topology), program.output_vertices); | 401 | OutputPrimitive(program.output_topology), program.output_vertices); |
| 401 | break; | 402 | break; |
| 402 | case Stage::Compute: | 403 | case Stage::Compute: |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.h b/src/shader_recompiler/backend/glasm/emit_glasm.h index a0dfdd818..3d02d873e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm.h | |||
| @@ -12,12 +12,12 @@ | |||
| 12 | 12 | ||
| 13 | namespace Shader::Backend::GLASM { | 13 | namespace Shader::Backend::GLASM { |
| 14 | 14 | ||
| 15 | [[nodiscard]] std::string EmitGLASM(const Profile& profile, IR::Program& program, | 15 | [[nodiscard]] std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, |
| 16 | Bindings& binding); | 16 | IR::Program& program, Bindings& bindings); |
| 17 | 17 | ||
| 18 | [[nodiscard]] inline std::string EmitGLASM(const Profile& profile, IR::Program& program) { | 18 | [[nodiscard]] inline std::string EmitGLASM(const Profile& profile, IR::Program& program) { |
| 19 | Bindings binding; | 19 | Bindings binding; |
| 20 | return EmitGLASM(profile, program, binding); | 20 | return EmitGLASM(profile, {}, program, binding); |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | } // namespace Shader::Backend::GLASM | 23 | } // namespace Shader::Backend::GLASM |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index a98e08392..3e8899f53 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -136,7 +136,7 @@ Id DefineInput(EmitContext& ctx, Id type, bool per_invocation, | |||
| 136 | break; | 136 | break; |
| 137 | case Stage::Geometry: | 137 | case Stage::Geometry: |
| 138 | if (per_invocation) { | 138 | if (per_invocation) { |
| 139 | const u32 num_vertices{NumVertices(ctx.profile.input_topology)}; | 139 | const u32 num_vertices{NumVertices(ctx.runtime_info.input_topology)}; |
| 140 | type = ctx.TypeArray(type, ctx.Const(num_vertices)); | 140 | type = ctx.TypeArray(type, ctx.Const(num_vertices)); |
| 141 | } | 141 | } |
| 142 | break; | 142 | break; |
| @@ -161,8 +161,8 @@ void DefineGenericOutput(EmitContext& ctx, size_t index, std::optional<u32> invo | |||
| 161 | while (element < 4) { | 161 | while (element < 4) { |
| 162 | const u32 remainder{4 - element}; | 162 | const u32 remainder{4 - element}; |
| 163 | const TransformFeedbackVarying* xfb_varying{}; | 163 | const TransformFeedbackVarying* xfb_varying{}; |
| 164 | if (!ctx.profile.xfb_varyings.empty()) { | 164 | if (!ctx.runtime_info.xfb_varyings.empty()) { |
| 165 | xfb_varying = &ctx.profile.xfb_varyings[base_attr_index + element]; | 165 | xfb_varying = &ctx.runtime_info.xfb_varyings[base_attr_index + element]; |
| 166 | xfb_varying = xfb_varying && xfb_varying->components > 0 ? xfb_varying : nullptr; | 166 | xfb_varying = xfb_varying && xfb_varying->components > 0 ? xfb_varying : nullptr; |
| 167 | } | 167 | } |
| 168 | const u32 num_components{xfb_varying ? xfb_varying->components : remainder}; | 168 | const u32 num_components{xfb_varying ? xfb_varying->components : remainder}; |
| @@ -208,7 +208,7 @@ Id GetAttributeType(EmitContext& ctx, AttributeType type) { | |||
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) { | 210 | std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) { |
| 211 | const AttributeType type{ctx.profile.generic_input_types.at(index)}; | 211 | const AttributeType type{ctx.runtime_info.generic_input_types.at(index)}; |
| 212 | switch (type) { | 212 | switch (type) { |
| 213 | case AttributeType::Float: | 213 | case AttributeType::Float: |
| 214 | return AttrInfo{ctx.input_f32, ctx.F32[1], false}; | 214 | return AttrInfo{ctx.input_f32, ctx.F32[1], false}; |
| @@ -441,13 +441,15 @@ void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_vie | |||
| 441 | } | 441 | } |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | EmitContext::EmitContext(const Profile& profile_, IR::Program& program, Bindings& binding) | 444 | EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_info_, |
| 445 | : Sirit::Module(profile_.supported_spirv), profile{profile_}, stage{program.stage} { | 445 | IR::Program& program, Bindings& bindings) |
| 446 | : Sirit::Module(profile_.supported_spirv), profile{profile_}, | ||
| 447 | runtime_info{runtime_info_}, stage{program.stage} { | ||
| 446 | const bool is_unified{profile.unified_descriptor_binding}; | 448 | const bool is_unified{profile.unified_descriptor_binding}; |
| 447 | u32& uniform_binding{is_unified ? binding.unified : binding.uniform_buffer}; | 449 | u32& uniform_binding{is_unified ? bindings.unified : bindings.uniform_buffer}; |
| 448 | u32& storage_binding{is_unified ? binding.unified : binding.storage_buffer}; | 450 | u32& storage_binding{is_unified ? bindings.unified : bindings.storage_buffer}; |
| 449 | u32& texture_binding{is_unified ? binding.unified : binding.texture}; | 451 | u32& texture_binding{is_unified ? bindings.unified : bindings.texture}; |
| 450 | u32& image_binding{is_unified ? binding.unified : binding.image}; | 452 | u32& image_binding{is_unified ? bindings.unified : bindings.image}; |
| 451 | AddCapability(spv::Capability::Shader); | 453 | AddCapability(spv::Capability::Shader); |
| 452 | DefineCommonTypes(program.info); | 454 | DefineCommonTypes(program.info); |
| 453 | DefineCommonConstants(); | 455 | DefineCommonConstants(); |
| @@ -1211,7 +1213,7 @@ void EmitContext::DefineInputs(const Info& info) { | |||
| 1211 | if (!generic.used) { | 1213 | if (!generic.used) { |
| 1212 | continue; | 1214 | continue; |
| 1213 | } | 1215 | } |
| 1214 | const AttributeType input_type{profile.generic_input_types[index]}; | 1216 | const AttributeType input_type{runtime_info.generic_input_types[index]}; |
| 1215 | if (input_type == AttributeType::Disabled) { | 1217 | if (input_type == AttributeType::Disabled) { |
| 1216 | continue; | 1218 | continue; |
| 1217 | } | 1219 | } |
| @@ -1256,7 +1258,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { | |||
| 1256 | if (info.stores_position || stage == Stage::VertexB) { | 1258 | if (info.stores_position || stage == Stage::VertexB) { |
| 1257 | output_position = DefineOutput(*this, F32[4], invocations, spv::BuiltIn::Position); | 1259 | output_position = DefineOutput(*this, F32[4], invocations, spv::BuiltIn::Position); |
| 1258 | } | 1260 | } |
| 1259 | if (info.stores_point_size || profile.fixed_state_point_size) { | 1261 | if (info.stores_point_size || runtime_info.fixed_state_point_size) { |
| 1260 | if (stage == Stage::Fragment) { | 1262 | if (stage == Stage::Fragment) { |
| 1261 | throw NotImplementedException("Storing PointSize in fragment stage"); | 1263 | throw NotImplementedException("Storing PointSize in fragment stage"); |
| 1262 | } | 1264 | } |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index d2b79f6c1..961c9180c 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h | |||
| @@ -103,7 +103,8 @@ struct GenericElementInfo { | |||
| 103 | 103 | ||
| 104 | class EmitContext final : public Sirit::Module { | 104 | class EmitContext final : public Sirit::Module { |
| 105 | public: | 105 | public: |
| 106 | explicit EmitContext(const Profile& profile, IR::Program& program, Bindings& binding); | 106 | explicit EmitContext(const Profile& profile, const RuntimeInfo& runtime_info, |
| 107 | IR::Program& program, Bindings& binding); | ||
| 107 | ~EmitContext(); | 108 | ~EmitContext(); |
| 108 | 109 | ||
| 109 | [[nodiscard]] Id Def(const IR::Value& value); | 110 | [[nodiscard]] Id Def(const IR::Value& value); |
| @@ -150,6 +151,7 @@ public: | |||
| 150 | } | 151 | } |
| 151 | 152 | ||
| 152 | const Profile& profile; | 153 | const Profile& profile; |
| 154 | const RuntimeInfo& runtime_info; | ||
| 153 | Stage stage{}; | 155 | Stage stage{}; |
| 154 | 156 | ||
| 155 | Id void_id{}; | 157 | Id void_id{}; |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 3e20ac3b9..cba420cda 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
| @@ -226,16 +226,17 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { | |||
| 226 | case Stage::TessellationEval: | 226 | case Stage::TessellationEval: |
| 227 | execution_model = spv::ExecutionModel::TessellationEvaluation; | 227 | execution_model = spv::ExecutionModel::TessellationEvaluation; |
| 228 | ctx.AddCapability(spv::Capability::Tessellation); | 228 | ctx.AddCapability(spv::Capability::Tessellation); |
| 229 | ctx.AddExecutionMode(main, ExecutionMode(ctx.profile.tess_primitive)); | 229 | ctx.AddExecutionMode(main, ExecutionMode(ctx.runtime_info.tess_primitive)); |
| 230 | ctx.AddExecutionMode(main, ExecutionMode(ctx.profile.tess_spacing)); | 230 | ctx.AddExecutionMode(main, ExecutionMode(ctx.runtime_info.tess_spacing)); |
| 231 | ctx.AddExecutionMode(main, ctx.profile.tess_clockwise ? spv::ExecutionMode::VertexOrderCw | 231 | ctx.AddExecutionMode(main, ctx.runtime_info.tess_clockwise |
| 232 | : spv::ExecutionMode::VertexOrderCcw); | 232 | ? spv::ExecutionMode::VertexOrderCw |
| 233 | : spv::ExecutionMode::VertexOrderCcw); | ||
| 233 | break; | 234 | break; |
| 234 | case Stage::Geometry: | 235 | case Stage::Geometry: |
| 235 | execution_model = spv::ExecutionModel::Geometry; | 236 | execution_model = spv::ExecutionModel::Geometry; |
| 236 | ctx.AddCapability(spv::Capability::Geometry); | 237 | ctx.AddCapability(spv::Capability::Geometry); |
| 237 | ctx.AddCapability(spv::Capability::GeometryStreams); | 238 | ctx.AddCapability(spv::Capability::GeometryStreams); |
| 238 | switch (ctx.profile.input_topology) { | 239 | switch (ctx.runtime_info.input_topology) { |
| 239 | case InputTopology::Points: | 240 | case InputTopology::Points: |
| 240 | ctx.AddExecutionMode(main, spv::ExecutionMode::InputPoints); | 241 | ctx.AddExecutionMode(main, spv::ExecutionMode::InputPoints); |
| 241 | break; | 242 | break; |
| @@ -279,7 +280,7 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { | |||
| 279 | if (program.info.stores_frag_depth) { | 280 | if (program.info.stores_frag_depth) { |
| 280 | ctx.AddExecutionMode(main, spv::ExecutionMode::DepthReplacing); | 281 | ctx.AddExecutionMode(main, spv::ExecutionMode::DepthReplacing); |
| 281 | } | 282 | } |
| 282 | if (ctx.profile.force_early_z) { | 283 | if (ctx.runtime_info.force_early_z) { |
| 283 | ctx.AddExecutionMode(main, spv::ExecutionMode::EarlyFragmentTests); | 284 | ctx.AddExecutionMode(main, spv::ExecutionMode::EarlyFragmentTests); |
| 284 | } | 285 | } |
| 285 | break; | 286 | break; |
| @@ -402,7 +403,7 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct | |||
| 402 | if (info.uses_sample_id) { | 403 | if (info.uses_sample_id) { |
| 403 | ctx.AddCapability(spv::Capability::SampleRateShading); | 404 | ctx.AddCapability(spv::Capability::SampleRateShading); |
| 404 | } | 405 | } |
| 405 | if (!ctx.profile.xfb_varyings.empty()) { | 406 | if (!ctx.runtime_info.xfb_varyings.empty()) { |
| 406 | ctx.AddCapability(spv::Capability::TransformFeedback); | 407 | ctx.AddCapability(spv::Capability::TransformFeedback); |
| 407 | } | 408 | } |
| 408 | if (info.uses_derivatives) { | 409 | if (info.uses_derivatives) { |
| @@ -433,8 +434,9 @@ void PatchPhiNodes(IR::Program& program, EmitContext& ctx) { | |||
| 433 | } | 434 | } |
| 434 | } // Anonymous namespace | 435 | } // Anonymous namespace |
| 435 | 436 | ||
| 436 | std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program, Bindings& binding) { | 437 | std::vector<u32> EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info, |
| 437 | EmitContext ctx{profile, program, binding}; | 438 | IR::Program& program, Bindings& bindings) { |
| 439 | EmitContext ctx{profile, runtime_info, program, bindings}; | ||
| 438 | const Id main{DefineMain(ctx, program)}; | 440 | const Id main{DefineMain(ctx, program)}; |
| 439 | DefineEntryPoint(program, ctx, main); | 441 | DefineEntryPoint(program, ctx, main); |
| 440 | if (profile.support_float_controls) { | 442 | if (profile.support_float_controls) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index d8ab2d8ed..db0c935fe 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h | |||
| @@ -16,12 +16,12 @@ | |||
| 16 | 16 | ||
| 17 | namespace Shader::Backend::SPIRV { | 17 | namespace Shader::Backend::SPIRV { |
| 18 | 18 | ||
| 19 | [[nodiscard]] std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program, | 19 | [[nodiscard]] std::vector<u32> EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_info, |
| 20 | Bindings& binding); | 20 | IR::Program& program, Bindings& bindings); |
| 21 | 21 | ||
| 22 | [[nodiscard]] inline std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program) { | 22 | [[nodiscard]] inline std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program) { |
| 23 | Bindings binding; | 23 | Bindings binding; |
| 24 | return EmitSPIRV(profile, program, binding); | 24 | return EmitSPIRV(profile, {}, program, binding); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | } // namespace Shader::Backend::SPIRV | 27 | } // namespace Shader::Backend::SPIRV |
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 8e57ff070..c1b69c234 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 | |||
| @@ -17,7 +17,7 @@ struct AttrInfo { | |||
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) { | 19 | std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) { |
| 20 | const AttributeType type{ctx.profile.generic_input_types.at(index)}; | 20 | const AttributeType type{ctx.runtime_info.generic_input_types.at(index)}; |
| 21 | switch (type) { | 21 | switch (type) { |
| 22 | case AttributeType::Float: | 22 | case AttributeType::Float: |
| 23 | return AttrInfo{ctx.input_f32, ctx.F32[1], false}; | 23 | return AttrInfo{ctx.input_f32, ctx.F32[1], false}; |
| @@ -468,7 +468,7 @@ Id EmitIsHelperInvocation(EmitContext& ctx) { | |||
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | Id EmitYDirection(EmitContext& ctx) { | 470 | Id EmitYDirection(EmitContext& ctx) { |
| 471 | return ctx.Const(ctx.profile.y_negate ? -1.0f : 1.0f); | 471 | return ctx.Const(ctx.runtime_info.y_negate ? -1.0f : 1.0f); |
| 472 | } | 472 | } |
| 473 | 473 | ||
| 474 | Id EmitLoadLocal(EmitContext& ctx, Id word_offset) { | 474 | Id EmitLoadLocal(EmitContext& ctx, Id word_offset) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index ba948f3c9..072a3b1bd 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp | |||
| @@ -18,8 +18,8 @@ void ConvertDepthMode(EmitContext& ctx) { | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | void SetFixedPipelinePointSize(EmitContext& ctx) { | 20 | void SetFixedPipelinePointSize(EmitContext& ctx) { |
| 21 | if (ctx.profile.fixed_state_point_size) { | 21 | if (ctx.runtime_info.fixed_state_point_size) { |
| 22 | const float point_size{*ctx.profile.fixed_state_point_size}; | 22 | const float point_size{*ctx.runtime_info.fixed_state_point_size}; |
| 23 | ctx.OpStore(ctx.output_point_size, ctx.Const(point_size)); | 23 | ctx.OpStore(ctx.output_point_size, ctx.Const(point_size)); |
| 24 | } | 24 | } |
| 25 | } | 25 | } |
| @@ -62,7 +62,10 @@ Id ComparisonFunction(EmitContext& ctx, CompareFunction comparison, Id operand_1 | |||
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | void AlphaTest(EmitContext& ctx) { | 64 | void AlphaTest(EmitContext& ctx) { |
| 65 | const auto comparison{*ctx.profile.alpha_test_func}; | 65 | if (!ctx.runtime_info.alpha_test_func) { |
| 66 | return; | ||
| 67 | } | ||
| 68 | const auto comparison{*ctx.runtime_info.alpha_test_func}; | ||
| 66 | if (comparison == CompareFunction::Always) { | 69 | if (comparison == CompareFunction::Always) { |
| 67 | return; | 70 | return; |
| 68 | } | 71 | } |
| @@ -76,7 +79,7 @@ void AlphaTest(EmitContext& ctx) { | |||
| 76 | 79 | ||
| 77 | const Id true_label{ctx.OpLabel()}; | 80 | const Id true_label{ctx.OpLabel()}; |
| 78 | const Id discard_label{ctx.OpLabel()}; | 81 | const Id discard_label{ctx.OpLabel()}; |
| 79 | const Id alpha_reference{ctx.Const(ctx.profile.alpha_test_reference)}; | 82 | const Id alpha_reference{ctx.Const(ctx.runtime_info.alpha_test_reference)}; |
| 80 | const Id condition{ComparisonFunction(ctx, comparison, alpha, alpha_reference)}; | 83 | const Id condition{ComparisonFunction(ctx, comparison, alpha, alpha_reference)}; |
| 81 | 84 | ||
| 82 | ctx.OpSelectionMerge(true_label, spv::SelectionControlMask::MaskNone); | 85 | ctx.OpSelectionMerge(true_label, spv::SelectionControlMask::MaskNone); |
| @@ -113,7 +116,7 @@ void EmitPrologue(EmitContext& ctx) { | |||
| 113 | } | 116 | } |
| 114 | 117 | ||
| 115 | void EmitEpilogue(EmitContext& ctx) { | 118 | void EmitEpilogue(EmitContext& ctx) { |
| 116 | if (ctx.stage == Stage::VertexB && ctx.profile.convert_depth_mode) { | 119 | if (ctx.stage == Stage::VertexB && ctx.runtime_info.convert_depth_mode) { |
| 117 | ConvertDepthMode(ctx); | 120 | ConvertDepthMode(ctx); |
| 118 | } | 121 | } |
| 119 | if (ctx.stage == Stage::Fragment) { | 122 | if (ctx.stage == Stage::Fragment) { |
| @@ -122,7 +125,7 @@ void EmitEpilogue(EmitContext& ctx) { | |||
| 122 | } | 125 | } |
| 123 | 126 | ||
| 124 | void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { | 127 | void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { |
| 125 | if (ctx.profile.convert_depth_mode) { | 128 | if (ctx.runtime_info.convert_depth_mode) { |
| 126 | ConvertDepthMode(ctx); | 129 | ConvertDepthMode(ctx); |
| 127 | } | 130 | } |
| 128 | if (stream.IsImmediate()) { | 131 | if (stream.IsImmediate()) { |
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 12699511a..c46452c3d 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h | |||
| @@ -81,19 +81,22 @@ struct Profile { | |||
| 81 | bool support_viewport_mask{}; | 81 | bool support_viewport_mask{}; |
| 82 | bool support_typeless_image_loads{}; | 82 | bool support_typeless_image_loads{}; |
| 83 | bool support_demote_to_helper_invocation{}; | 83 | bool support_demote_to_helper_invocation{}; |
| 84 | bool warp_size_potentially_larger_than_guest{}; | ||
| 85 | bool support_int64_atomics{}; | 84 | bool support_int64_atomics{}; |
| 85 | |||
| 86 | bool warp_size_potentially_larger_than_guest{}; | ||
| 86 | bool lower_left_origin_mode{}; | 87 | bool lower_left_origin_mode{}; |
| 87 | 88 | ||
| 88 | // FClamp is broken and OpFMax + OpFMin should be used instead | 89 | /// OpFClamp is broken and OpFMax + OpFMin should be used instead |
| 89 | bool has_broken_spirv_clamp{}; | 90 | bool has_broken_spirv_clamp{}; |
| 90 | // Offset image operands with an unsigned type do not work | 91 | /// Offset image operands with an unsigned type do not work |
| 91 | bool has_broken_unsigned_image_offsets{}; | 92 | bool has_broken_unsigned_image_offsets{}; |
| 92 | // Signed instructions with unsigned data types are misinterpreted | 93 | /// Signed instructions with unsigned data types are misinterpreted |
| 93 | bool has_broken_signed_operations{}; | 94 | bool has_broken_signed_operations{}; |
| 94 | // Ignores SPIR-V ordered vs unordered using GLSL semantics | 95 | /// Ignores SPIR-V ordered vs unordered using GLSL semantics |
| 95 | bool ignore_nan_fp_comparisons{}; | 96 | bool ignore_nan_fp_comparisons{}; |
| 97 | }; | ||
| 96 | 98 | ||
| 99 | struct RuntimeInfo { | ||
| 97 | std::array<AttributeType, 32> generic_input_types{}; | 100 | std::array<AttributeType, 32> generic_input_types{}; |
| 98 | bool convert_depth_mode{}; | 101 | bool convert_depth_mode{}; |
| 99 | bool force_early_z{}; | 102 | bool force_early_z{}; |