summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-02-20 03:30:13 -0300
committerGravatar ameerj2021-07-22 21:51:22 -0400
commite2bc05b17d91854cbb9c0ce3647141bf7d33143e (patch)
tree96769db006b6015cd536483db98ee0697aee4992 /src/shader_recompiler/backend
parentspirv: Add lower fp16 to fp32 pass (diff)
downloadyuzu-e2bc05b17d91854cbb9c0ce3647141bf7d33143e.tar.gz
yuzu-e2bc05b17d91854cbb9c0ce3647141bf7d33143e.tar.xz
yuzu-e2bc05b17d91854cbb9c0ce3647141bf7d33143e.zip
shader: Add denorm flush support
Diffstat (limited to 'src/shader_recompiler/backend')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.cpp63
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.h4
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp6
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
19namespace Shader::Backend::SPIRV { 17namespace Shader::Backend::SPIRV {
20namespace { 18namespace {
21template <class Func> 19template <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
115void 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
118std::vector<u32> EmitSPIRV(Environment& env, IR::Program& program) { 168std::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
15namespace Shader::Backend::SPIRV { 16namespace 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
20Id EmitPhi(EmitContext& ctx, IR::Inst* inst); 22Id 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