| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- // Copyright 2021 yuzu Emulator Project
- // Licensed under GPLv2 or any later version
- // Refer to the license.txt file included.
- #include <string>
- #include <string_view>
- #include <fmt/format.h>
- #include "shader_recompiler/backend/glsl/var_alloc.h"
- #include "shader_recompiler/exception.h"
- #include "shader_recompiler/frontend/ir/value.h"
- namespace Shader::Backend::GLSL {
- namespace {
- std::string TypePrefix(GlslVarType type) {
- switch (type) {
- case GlslVarType::U1:
- return "b_";
- case GlslVarType::F16x2:
- return "f16x2_";
- case GlslVarType::U32:
- return "u_";
- case GlslVarType::F32:
- return "f_";
- case GlslVarType::U64:
- return "u64_";
- case GlslVarType::F64:
- return "d_";
- case GlslVarType::U32x2:
- return "u2_";
- case GlslVarType::F32x2:
- return "f2_";
- case GlslVarType::U32x3:
- return "u3_";
- case GlslVarType::F32x3:
- return "f3_";
- case GlslVarType::U32x4:
- return "u4_";
- case GlslVarType::F32x4:
- return "f4_";
- case GlslVarType::PrecF32:
- return "pf_";
- case GlslVarType::PrecF64:
- return "pd_";
- case GlslVarType::Void:
- return "";
- default:
- throw NotImplementedException("Type {}", type);
- }
- }
- std::string FormatFloat(std::string_view value, IR::Type type) {
- // TODO: Confirm FP64 nan/inf
- if (type == IR::Type::F32) {
- if (value == "nan") {
- return "utof(0x7fc00000)";
- }
- if (value == "inf") {
- return "utof(0x7f800000)";
- }
- if (value == "-inf") {
- return "utof(0xff800000)";
- }
- }
- if (value.find_first_of('e') != std::string_view::npos) {
- // scientific notation
- const auto cast{type == IR::Type::F32 ? "float" : "double"};
- return fmt::format("{}({})", cast, value);
- }
- const bool needs_dot{value.find_first_of('.') == std::string_view::npos};
- const bool needs_suffix{!value.ends_with('f')};
- const auto suffix{type == IR::Type::F32 ? "f" : "lf"};
- return fmt::format("{}{}{}", value, needs_dot ? "." : "", needs_suffix ? suffix : "");
- }
- std::string MakeImm(const IR::Value& value) {
- switch (value.Type()) {
- case IR::Type::U1:
- return fmt::format("{}", value.U1() ? "true" : "false");
- case IR::Type::U32:
- return fmt::format("{}u", value.U32());
- case IR::Type::F32:
- return FormatFloat(fmt::format("{}", value.F32()), IR::Type::F32);
- case IR::Type::U64:
- return fmt::format("{}ul", value.U64());
- case IR::Type::F64:
- return FormatFloat(fmt::format("{}", value.F64()), IR::Type::F64);
- case IR::Type::Void:
- return "";
- default:
- throw NotImplementedException("Immediate type {}", value.Type());
- }
- }
- } // Anonymous namespace
- std::string VarAlloc::Representation(u32 index, GlslVarType type) const {
- const auto prefix{TypePrefix(type)};
- return fmt::format("{}{}", prefix, index);
- }
- std::string VarAlloc::Representation(Id id) const {
- return Representation(id.index, id.type);
- }
- std::string VarAlloc::Define(IR::Inst& inst, GlslVarType type) {
- if (inst.HasUses()) {
- inst.SetDefinition<Id>(Alloc(type));
- return Representation(inst.Definition<Id>());
- } else {
- Id id{};
- id.type.Assign(type);
- GetUseTracker(type).uses_temp = true;
- inst.SetDefinition<Id>(id);
- return 't' + Representation(inst.Definition<Id>());
- }
- }
- std::string VarAlloc::Define(IR::Inst& inst, IR::Type type) {
- return Define(inst, RegType(type));
- }
- std::string VarAlloc::PhiDefine(IR::Inst& inst, IR::Type type) {
- return AddDefine(inst, RegType(type));
- }
- std::string VarAlloc::AddDefine(IR::Inst& inst, GlslVarType type) {
- if (inst.HasUses()) {
- inst.SetDefinition<Id>(Alloc(type));
- return Representation(inst.Definition<Id>());
- } else {
- return "";
- }
- return Representation(inst.Definition<Id>());
- }
- std::string VarAlloc::Consume(const IR::Value& value) {
- return value.IsImmediate() ? MakeImm(value) : ConsumeInst(*value.InstRecursive());
- }
- std::string VarAlloc::ConsumeInst(IR::Inst& inst) {
- inst.DestructiveRemoveUsage();
- if (!inst.HasUses()) {
- Free(inst.Definition<Id>());
- }
- return Representation(inst.Definition<Id>());
- }
- std::string VarAlloc::GetGlslType(IR::Type type) const {
- return GetGlslType(RegType(type));
- }
- Id VarAlloc::Alloc(GlslVarType type) {
- auto& use_tracker{GetUseTracker(type)};
- const auto num_vars{use_tracker.var_use.size()};
- for (size_t var = 0; var < num_vars; ++var) {
- if (use_tracker.var_use[var]) {
- continue;
- }
- use_tracker.num_used = std::max(use_tracker.num_used, var + 1);
- use_tracker.var_use[var] = true;
- Id ret{};
- ret.is_valid.Assign(1);
- ret.type.Assign(type);
- ret.index.Assign(static_cast<u32>(var));
- return ret;
- }
- // Allocate a new variable
- use_tracker.var_use.push_back(true);
- Id ret{};
- ret.is_valid.Assign(1);
- ret.type.Assign(type);
- ret.index.Assign(static_cast<u32>(use_tracker.num_used));
- ++use_tracker.num_used;
- return ret;
- }
- void VarAlloc::Free(Id id) {
- if (id.is_valid == 0) {
- throw LogicError("Freeing invalid variable");
- }
- auto& use_tracker{GetUseTracker(id.type)};
- use_tracker.var_use[id.index] = false;
- }
- GlslVarType VarAlloc::RegType(IR::Type type) const {
- switch (type) {
- case IR::Type::U1:
- return GlslVarType::U1;
- case IR::Type::U32:
- return GlslVarType::U32;
- case IR::Type::F32:
- return GlslVarType::F32;
- case IR::Type::U64:
- return GlslVarType::U64;
- case IR::Type::F64:
- return GlslVarType::F64;
- default:
- throw NotImplementedException("IR type {}", type);
- }
- }
- std::string VarAlloc::GetGlslType(GlslVarType type) const {
- switch (type) {
- case GlslVarType::U1:
- return "bool";
- case GlslVarType::F16x2:
- return "f16vec2";
- case GlslVarType::U32:
- return "uint";
- case GlslVarType::F32:
- case GlslVarType::PrecF32:
- return "float";
- case GlslVarType::U64:
- return "uint64_t";
- case GlslVarType::F64:
- case GlslVarType::PrecF64:
- return "double";
- case GlslVarType::U32x2:
- return "uvec2";
- case GlslVarType::F32x2:
- return "vec2";
- case GlslVarType::U32x3:
- return "uvec3";
- case GlslVarType::F32x3:
- return "vec3";
- case GlslVarType::U32x4:
- return "uvec4";
- case GlslVarType::F32x4:
- return "vec4";
- case GlslVarType::Void:
- return "";
- default:
- throw NotImplementedException("Type {}", type);
- }
- }
- VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) {
- switch (type) {
- case GlslVarType::U1:
- return var_bool;
- case GlslVarType::F16x2:
- return var_f16x2;
- case GlslVarType::U32:
- return var_u32;
- case GlslVarType::F32:
- return var_f32;
- case GlslVarType::U64:
- return var_u64;
- case GlslVarType::F64:
- return var_f64;
- case GlslVarType::U32x2:
- return var_u32x2;
- case GlslVarType::F32x2:
- return var_f32x2;
- case GlslVarType::U32x3:
- return var_u32x3;
- case GlslVarType::F32x3:
- return var_f32x3;
- case GlslVarType::U32x4:
- return var_u32x4;
- case GlslVarType::F32x4:
- return var_f32x4;
- case GlslVarType::PrecF32:
- return var_precf32;
- case GlslVarType::PrecF64:
- return var_precf64;
- default:
- throw NotImplementedException("Type {}", type);
- }
- }
- const VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) const {
- switch (type) {
- case GlslVarType::U1:
- return var_bool;
- case GlslVarType::F16x2:
- return var_f16x2;
- case GlslVarType::U32:
- return var_u32;
- case GlslVarType::F32:
- return var_f32;
- case GlslVarType::U64:
- return var_u64;
- case GlslVarType::F64:
- return var_f64;
- case GlslVarType::U32x2:
- return var_u32x2;
- case GlslVarType::F32x2:
- return var_f32x2;
- case GlslVarType::U32x3:
- return var_u32x3;
- case GlslVarType::F32x3:
- return var_f32x3;
- case GlslVarType::U32x4:
- return var_u32x4;
- case GlslVarType::F32x4:
- return var_f32x4;
- case GlslVarType::PrecF32:
- return var_precf32;
- case GlslVarType::PrecF64:
- return var_precf64;
- default:
- throw NotImplementedException("Type {}", type);
- }
- }
- } // namespace Shader::Backend::GLSL
|