forked from suyu/suyu
gl_shader_decompiler: Add AOFFI backing implementation
This commit is contained in:
parent
cb68ce7c2f
commit
e8abe4b77c
1 changed files with 87 additions and 40 deletions
|
@ -34,14 +34,20 @@ using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
|||
using ShaderStage = Tegra::Engines::Maxwell3D::Regs::ShaderStage;
|
||||
using Operation = const OperationNode&;
|
||||
|
||||
enum class Type { Bool, Bool2, Float, Int, Uint, HalfFloat };
|
||||
|
||||
namespace {
|
||||
struct TextureAoffi {};
|
||||
using TextureArgument = std::pair<Type, Node>;
|
||||
using TextureIR = std::variant<TextureAoffi, TextureArgument>;
|
||||
} // namespace
|
||||
|
||||
enum : u32 { POSITION_VARYING_LOCATION = 0, GENERIC_VARYING_START_LOCATION = 1 };
|
||||
constexpr u32 MAX_CONSTBUFFER_ELEMENTS =
|
||||
static_cast<u32>(RasterizerOpenGL::MaxConstbufferSize) / (4 * sizeof(float));
|
||||
constexpr u32 MAX_GLOBALMEMORY_ELEMENTS =
|
||||
static_cast<u32>(RasterizerOpenGL::MaxGlobalMemorySize) / sizeof(float);
|
||||
|
||||
enum class Type { Bool, Bool2, Float, Int, Uint, HalfFloat };
|
||||
|
||||
class ShaderWriter {
|
||||
public:
|
||||
void AddExpression(std::string_view text) {
|
||||
|
@ -718,8 +724,8 @@ private:
|
|||
result_type));
|
||||
}
|
||||
|
||||
std::string GenerateTexture(Operation operation, const std::string& func,
|
||||
const std::vector<std::pair<Type, Node>>& extras) {
|
||||
std::string GenerateTexture(Operation operation, const std::string& function_suffix,
|
||||
const std::vector<TextureIR>& extras) {
|
||||
constexpr std::array<const char*, 4> coord_constructors = {"float", "vec2", "vec3", "vec4"};
|
||||
|
||||
const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
|
||||
|
@ -729,11 +735,11 @@ private:
|
|||
const bool has_array = meta->sampler.IsArray();
|
||||
const bool has_shadow = meta->sampler.IsShadow();
|
||||
|
||||
std::string expr = func;
|
||||
expr += '(';
|
||||
expr += GetSampler(meta->sampler);
|
||||
expr += ", ";
|
||||
|
||||
std::string expr = "texture" + function_suffix;
|
||||
if (!meta->aoffi.empty()) {
|
||||
expr += "Offset";
|
||||
}
|
||||
expr += '(' + GetSampler(meta->sampler) + ", ";
|
||||
expr += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow ? 1 : 0) - 1);
|
||||
expr += '(';
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
|
@ -751,38 +757,76 @@ private:
|
|||
}
|
||||
expr += ')';
|
||||
|
||||
for (const auto& extra_pair : extras) {
|
||||
const auto [type, operand] = extra_pair;
|
||||
if (operand == nullptr) {
|
||||
continue;
|
||||
}
|
||||
expr += ", ";
|
||||
|
||||
switch (type) {
|
||||
case Type::Int:
|
||||
if (const auto immediate = std::get_if<ImmediateNode>(operand)) {
|
||||
// Inline the string as an immediate integer in GLSL (some extra arguments are
|
||||
// required to be constant)
|
||||
expr += std::to_string(static_cast<s32>(immediate->GetValue()));
|
||||
} else {
|
||||
expr += "ftoi(" + Visit(operand) + ')';
|
||||
}
|
||||
break;
|
||||
case Type::Float:
|
||||
expr += Visit(operand);
|
||||
break;
|
||||
default: {
|
||||
const auto type_int = static_cast<u32>(type);
|
||||
UNIMPLEMENTED_MSG("Unimplemented extra type={}", type_int);
|
||||
expr += '0';
|
||||
break;
|
||||
}
|
||||
for (const auto& variant : extras) {
|
||||
if (const auto argument = std::get_if<TextureArgument>(&variant)) {
|
||||
expr += GenerateTextureArgument(*argument);
|
||||
} else if (std::get_if<TextureAoffi>(&variant)) {
|
||||
expr += GenerateTextureAoffi(meta->aoffi);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
return expr + ')';
|
||||
}
|
||||
|
||||
std::string GenerateTextureArgument(TextureArgument argument) {
|
||||
const auto [type, operand] = argument;
|
||||
if (operand == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string expr = ", ";
|
||||
switch (type) {
|
||||
case Type::Int:
|
||||
if (const auto immediate = std::get_if<ImmediateNode>(operand)) {
|
||||
// Inline the string as an immediate integer in GLSL (some extra arguments are
|
||||
// required to be constant)
|
||||
expr += std::to_string(static_cast<s32>(immediate->GetValue()));
|
||||
} else {
|
||||
expr += "ftoi(" + Visit(operand) + ')';
|
||||
}
|
||||
break;
|
||||
case Type::Float:
|
||||
expr += Visit(operand);
|
||||
break;
|
||||
default: {
|
||||
const auto type_int = static_cast<u32>(type);
|
||||
UNIMPLEMENTED_MSG("Unimplemented extra type={}", type_int);
|
||||
expr += '0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
std::string GenerateTextureAoffi(const std::vector<Node>& aoffi) {
|
||||
if (aoffi.empty()) {
|
||||
return {};
|
||||
}
|
||||
constexpr std::array<const char*, 3> coord_constructors = {"int", "ivec2", "ivec3"};
|
||||
std::string expr = ", ";
|
||||
expr += coord_constructors.at(aoffi.size() - 1);
|
||||
expr += '(';
|
||||
|
||||
for (std::size_t index = 0; index < aoffi.size(); ++index) {
|
||||
const auto operand{aoffi.at(index)};
|
||||
if (const auto immediate = std::get_if<ImmediateNode>(operand)) {
|
||||
// Inline the string as an immediate integer in GLSL (AOFFI arguments are required
|
||||
// to be constant by the standard).
|
||||
expr += std::to_string(static_cast<s32>(immediate->GetValue()));
|
||||
} else {
|
||||
expr += "ftoi(" + Visit(operand) + ')';
|
||||
}
|
||||
if (index + 1 < aoffi.size()) {
|
||||
expr += ", ";
|
||||
}
|
||||
}
|
||||
expr += ')';
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
std::string Assign(Operation operation) {
|
||||
const Node dest = operation[0];
|
||||
const Node src = operation[1];
|
||||
|
@ -1159,7 +1203,8 @@ private:
|
|||
const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
|
||||
ASSERT(meta);
|
||||
|
||||
std::string expr = GenerateTexture(operation, "texture", {{Type::Float, meta->bias}});
|
||||
std::string expr = GenerateTexture(
|
||||
operation, "", {TextureAoffi{}, TextureArgument{Type::Float, meta->bias}});
|
||||
if (meta->sampler.IsShadow()) {
|
||||
expr = "vec4(" + expr + ')';
|
||||
}
|
||||
|
@ -1170,7 +1215,8 @@ private:
|
|||
const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
|
||||
ASSERT(meta);
|
||||
|
||||
std::string expr = GenerateTexture(operation, "textureLod", {{Type::Float, meta->lod}});
|
||||
std::string expr = GenerateTexture(
|
||||
operation, "Lod", {TextureArgument{Type::Float, meta->lod}, TextureAoffi{}});
|
||||
if (meta->sampler.IsShadow()) {
|
||||
expr = "vec4(" + expr + ')';
|
||||
}
|
||||
|
@ -1182,7 +1228,8 @@ private:
|
|||
ASSERT(meta);
|
||||
|
||||
const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int;
|
||||
return GenerateTexture(operation, "textureGather", {{type, meta->component}}) +
|
||||
return GenerateTexture(operation, "Gather",
|
||||
{TextureArgument{type, meta->component}, TextureAoffi{}}) +
|
||||
GetSwizzle(meta->element);
|
||||
}
|
||||
|
||||
|
@ -1211,8 +1258,8 @@ private:
|
|||
ASSERT(meta);
|
||||
|
||||
if (meta->element < 2) {
|
||||
return "itof(int((" + GenerateTexture(operation, "textureQueryLod", {}) +
|
||||
" * vec2(256))" + GetSwizzle(meta->element) + "))";
|
||||
return "itof(int((" + GenerateTexture(operation, "QueryLod", {}) + " * vec2(256))" +
|
||||
GetSwizzle(meta->element) + "))";
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue