14 changed files with 482 additions and 353 deletions
-
4src/shader_recompiler/CMakeLists.txt
-
36src/shader_recompiler/backend/glsl/emit_context.h
-
29src/shader_recompiler/backend/glsl/emit_glsl.cpp
-
11src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
-
2src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
-
14src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
-
26src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
-
10src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
-
28src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
-
10src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
-
191src/shader_recompiler/backend/glsl/reg_alloc.cpp
-
84src/shader_recompiler/backend/glsl/reg_alloc.h
-
290src/shader_recompiler/backend/glsl/var_alloc.cpp
-
100src/shader_recompiler/backend/glsl/var_alloc.h
@ -1,191 +0,0 @@ |
|||||
// 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/reg_alloc.h"
|
|
||||
#include "shader_recompiler/exception.h"
|
|
||||
#include "shader_recompiler/frontend/ir/value.h"
|
|
||||
|
|
||||
namespace Shader::Backend::GLSL { |
|
||||
namespace { |
|
||||
std::string Representation(Id id) { |
|
||||
if (id.is_condition_code != 0) { |
|
||||
throw NotImplementedException("Condition code"); |
|
||||
} |
|
||||
if (id.is_spill != 0) { |
|
||||
throw NotImplementedException("Spilling"); |
|
||||
} |
|
||||
const u32 index{static_cast<u32>(id.index)}; |
|
||||
return fmt::format("R{}", index); |
|
||||
} |
|
||||
|
|
||||
std::string FormatFloat(std::string_view value, IR::Type type) { |
|
||||
// TODO: Confirm FP64 nan/inf
|
|
||||
if (type == IR::Type::F32) { |
|
||||
if (value == "nan") { |
|
||||
return "uintBitsToFloat(0x7fc00000)"; |
|
||||
} |
|
||||
if (value == "inf") { |
|
||||
return "uintBitsToFloat(0x7f800000)"; |
|
||||
} |
|
||||
if (value == "-inf") { |
|
||||
return "uintBitsToFloat(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 RegAlloc::Define(IR::Inst& inst) { |
|
||||
const Id id{Alloc()}; |
|
||||
inst.SetDefinition<Id>(id); |
|
||||
return Representation(id); |
|
||||
} |
|
||||
|
|
||||
std::string RegAlloc::Define(IR::Inst& inst, Type type) { |
|
||||
const Id id{Alloc()}; |
|
||||
std::string type_str = ""; |
|
||||
if (!register_defined[id.index]) { |
|
||||
register_defined[id.index] = true; |
|
||||
// type_str = GetGlslType(type);
|
|
||||
reg_types.push_back(GetGlslType(type)); |
|
||||
++num_used_registers; |
|
||||
} |
|
||||
inst.SetDefinition<Id>(id); |
|
||||
return type_str + Representation(id); |
|
||||
} |
|
||||
|
|
||||
std::string RegAlloc::Define(IR::Inst& inst, IR::Type type) { |
|
||||
return Define(inst, RegType(type)); |
|
||||
} |
|
||||
|
|
||||
std::string RegAlloc::Consume(const IR::Value& value) { |
|
||||
return value.IsImmediate() ? MakeImm(value) : Consume(*value.InstRecursive()); |
|
||||
} |
|
||||
|
|
||||
std::string RegAlloc::Consume(IR::Inst& inst) { |
|
||||
inst.DestructiveRemoveUsage(); |
|
||||
// TODO: reuse variables of same type if possible
|
|
||||
// if (!inst.HasUses()) {
|
|
||||
// Free(id);
|
|
||||
// }
|
|
||||
return Representation(inst.Definition<Id>()); |
|
||||
} |
|
||||
|
|
||||
Type RegAlloc::RegType(IR::Type type) { |
|
||||
switch (type) { |
|
||||
case IR::Type::U1: |
|
||||
return Type::U1; |
|
||||
case IR::Type::U32: |
|
||||
return Type::U32; |
|
||||
case IR::Type::F32: |
|
||||
return Type::F32; |
|
||||
case IR::Type::U64: |
|
||||
return Type::U64; |
|
||||
case IR::Type::F64: |
|
||||
return Type::F64; |
|
||||
default: |
|
||||
throw NotImplementedException("IR type {}", type); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
std::string RegAlloc::GetGlslType(Type type) { |
|
||||
switch (type) { |
|
||||
case Type::U1: |
|
||||
return "bool "; |
|
||||
case Type::F16x2: |
|
||||
return "f16vec2 "; |
|
||||
case Type::U32: |
|
||||
return "uint "; |
|
||||
case Type::S32: |
|
||||
return "int "; |
|
||||
case Type::F32: |
|
||||
return "float "; |
|
||||
case Type::S64: |
|
||||
return "int64_t "; |
|
||||
case Type::U64: |
|
||||
return "uint64_t "; |
|
||||
case Type::F64: |
|
||||
return "double "; |
|
||||
case Type::U32x2: |
|
||||
return "uvec2 "; |
|
||||
case Type::F32x2: |
|
||||
return "vec2 "; |
|
||||
case Type::U32x3: |
|
||||
return "uvec3 "; |
|
||||
case Type::F32x3: |
|
||||
return "vec3 "; |
|
||||
case Type::U32x4: |
|
||||
return "uvec4 "; |
|
||||
case Type::F32x4: |
|
||||
return "vec4 "; |
|
||||
case Type::Void: |
|
||||
return ""; |
|
||||
default: |
|
||||
throw NotImplementedException("Type {}", type); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
std::string RegAlloc::GetGlslType(IR::Type type) { |
|
||||
return GetGlslType(RegType(type)); |
|
||||
} |
|
||||
|
|
||||
Id RegAlloc::Alloc() { |
|
||||
if (num_used_registers < NUM_REGS) { |
|
||||
for (size_t reg = 0; reg < NUM_REGS; ++reg) { |
|
||||
if (register_use[reg]) { |
|
||||
continue; |
|
||||
} |
|
||||
register_use[reg] = true; |
|
||||
Id ret{}; |
|
||||
ret.is_valid.Assign(1); |
|
||||
ret.is_long.Assign(0); |
|
||||
ret.is_spill.Assign(0); |
|
||||
ret.is_condition_code.Assign(0); |
|
||||
ret.index.Assign(static_cast<u32>(reg)); |
|
||||
return ret; |
|
||||
} |
|
||||
} |
|
||||
throw NotImplementedException("Register spilling"); |
|
||||
} |
|
||||
|
|
||||
void RegAlloc::Free(Id id) { |
|
||||
if (id.is_spill != 0) { |
|
||||
throw NotImplementedException("Free spill"); |
|
||||
} |
|
||||
register_use[id.index] = false; |
|
||||
} |
|
||||
|
|
||||
} // namespace Shader::Backend::GLSL
|
|
||||
@ -1,84 +0,0 @@ |
|||||
// Copyright 2021 yuzu Emulator Project |
|
||||
// Licensed under GPLv2 or any later version |
|
||||
// Refer to the license.txt file included. |
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <bitset> |
|
||||
#include <vector> |
|
||||
|
|
||||
#include "common/bit_field.h" |
|
||||
#include "common/common_types.h" |
|
||||
|
|
||||
namespace Shader::IR { |
|
||||
class Inst; |
|
||||
class Value; |
|
||||
enum class Type; |
|
||||
} // namespace Shader::IR |
|
||||
|
|
||||
namespace Shader::Backend::GLSL { |
|
||||
enum class Type : u32 { |
|
||||
U1, |
|
||||
F16x2, |
|
||||
S32, |
|
||||
U32, |
|
||||
F32, |
|
||||
S64, |
|
||||
U64, |
|
||||
F64, |
|
||||
U32x2, |
|
||||
F32x2, |
|
||||
U32x3, |
|
||||
F32x3, |
|
||||
U32x4, |
|
||||
F32x4, |
|
||||
Void, |
|
||||
}; |
|
||||
|
|
||||
struct Id { |
|
||||
union { |
|
||||
u32 raw; |
|
||||
BitField<0, 1, u32> is_valid; |
|
||||
BitField<1, 1, u32> is_long; |
|
||||
BitField<2, 1, u32> is_spill; |
|
||||
BitField<3, 1, u32> is_condition_code; |
|
||||
BitField<4, 1, u32> is_null; |
|
||||
BitField<5, 27, u32> index; |
|
||||
}; |
|
||||
|
|
||||
bool operator==(Id rhs) const noexcept { |
|
||||
return raw == rhs.raw; |
|
||||
} |
|
||||
bool operator!=(Id rhs) const noexcept { |
|
||||
return !operator==(rhs); |
|
||||
} |
|
||||
}; |
|
||||
static_assert(sizeof(Id) == sizeof(u32)); |
|
||||
|
|
||||
class RegAlloc { |
|
||||
public: |
|
||||
std::string Define(IR::Inst& inst); |
|
||||
std::string Define(IR::Inst& inst, Type type); |
|
||||
std::string Define(IR::Inst& inst, IR::Type type); |
|
||||
|
|
||||
std::string Consume(const IR::Value& value); |
|
||||
std::string Consume(IR::Inst& inst); |
|
||||
|
|
||||
std::string GetGlslType(Type type); |
|
||||
std::string GetGlslType(IR::Type type); |
|
||||
|
|
||||
size_t num_used_registers{}; |
|
||||
std::vector<std::string> reg_types; |
|
||||
|
|
||||
private: |
|
||||
static constexpr size_t NUM_REGS = 4096; |
|
||||
|
|
||||
Type RegType(IR::Type type); |
|
||||
Id Alloc(); |
|
||||
void Free(Id id); |
|
||||
|
|
||||
std::bitset<NUM_REGS> register_use{}; |
|
||||
std::bitset<NUM_REGS> register_defined{}; |
|
||||
}; |
|
||||
|
|
||||
} // namespace Shader::Backend::GLSL |
|
||||
@ -0,0 +1,290 @@ |
|||||
|
// 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::S32: |
||||
|
return "s_"; |
||||
|
case GlslVarType::F32: |
||||
|
return "f_"; |
||||
|
case GlslVarType::S64: |
||||
|
return "s64_"; |
||||
|
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::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 "uintBitsToFloat(0x7fc00000)"; |
||||
|
} |
||||
|
if (value == "inf") { |
||||
|
return "uintBitsToFloat(0x7f800000)"; |
||||
|
} |
||||
|
if (value == "-inf") { |
||||
|
return "uintBitsToFloat(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); |
||||
|
// id.is_null.Assign(1);
|
||||
|
GetUseTracker(type).uses_temp = true; |
||||
|
inst.SetDefinition<Id>(id); |
||||
|
} |
||||
|
return Representation(inst.Definition<Id>()); |
||||
|
} |
||||
|
|
||||
|
std::string VarAlloc::Define(IR::Inst& inst, IR::Type type) { |
||||
|
return Define(inst, RegType(type)); |
||||
|
} |
||||
|
|
||||
|
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)}; |
||||
|
if (use_tracker.num_used < NUM_VARS) { |
||||
|
for (size_t var = 1; 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; |
||||
|
} |
||||
|
} |
||||
|
throw NotImplementedException("Variable spilling"); |
||||
|
} |
||||
|
|
||||
|
void VarAlloc::Free(Id id) { |
||||
|
if (id.is_valid == 0) { |
||||
|
// throw LogicError("Freeing invalid variable");
|
||||
|
return; |
||||
|
} |
||||
|
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::S32: |
||||
|
return "int "; |
||||
|
case GlslVarType::F32: |
||||
|
return "float "; |
||||
|
case GlslVarType::S64: |
||||
|
return "int64_t "; |
||||
|
case GlslVarType::U64: |
||||
|
return "uint64_t "; |
||||
|
case GlslVarType::F64: |
||||
|
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::U32: |
||||
|
return var_u32; |
||||
|
case GlslVarType::S32: |
||||
|
return var_s32; |
||||
|
case GlslVarType::F32: |
||||
|
return var_f32; |
||||
|
case GlslVarType::S64: |
||||
|
return var_s64; |
||||
|
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; |
||||
|
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::S32: |
||||
|
return var_s32; |
||||
|
case GlslVarType::F32: |
||||
|
return var_f32; |
||||
|
case GlslVarType::S64: |
||||
|
return var_s64; |
||||
|
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; |
||||
|
default: |
||||
|
throw NotImplementedException("Type {}", type); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} // namespace Shader::Backend::GLSL
|
||||
@ -0,0 +1,100 @@ |
|||||
|
// Copyright 2021 yuzu Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <bitset> |
||||
|
#include <string> |
||||
|
#include <vector> |
||||
|
|
||||
|
#include "common/bit_field.h" |
||||
|
#include "common/common_types.h" |
||||
|
|
||||
|
namespace Shader::IR { |
||||
|
class Inst; |
||||
|
class Value; |
||||
|
enum class Type; |
||||
|
} // namespace Shader::IR |
||||
|
|
||||
|
namespace Shader::Backend::GLSL { |
||||
|
enum class GlslVarType : u32 { |
||||
|
U1, |
||||
|
F16x2, |
||||
|
S32, |
||||
|
U32, |
||||
|
F32, |
||||
|
S64, |
||||
|
U64, |
||||
|
F64, |
||||
|
U32x2, |
||||
|
F32x2, |
||||
|
U32x3, |
||||
|
F32x3, |
||||
|
U32x4, |
||||
|
F32x4, |
||||
|
Void, |
||||
|
}; |
||||
|
|
||||
|
struct Id { |
||||
|
union { |
||||
|
u32 raw; |
||||
|
BitField<0, 1, u32> is_valid; |
||||
|
BitField<1, 4, GlslVarType> type; |
||||
|
BitField<5, 27, u32> index; |
||||
|
}; |
||||
|
|
||||
|
bool operator==(Id rhs) const noexcept { |
||||
|
return raw == rhs.raw; |
||||
|
} |
||||
|
bool operator!=(Id rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
}; |
||||
|
static_assert(sizeof(Id) == sizeof(u32)); |
||||
|
|
||||
|
class VarAlloc { |
||||
|
public: |
||||
|
static constexpr size_t NUM_VARS = 511; |
||||
|
struct UseTracker { |
||||
|
size_t num_used{}; |
||||
|
std::bitset<NUM_VARS> var_use{}; |
||||
|
bool uses_temp{}; |
||||
|
}; |
||||
|
|
||||
|
std::string Define(IR::Inst& inst, GlslVarType type); |
||||
|
std::string Define(IR::Inst& inst, IR::Type type); |
||||
|
|
||||
|
std::string Consume(const IR::Value& value); |
||||
|
std::string ConsumeInst(IR::Inst& inst); |
||||
|
|
||||
|
std::string GetGlslType(GlslVarType type) const; |
||||
|
std::string GetGlslType(IR::Type type) const; |
||||
|
|
||||
|
const UseTracker& GetUseTracker(GlslVarType type) const; |
||||
|
std::string Representation(u32 index, GlslVarType type) const; |
||||
|
|
||||
|
private: |
||||
|
GlslVarType RegType(IR::Type type) const; |
||||
|
Id Alloc(GlslVarType type); |
||||
|
void Free(Id id); |
||||
|
UseTracker& GetUseTracker(GlslVarType type); |
||||
|
std::string Representation(Id id) const; |
||||
|
|
||||
|
UseTracker var_bool{}; |
||||
|
UseTracker var_f16x2{}; |
||||
|
UseTracker var_s32{}; |
||||
|
UseTracker var_u32{}; |
||||
|
UseTracker var_u32x2{}; |
||||
|
UseTracker var_u32x3{}; |
||||
|
UseTracker var_u32x4{}; |
||||
|
UseTracker var_f32{}; |
||||
|
UseTracker var_f32x2{}; |
||||
|
UseTracker var_f32x3{}; |
||||
|
UseTracker var_f32x4{}; |
||||
|
UseTracker var_u64{}; |
||||
|
UseTracker var_s64{}; |
||||
|
UseTracker var_f64{}; |
||||
|
}; |
||||
|
|
||||
|
} // namespace Shader::Backend::GLSL |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue