diff options
Diffstat (limited to 'src/shader_recompiler/backend/spirv')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv.cpp | 63 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv.h | 4 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp | 6 |
3 files changed, 64 insertions, 9 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 4ce07c281..2519e446a 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
| @@ -14,8 +14,6 @@ | |||
| 14 | #include "shader_recompiler/frontend/ir/microinstruction.h" | 14 | #include "shader_recompiler/frontend/ir/microinstruction.h" |
| 15 | #include "shader_recompiler/frontend/ir/program.h" | 15 | #include "shader_recompiler/frontend/ir/program.h" |
| 16 | 16 | ||
| 17 | #pragma optimize("", off) | ||
| 18 | |||
| 19 | namespace Shader::Backend::SPIRV { | 17 | namespace Shader::Backend::SPIRV { |
| 20 | namespace { | 18 | namespace { |
| 21 | template <class Func> | 19 | template <class Func> |
| @@ -113,9 +111,61 @@ Id TypeId(const EmitContext& ctx, IR::Type type) { | |||
| 113 | throw NotImplementedException("Phi node type {}", type); | 111 | throw NotImplementedException("Phi node type {}", type); |
| 114 | } | 112 | } |
| 115 | } | 113 | } |
| 114 | |||
| 115 | void SetupDenormControl(const Profile& profile, const IR::Program& program, EmitContext& ctx, | ||
| 116 | Id main_func) { | ||
| 117 | if (!profile.support_float_controls) { | ||
| 118 | return; | ||
| 119 | } | ||
| 120 | const Info& info{program.info}; | ||
| 121 | if (!info.uses_fp32_denorms_flush && !info.uses_fp32_denorms_preserve && | ||
| 122 | !info.uses_fp16_denorms_flush && !info.uses_fp16_denorms_preserve) { | ||
| 123 | return; | ||
| 124 | } | ||
| 125 | ctx.AddExtension("SPV_KHR_float_controls"); | ||
| 126 | |||
| 127 | if (info.uses_fp32_denorms_flush && info.uses_fp32_denorms_preserve) { | ||
| 128 | // LOG_ERROR(HW_GPU, "Fp32 denorm flush and preserve on the same shader"); | ||
| 129 | } else if (info.uses_fp32_denorms_flush) { | ||
| 130 | if (profile.support_fp32_denorm_flush) { | ||
| 131 | ctx.AddCapability(spv::Capability::DenormFlushToZero); | ||
| 132 | ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormFlushToZero, 32U); | ||
| 133 | } else { | ||
| 134 | // Drivers will most likely flush denorms by default, no need to warn | ||
| 135 | } | ||
| 136 | } else if (info.uses_fp32_denorms_preserve) { | ||
| 137 | if (profile.support_fp32_denorm_preserve) { | ||
| 138 | ctx.AddCapability(spv::Capability::DenormPreserve); | ||
| 139 | ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 32U); | ||
| 140 | } else { | ||
| 141 | // LOG_WARNING(HW_GPU, "Fp32 denorm preserve used in shader without host support"); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | if (!profile.support_separate_denorm_behavior) { | ||
| 145 | // No separate denorm behavior | ||
| 146 | return; | ||
| 147 | } | ||
| 148 | if (info.uses_fp16_denorms_flush && info.uses_fp16_denorms_preserve) { | ||
| 149 | // LOG_ERROR(HW_GPU, "Fp16 denorm flush and preserve on the same shader"); | ||
| 150 | } else if (info.uses_fp16_denorms_flush) { | ||
| 151 | if (profile.support_fp16_denorm_flush) { | ||
| 152 | ctx.AddCapability(spv::Capability::DenormFlushToZero); | ||
| 153 | ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 16U); | ||
| 154 | } else { | ||
| 155 | // Same as fp32, no need to warn as most drivers will flush by default | ||
| 156 | } | ||
| 157 | } else if (info.uses_fp32_denorms_preserve) { | ||
| 158 | if (profile.support_fp16_denorm_preserve) { | ||
| 159 | ctx.AddCapability(spv::Capability::DenormPreserve); | ||
| 160 | ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 16U); | ||
| 161 | } else { | ||
| 162 | // LOG_WARNING(HW_GPU, "Fp16 denorm preserve used in shader without host support"); | ||
| 163 | } | ||
| 164 | } | ||
| 165 | } | ||
| 116 | } // Anonymous namespace | 166 | } // Anonymous namespace |
| 117 | 167 | ||
| 118 | std::vector<u32> EmitSPIRV(Environment& env, IR::Program& program) { | 168 | std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program) { |
| 119 | EmitContext ctx{program}; | 169 | EmitContext ctx{program}; |
| 120 | const Id void_function{ctx.TypeFunction(ctx.void_id)}; | 170 | const Id void_function{ctx.TypeFunction(ctx.void_id)}; |
| 121 | // FIXME: Forward declare functions (needs sirit support) | 171 | // FIXME: Forward declare functions (needs sirit support) |
| @@ -131,10 +181,11 @@ std::vector<u32> EmitSPIRV(Environment& env, IR::Program& program) { | |||
| 131 | ctx.OpFunctionEnd(); | 181 | ctx.OpFunctionEnd(); |
| 132 | } | 182 | } |
| 133 | boost::container::small_vector<Id, 32> interfaces; | 183 | boost::container::small_vector<Id, 32> interfaces; |
| 134 | if (program.info.uses_workgroup_id) { | 184 | const Info& info{program.info}; |
| 185 | if (info.uses_workgroup_id) { | ||
| 135 | interfaces.push_back(ctx.workgroup_id); | 186 | interfaces.push_back(ctx.workgroup_id); |
| 136 | } | 187 | } |
| 137 | if (program.info.uses_local_invocation_id) { | 188 | if (info.uses_local_invocation_id) { |
| 138 | interfaces.push_back(ctx.local_invocation_id); | 189 | interfaces.push_back(ctx.local_invocation_id); |
| 139 | } | 190 | } |
| 140 | const std::span interfaces_span(interfaces.data(), interfaces.size()); | 191 | const std::span interfaces_span(interfaces.data(), interfaces.size()); |
| @@ -144,6 +195,8 @@ std::vector<u32> EmitSPIRV(Environment& env, IR::Program& program) { | |||
| 144 | ctx.AddExecutionMode(func, spv::ExecutionMode::LocalSize, workgroup_size[0], workgroup_size[1], | 195 | ctx.AddExecutionMode(func, spv::ExecutionMode::LocalSize, workgroup_size[0], workgroup_size[1], |
| 145 | workgroup_size[2]); | 196 | workgroup_size[2]); |
| 146 | 197 | ||
| 198 | SetupDenormControl(profile, program, ctx, func); | ||
| 199 | |||
| 147 | return ctx.Assemble(); | 200 | return ctx.Assemble(); |
| 148 | } | 201 | } |
| 149 | 202 | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index 2b59c0b72..de624a151 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h | |||
| @@ -11,10 +11,12 @@ | |||
| 11 | #include "shader_recompiler/environment.h" | 11 | #include "shader_recompiler/environment.h" |
| 12 | #include "shader_recompiler/frontend/ir/microinstruction.h" | 12 | #include "shader_recompiler/frontend/ir/microinstruction.h" |
| 13 | #include "shader_recompiler/frontend/ir/program.h" | 13 | #include "shader_recompiler/frontend/ir/program.h" |
| 14 | #include "shader_recompiler/profile.h" | ||
| 14 | 15 | ||
| 15 | namespace Shader::Backend::SPIRV { | 16 | namespace Shader::Backend::SPIRV { |
| 16 | 17 | ||
| 17 | [[nodiscard]] std::vector<u32> EmitSPIRV(Environment& env, IR::Program& program); | 18 | [[nodiscard]] std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, |
| 19 | IR::Program& program); | ||
| 18 | 20 | ||
| 19 | // Microinstruction emitters | 21 | // Microinstruction emitters |
| 20 | Id EmitPhi(EmitContext& ctx, IR::Inst* inst); | 22 | Id EmitPhi(EmitContext& ctx, IR::Inst* inst); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp index 9ef180531..c9687de37 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp | |||
| @@ -13,7 +13,10 @@ Id Decorate(EmitContext& ctx, IR::Inst* inst, Id op) { | |||
| 13 | ctx.Decorate(op, spv::Decoration::NoContraction); | 13 | ctx.Decorate(op, spv::Decoration::NoContraction); |
| 14 | } | 14 | } |
| 15 | switch (flags.rounding) { | 15 | switch (flags.rounding) { |
| 16 | case IR::FpRounding::DontCare: | ||
| 17 | break; | ||
| 16 | case IR::FpRounding::RN: | 18 | case IR::FpRounding::RN: |
| 19 | ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTE); | ||
| 17 | break; | 20 | break; |
| 18 | case IR::FpRounding::RM: | 21 | case IR::FpRounding::RM: |
| 19 | ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTN); | 22 | ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTN); |
| @@ -25,9 +28,6 @@ Id Decorate(EmitContext& ctx, IR::Inst* inst, Id op) { | |||
| 25 | ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTZ); | 28 | ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTZ); |
| 26 | break; | 29 | break; |
| 27 | } | 30 | } |
| 28 | if (flags.fmz_mode != IR::FmzMode::FTZ) { | ||
| 29 | throw NotImplementedException("Denorm management not implemented"); | ||
| 30 | } | ||
| 31 | return op; | 31 | return op; |
| 32 | } | 32 | } |
| 33 | 33 | ||