glsl: Implement precise fp variable allocation

This commit is contained in:
ameerj 2021-05-30 22:44:28 -04:00
parent 14bfb4719a
commit e10366974e
4 changed files with 67 additions and 8 deletions

View file

@ -118,6 +118,16 @@ public:
Add<GlslVarType::F32x4>(format_str, inst, args...); Add<GlslVarType::F32x4>(format_str, inst, args...);
} }
template <typename... Args>
void AddPrecF32(const char* format_str, IR::Inst& inst, Args&&... args) {
Add<GlslVarType::PrecF32>(format_str, inst, args...);
}
template <typename... Args>
void AddPrecF64(const char* format_str, IR::Inst& inst, Args&&... args) {
Add<GlslVarType::PrecF64>(format_str, inst, args...);
}
template <typename... Args> template <typename... Args>
void Add(const char* format_str, Args&&... args) { void Add(const char* format_str, Args&&... args) {
code += fmt::format(format_str, std::forward<Args>(args)...); code += fmt::format(format_str, std::forward<Args>(args)...);

View file

@ -6,6 +6,7 @@
#include "shader_recompiler/backend/glsl/emit_context.h" #include "shader_recompiler/backend/glsl/emit_context.h"
#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" #include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
#include "shader_recompiler/frontend/ir/modifiers.h"
#include "shader_recompiler/frontend/ir/value.h" #include "shader_recompiler/frontend/ir/value.h"
namespace Shader::Backend::GLSL { namespace Shader::Backend::GLSL {
@ -20,6 +21,10 @@ void Compare(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string
} }
ctx.code += ";"; ctx.code += ";";
} }
bool Precise(IR::Inst& inst) {
return {inst.Flags<IR::FpControl>().no_contraction};
}
} // namespace } // namespace
void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@ -41,11 +46,19 @@ void EmitFPAdd16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
} }
void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
if (Precise(inst)) {
ctx.AddPrecF32("{}=float({})+float({});", inst, a, b);
} else {
ctx.AddF32("{}=float({})+float({});", inst, a, b); ctx.AddF32("{}=float({})+float({});", inst, a, b);
}
} }
void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
if (Precise(inst)) {
ctx.AddPrecF64("{}=double({})+double({});", inst, a, b);
} else {
ctx.AddF64("{}=double({})+double({});", inst, a, b); ctx.AddF64("{}=double({})+double({});", inst, a, b);
}
} }
void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@ -56,12 +69,20 @@ void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b, void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b,
std::string_view c) { std::string_view c) {
if (Precise(inst)) {
ctx.AddPrecF32("{}=fma({},{},{});", inst, a, b, c);
} else {
ctx.AddF32("{}=fma({},{},{});", inst, a, b, c); ctx.AddF32("{}=fma({},{},{});", inst, a, b, c);
}
} }
void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b, void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b,
std::string_view c) { std::string_view c) {
if (Precise(inst)) {
ctx.AddPrecF64("{}=fma({},{},{});", inst, a, b, c);
} else {
ctx.AddF64("{}=fma({},{},{});", inst, a, b, c); ctx.AddF64("{}=fma({},{},{});", inst, a, b, c);
}
} }
void EmitFPMax32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { void EmitFPMax32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
@ -86,11 +107,19 @@ void EmitFPMul16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
} }
void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
if (Precise(inst)) {
ctx.AddPrecF32("{}={}*{};", inst, a, b);
} else {
ctx.AddF32("{}={}*{};", inst, a, b); ctx.AddF32("{}={}*{};", inst, a, b);
}
} }
void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) { void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
if (Precise(inst)) {
ctx.AddPrecF64("{}={}*{};", inst, a, b);
} else {
ctx.AddF64("{}={}*{};", inst, a, b); ctx.AddF64("{}={}*{};", inst, a, b);
}
} }
void EmitFPNeg16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst, void EmitFPNeg16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,

View file

@ -43,6 +43,10 @@ std::string TypePrefix(GlslVarType type) {
return "u4_"; return "u4_";
case GlslVarType::F32x4: case GlslVarType::F32x4:
return "f4_"; return "f4_";
case GlslVarType::PrecF32:
return "pf_";
case GlslVarType::PrecF64:
return "pd_";
case GlslVarType::Void: case GlslVarType::Void:
return ""; return "";
default: default:
@ -225,6 +229,10 @@ std::string VarAlloc::GetGlslType(GlslVarType type) const {
return "uvec4 "; return "uvec4 ";
case GlslVarType::F32x4: case GlslVarType::F32x4:
return "vec4 "; return "vec4 ";
case GlslVarType::PrecF32:
return "precise float ";
case GlslVarType::PrecF64:
return "precise double ";
case GlslVarType::Void: case GlslVarType::Void:
return ""; return "";
default: default:
@ -262,6 +270,10 @@ VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) {
return var_u32x4; return var_u32x4;
case GlslVarType::F32x4: case GlslVarType::F32x4:
return var_f32x4; return var_f32x4;
case GlslVarType::PrecF32:
return var_precf32;
case GlslVarType::PrecF64:
return var_precf64;
default: default:
throw NotImplementedException("Type {}", type); throw NotImplementedException("Type {}", type);
} }
@ -297,6 +309,10 @@ const VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) const {
return var_u32x4; return var_u32x4;
case GlslVarType::F32x4: case GlslVarType::F32x4:
return var_f32x4; return var_f32x4;
case GlslVarType::PrecF32:
return var_precf32;
case GlslVarType::PrecF64:
return var_precf64;
default: default:
throw NotImplementedException("Type {}", type); throw NotImplementedException("Type {}", type);
} }

View file

@ -33,6 +33,8 @@ enum class GlslVarType : u32 {
F32x3, F32x3,
U32x4, U32x4,
F32x4, F32x4,
PrecF32,
PrecF64,
Void, Void,
}; };
@ -40,8 +42,8 @@ struct Id {
union { union {
u32 raw; u32 raw;
BitField<0, 1, u32> is_valid; BitField<0, 1, u32> is_valid;
BitField<1, 4, GlslVarType> type; BitField<1, 5, GlslVarType> type;
BitField<5, 27, u32> index; BitField<6, 26, u32> index;
}; };
bool operator==(Id rhs) const noexcept { bool operator==(Id rhs) const noexcept {
@ -101,6 +103,8 @@ private:
UseTracker var_u64{}; UseTracker var_u64{};
UseTracker var_s64{}; UseTracker var_s64{};
UseTracker var_f64{}; UseTracker var_f64{};
UseTracker var_precf32{};
UseTracker var_precf64{};
}; };
} // namespace Shader::Backend::GLSL } // namespace Shader::Backend::GLSL