|
|
@@ -146,6 +146,90 @@ private:
|
|
|
std::string shader_source;
|
|
|
};
|
|
|
|
|
|
+/**
|
|
|
+ * Represents an emulated shader register, used to track the state of that register for emulation
|
|
|
+ * with GLSL. At this time, a register can be used as a float or an integer. This class is used for
|
|
|
+ * bookkeeping within the GLSL program.
|
|
|
+ */
|
|
|
+class GLSLRegister {
|
|
|
+public:
|
|
|
+ GLSLRegister(size_t index, ShaderWriter& shader)
|
|
|
+ : index{index}, shader{shader}, float_str{"freg_" + std::to_string(index)},
|
|
|
+ integer_str{"ireg_" + std::to_string(index)} {}
|
|
|
+
|
|
|
+ /// Returns a GLSL string representing the current state of the register
|
|
|
+ const std::string& GetActiveString() {
|
|
|
+ declr_type.insert(active_type);
|
|
|
+
|
|
|
+ switch (active_type) {
|
|
|
+ case Type::Float:
|
|
|
+ return float_str;
|
|
|
+ case Type::Integer:
|
|
|
+ return integer_str;
|
|
|
+ }
|
|
|
+
|
|
|
+ UNREACHABLE();
|
|
|
+ return float_str;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Returns a GLSL string representing the register as a float
|
|
|
+ const std::string& GetFloatString() const {
|
|
|
+ ASSERT(IsFloatUsed());
|
|
|
+ return float_str;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Returns a GLSL string representing the register as an integer
|
|
|
+ const std::string& GetIntegerString() const {
|
|
|
+ ASSERT(IsIntegerUsed());
|
|
|
+ return integer_str;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Convert the current register state from float to integer
|
|
|
+ void FloatToInteger() {
|
|
|
+ ASSERT(active_type == Type::Float);
|
|
|
+
|
|
|
+ const std::string src = GetActiveString();
|
|
|
+ active_type = Type::Integer;
|
|
|
+ const std::string dest = GetActiveString();
|
|
|
+
|
|
|
+ shader.AddLine(dest + " = floatBitsToInt(" + src + ");");
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Convert the current register state from integer to float
|
|
|
+ void IntegerToFloat() {
|
|
|
+ ASSERT(active_type == Type::Integer);
|
|
|
+
|
|
|
+ const std::string src = GetActiveString();
|
|
|
+ active_type = Type::Float;
|
|
|
+ const std::string dest = GetActiveString();
|
|
|
+
|
|
|
+ shader.AddLine(dest + " = intBitsToFloat(" + src + ");");
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Returns true if the register was ever used as a float, used for register declarations
|
|
|
+ bool IsFloatUsed() const {
|
|
|
+ return declr_type.find(Type::Float) != declr_type.end();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Returns true if the register was ever used as an integer, used for register declarations
|
|
|
+ bool IsIntegerUsed() const {
|
|
|
+ return declr_type.find(Type::Integer) != declr_type.end();
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ enum class Type {
|
|
|
+ Float,
|
|
|
+ Integer,
|
|
|
+ };
|
|
|
+
|
|
|
+ const size_t index;
|
|
|
+ const std::string float_str;
|
|
|
+ const std::string integer_str;
|
|
|
+ ShaderWriter& shader;
|
|
|
+ Type active_type{Type::Float};
|
|
|
+ std::set<Type> declr_type;
|
|
|
+};
|
|
|
+
|
|
|
class GLSLGenerator {
|
|
|
public:
|
|
|
GLSLGenerator(const std::set<Subroutine>& subroutines, const ProgramCode& program_code,
|
|
|
@@ -153,6 +237,7 @@ public:
|
|
|
: subroutines(subroutines), program_code(program_code), main_offset(main_offset),
|
|
|
stage(stage) {
|
|
|
|
|
|
+ BuildRegisterList();
|
|
|
Generate();
|
|
|
}
|
|
|
|
|
|
@@ -166,6 +251,13 @@ public:
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
+ /// Build the GLSL register list
|
|
|
+ void BuildRegisterList() {
|
|
|
+ for (size_t index = 0; index < Register::NumRegisters; ++index) {
|
|
|
+ regs.emplace_back(index, shader);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// Gets the Subroutine object corresponding to the specified address.
|
|
|
const Subroutine& GetSubroutine(u32 begin, u32 end) const {
|
|
|
auto iter = subroutines.find(Subroutine{begin, end});
|
|
|
@@ -224,8 +316,8 @@ private:
|
|
|
if (reg == Register::ZeroIndex) {
|
|
|
return "0";
|
|
|
}
|
|
|
- return *declr_register.insert("register_" + std::to_string(reg.GetSwizzledIndex(elem)))
|
|
|
- .first;
|
|
|
+
|
|
|
+ return regs[reg.GetSwizzledIndex(elem)].GetActiveString();
|
|
|
}
|
|
|
|
|
|
/// Generates code representing a uniform (C buffer) register.
|
|
|
@@ -761,8 +853,13 @@ private:
|
|
|
|
|
|
/// Add declarations for registers
|
|
|
void GenerateDeclarations() {
|
|
|
- for (const auto& reg : declr_register) {
|
|
|
- declarations.AddLine("float " + reg + " = 0.0;");
|
|
|
+ for (const auto& reg : regs) {
|
|
|
+ if (reg.IsFloatUsed()) {
|
|
|
+ declarations.AddLine("float " + reg.GetFloatString() + " = 0.0;");
|
|
|
+ }
|
|
|
+ if (reg.IsIntegerUsed()) {
|
|
|
+ declarations.AddLine("int " + reg.GetIntegerString() + " = 0;");
|
|
|
+ }
|
|
|
}
|
|
|
declarations.AddNewLine();
|
|
|
|
|
|
@@ -809,9 +906,9 @@ private:
|
|
|
|
|
|
ShaderWriter shader;
|
|
|
ShaderWriter declarations;
|
|
|
+ std::vector<GLSLRegister> regs;
|
|
|
|
|
|
// Declarations
|
|
|
- std::set<std::string> declr_register;
|
|
|
std::set<std::string> declr_predicates;
|
|
|
std::set<Attribute::Index> declr_input_attribute;
|
|
|
std::set<Attribute::Index> declr_output_attribute;
|