glsl: Reusable typed variables. IADD32

This commit is contained in:
ameerj 2021-05-21 02:00:12 -04:00
parent faf4cd72c5
commit e221baccdd
6 changed files with 311 additions and 203 deletions

View file

@ -31,9 +31,33 @@ class EmitContext {
public:
explicit EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_);
// template <typename... Args>
// void Add(const char* format_str, IR::Inst& inst, Args&&... args) {
// code += fmt::format(format_str, reg_alloc.Define(inst), std::forward<Args>(args)...);
// // TODO: Remove this
// code += '\n';
// }
template <typename... Args>
void Add(const char* format_str, IR::Inst& inst, Args&&... args) {
code += fmt::format(format_str, reg_alloc.Define(inst), std::forward<Args>(args)...);
void AddU32(const char* format_str, IR::Inst& inst, Args&&... args) {
code +=
fmt::format(format_str, reg_alloc.Define(inst, Type::U32), std::forward<Args>(args)...);
// TODO: Remove this
code += '\n';
}
template <typename... Args>
void AddS32(const char* format_str, IR::Inst& inst, Args&&... args) {
code +=
fmt::format(format_str, reg_alloc.Define(inst, Type::S32), std::forward<Args>(args)...);
// TODO: Remove this
code += '\n';
}
template <typename... Args>
void AddF32(const char* format_str, IR::Inst& inst, Args&&... args) {
code +=
fmt::format(format_str, reg_alloc.Define(inst, Type::F32), std::forward<Args>(args)...);
// TODO: Remove this
code += '\n';
}

View file

@ -33,8 +33,8 @@ void EmitGetCbufS16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] const IR
void EmitGetCbufU32(EmitContext& ctx, IR::Inst* inst, const IR::Value& binding,
const IR::Value& offset) {
const auto u32_offset{offset.U32()};
ctx.Add("uint {}=floatBitsToUint(cbuf{}[{}][{}]);", *inst, binding.U32(), u32_offset / 16,
(u32_offset / 4) % 4);
ctx.AddU32("{}=floatBitsToUint(cbuf{}[{}][{}]);", *inst, binding.U32(), u32_offset / 16,
(u32_offset / 4) % 4);
}
void EmitGetCbufF32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] const IR::Value& binding,

View file

@ -0,0 +1,221 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <string_view>
#include "shader_recompiler/backend/glsl/emit_context.h"
#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
#include "shader_recompiler/frontend/ir/value.h"
#include "shader_recompiler/profile.h"
namespace Shader::Backend::GLSL {
void EmitIAdd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
[[maybe_unused]] std::string a, [[maybe_unused]] std::string b) {
ctx.AddU32("{}={}+{};", *inst, a, b);
}
void EmitIAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
[[maybe_unused]] std::string b) {
throw NotImplementedException("GLSL Instruction");
}
void EmitISub32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
[[maybe_unused]] std::string b) {
throw NotImplementedException("GLSL Instruction");
}
void EmitISub64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
[[maybe_unused]] std::string b) {
throw NotImplementedException("GLSL Instruction");
}
void EmitIMul32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
[[maybe_unused]] std::string b) {
throw NotImplementedException("GLSL Instruction");
}
void EmitINeg32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
throw NotImplementedException("GLSL Instruction");
}
void EmitINeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
throw NotImplementedException("GLSL Instruction");
}
void EmitIAbs32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
throw NotImplementedException("GLSL Instruction");
}
void EmitIAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
throw NotImplementedException("GLSL Instruction");
}
void EmitShiftLeftLogical32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string base,
[[maybe_unused]] std::string shift) {
throw NotImplementedException("GLSL Instruction");
}
void EmitShiftLeftLogical64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string base,
[[maybe_unused]] std::string shift) {
throw NotImplementedException("GLSL Instruction");
}
void EmitShiftRightLogical32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string base,
[[maybe_unused]] std::string shift) {
throw NotImplementedException("GLSL Instruction");
}
void EmitShiftRightLogical64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string base,
[[maybe_unused]] std::string shift) {
throw NotImplementedException("GLSL Instruction");
}
void EmitShiftRightArithmetic32([[maybe_unused]] EmitContext& ctx,
[[maybe_unused]] std::string base,
[[maybe_unused]] std::string shift) {
throw NotImplementedException("GLSL Instruction");
}
void EmitShiftRightArithmetic64([[maybe_unused]] EmitContext& ctx,
[[maybe_unused]] std::string base,
[[maybe_unused]] std::string shift) {
throw NotImplementedException("GLSL Instruction");
}
void EmitBitwiseAnd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
[[maybe_unused]] std::string a, [[maybe_unused]] std::string b) {
throw NotImplementedException("GLSL Instruction");
}
void EmitBitwiseOr32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
[[maybe_unused]] std::string a, [[maybe_unused]] std::string b) {
throw NotImplementedException("GLSL Instruction");
}
void EmitBitwiseXor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
[[maybe_unused]] std::string a, [[maybe_unused]] std::string b) {
throw NotImplementedException("GLSL Instruction");
}
void EmitBitFieldInsert([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string base,
[[maybe_unused]] std::string insert, [[maybe_unused]] std::string offset,
std::string count) {
throw NotImplementedException("GLSL Instruction");
}
void EmitBitFieldSExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
[[maybe_unused]] std::string base, [[maybe_unused]] std::string offset,
std::string count) {
throw NotImplementedException("GLSL Instruction");
}
void EmitBitFieldUExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
[[maybe_unused]] std::string base, [[maybe_unused]] std::string offset,
std::string count) {
throw NotImplementedException("GLSL Instruction");
}
void EmitBitReverse32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
throw NotImplementedException("GLSL Instruction");
}
void EmitBitCount32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
throw NotImplementedException("GLSL Instruction");
}
void EmitBitwiseNot32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
throw NotImplementedException("GLSL Instruction");
}
void EmitFindSMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
throw NotImplementedException("GLSL Instruction");
}
void EmitFindUMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
throw NotImplementedException("GLSL Instruction");
}
void EmitSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
[[maybe_unused]] std::string b) {
throw NotImplementedException("GLSL Instruction");
}
void EmitUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
[[maybe_unused]] std::string b) {
throw NotImplementedException("GLSL Instruction");
}
void EmitSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
[[maybe_unused]] std::string b) {
throw NotImplementedException("GLSL Instruction");
}
void EmitUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
[[maybe_unused]] std::string b) {
throw NotImplementedException("GLSL Instruction");
}
void EmitSClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
[[maybe_unused]] std::string value, [[maybe_unused]] std::string min,
std::string max) {
throw NotImplementedException("GLSL Instruction");
}
void EmitUClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
[[maybe_unused]] std::string value, [[maybe_unused]] std::string min,
std::string max) {
throw NotImplementedException("GLSL Instruction");
}
void EmitSLessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
[[maybe_unused]] std::string rhs) {
throw NotImplementedException("GLSL Instruction");
}
void EmitULessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
[[maybe_unused]] std::string rhs) {
throw NotImplementedException("GLSL Instruction");
}
void EmitIEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
[[maybe_unused]] std::string rhs) {
throw NotImplementedException("GLSL Instruction");
}
void EmitSLessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
[[maybe_unused]] std::string rhs) {
throw NotImplementedException("GLSL Instruction");
}
void EmitULessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
[[maybe_unused]] std::string rhs) {
throw NotImplementedException("GLSL Instruction");
}
void EmitSGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
[[maybe_unused]] std::string rhs) {
throw NotImplementedException("GLSL Instruction");
}
void EmitUGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
[[maybe_unused]] std::string rhs) {
throw NotImplementedException("GLSL Instruction");
}
void EmitINotEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
[[maybe_unused]] std::string rhs) {
throw NotImplementedException("GLSL Instruction");
}
void EmitSGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
[[maybe_unused]] std::string rhs) {
throw NotImplementedException("GLSL Instruction");
}
void EmitUGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
[[maybe_unused]] std::string rhs) {
throw NotImplementedException("GLSL Instruction");
}
} // namespace Shader::Backend::GLSL

View file

@ -979,179 +979,6 @@ void EmitFPIsNan64(EmitContext& ctx, std::string value) {
NotImplemented();
}
void EmitIAdd32(EmitContext& ctx, IR::Inst* inst, std::string a, std::string b) {
NotImplemented();
}
void EmitIAdd64(EmitContext& ctx, std::string a, std::string b) {
NotImplemented();
}
void EmitISub32(EmitContext& ctx, std::string a, std::string b) {
NotImplemented();
}
void EmitISub64(EmitContext& ctx, std::string a, std::string b) {
NotImplemented();
}
void EmitIMul32(EmitContext& ctx, std::string a, std::string b) {
NotImplemented();
}
void EmitINeg32(EmitContext& ctx, std::string value) {
NotImplemented();
}
void EmitINeg64(EmitContext& ctx, std::string value) {
NotImplemented();
}
void EmitIAbs32(EmitContext& ctx, std::string value) {
NotImplemented();
}
void EmitIAbs64(EmitContext& ctx, std::string value) {
NotImplemented();
}
void EmitShiftLeftLogical32(EmitContext& ctx, std::string base, std::string shift) {
NotImplemented();
}
void EmitShiftLeftLogical64(EmitContext& ctx, std::string base, std::string shift) {
NotImplemented();
}
void EmitShiftRightLogical32(EmitContext& ctx, std::string base, std::string shift) {
NotImplemented();
}
void EmitShiftRightLogical64(EmitContext& ctx, std::string base, std::string shift) {
NotImplemented();
}
void EmitShiftRightArithmetic32(EmitContext& ctx, std::string base, std::string shift) {
NotImplemented();
}
void EmitShiftRightArithmetic64(EmitContext& ctx, std::string base, std::string shift) {
NotImplemented();
}
void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst* inst, std::string a, std::string b) {
NotImplemented();
}
void EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, std::string a, std::string b) {
NotImplemented();
}
void EmitBitwiseXor32(EmitContext& ctx, IR::Inst* inst, std::string a, std::string b) {
NotImplemented();
}
void EmitBitFieldInsert(EmitContext& ctx, std::string base, std::string insert, std::string offset,
std::string count) {
NotImplemented();
}
void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst* inst, std::string base, std::string offset,
std::string count) {
NotImplemented();
}
void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst* inst, std::string base, std::string offset,
std::string count) {
NotImplemented();
}
void EmitBitReverse32(EmitContext& ctx, std::string value) {
NotImplemented();
}
void EmitBitCount32(EmitContext& ctx, std::string value) {
NotImplemented();
}
void EmitBitwiseNot32(EmitContext& ctx, std::string value) {
NotImplemented();
}
void EmitFindSMsb32(EmitContext& ctx, std::string value) {
NotImplemented();
}
void EmitFindUMsb32(EmitContext& ctx, std::string value) {
NotImplemented();
}
void EmitSMin32(EmitContext& ctx, std::string a, std::string b) {
NotImplemented();
}
void EmitUMin32(EmitContext& ctx, std::string a, std::string b) {
NotImplemented();
}
void EmitSMax32(EmitContext& ctx, std::string a, std::string b) {
NotImplemented();
}
void EmitUMax32(EmitContext& ctx, std::string a, std::string b) {
NotImplemented();
}
void EmitSClamp32(EmitContext& ctx, IR::Inst* inst, std::string value, std::string min,
std::string max) {
NotImplemented();
}
void EmitUClamp32(EmitContext& ctx, IR::Inst* inst, std::string value, std::string min,
std::string max) {
NotImplemented();
}
void EmitSLessThan(EmitContext& ctx, std::string lhs, std::string rhs) {
NotImplemented();
}
void EmitULessThan(EmitContext& ctx, std::string lhs, std::string rhs) {
NotImplemented();
}
void EmitIEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
NotImplemented();
}
void EmitSLessThanEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
NotImplemented();
}
void EmitULessThanEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
NotImplemented();
}
void EmitSGreaterThan(EmitContext& ctx, std::string lhs, std::string rhs) {
NotImplemented();
}
void EmitUGreaterThan(EmitContext& ctx, std::string lhs, std::string rhs) {
NotImplemented();
}
void EmitINotEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
NotImplemented();
}
void EmitSGreaterThanEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
NotImplemented();
}
void EmitUGreaterThanEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
NotImplemented();
}
void EmitSharedAtomicIAdd32(EmitContext& ctx, std::string pointer_offset, std::string value) {
NotImplemented();
}

View file

@ -13,7 +13,6 @@
#pragma optimize("", off)
namespace Shader::Backend::GLSL {
namespace {
constexpr std::string_view SWIZZLE = "xyzw";
std::string Representation(Id id) {
if (id.is_condition_code != 0) {
@ -22,7 +21,6 @@ std::string Representation(Id id) {
if (id.is_spill != 0) {
throw NotImplementedException("Spilling");
}
const u32 num_elements{id.num_elements_minus_one + 1};
const u32 index{static_cast<u32>(id.index)};
return fmt::format("R{}", index);
}
@ -45,10 +43,11 @@ std::string MakeImm(const IR::Value& value) {
}
} // Anonymous namespace
std::string RegAlloc::Define(IR::Inst& inst, u32 num_elements, u32 alignment) {
const Id id{Alloc(num_elements, alignment)};
std::string RegAlloc::Define(IR::Inst& inst, Type type) {
const Id id{Alloc()};
const auto type_str{GetType(type, id.index)};
inst.SetDefinition<Id>(id);
return Representation(id);
return type_str + Representation(id);
}
std::string RegAlloc::Consume(const IR::Value& value) {
@ -65,20 +64,37 @@ std::string RegAlloc::Consume(IR::Inst& inst) {
return Representation(inst.Definition<Id>());
}
Id RegAlloc::Alloc(u32 num_elements, [[maybe_unused]] u32 alignment) {
for (size_t reg = 0; reg < NUM_REGS; ++reg) {
if (register_use[reg]) {
continue;
std::string RegAlloc::GetType(Type type, u32 index) {
if (register_defined[index]) {
return "";
}
register_defined[index] = true;
switch (type) {
case Type::U32:
return "uint ";
case Type::S32:
return "int ";
case Type::F32:
return "float ";
default:
return "";
}
}
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.index.Assign(static_cast<u32>(reg));
ret.is_long.Assign(0);
ret.is_spill.Assign(0);
ret.is_condition_code.Assign(0);
return ret;
}
num_used_registers = std::max(num_used_registers, reg + 1);
register_use[reg] = true;
return Id{
.base_element = 0,
.num_elements_minus_one = num_elements - 1,
.index = static_cast<u32>(reg),
.is_spill = 0,
.is_condition_code = 0,
};
}
throw NotImplementedException("Register spilling");
}

View file

@ -6,6 +6,7 @@
#include <bitset>
#include "common/bit_field.h"
#include "common/common_types.h"
namespace Shader::IR {
@ -14,18 +15,36 @@ class Value;
} // namespace Shader::IR
namespace Shader::Backend::GLSL {
enum class Type : u32 {
U32,
S32,
F32,
U64,
F64,
Void,
};
struct Id {
u32 base_element : 2;
u32 num_elements_minus_one : 2;
u32 index : 26;
u32 is_spill : 1;
u32 is_condition_code : 1;
union {
u32 raw;
BitField<0, 29, u32> index;
BitField<29, 1, u32> is_long;
BitField<30, 1, u32> is_spill;
BitField<31, 1, u32> is_condition_code;
};
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, u32 num_elements = 1, u32 alignment = 1);
std::string Define(IR::Inst& inst, Type type = Type::Void);
std::string Consume(const IR::Value& value);
@ -40,13 +59,14 @@ private:
static constexpr size_t NUM_ELEMENTS = 4;
std::string Consume(IR::Inst& inst);
std::string GetType(Type type, u32 index);
Id Alloc(u32 num_elements, u32 alignment);
Id Alloc();
void Free(Id id);
size_t num_used_registers{};
std::bitset<NUM_REGS> register_use{};
std::bitset<NUM_REGS> register_defined{};
};
} // namespace Shader::Backend::GLSL