|
|
@ -34,14 +34,20 @@ using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
|
|
using ShaderStage = Tegra::Engines::Maxwell3D::Regs::ShaderStage; |
|
|
using ShaderStage = Tegra::Engines::Maxwell3D::Regs::ShaderStage; |
|
|
using Operation = const OperationNode&; |
|
|
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 }; |
|
|
enum : u32 { POSITION_VARYING_LOCATION = 0, GENERIC_VARYING_START_LOCATION = 1 }; |
|
|
constexpr u32 MAX_CONSTBUFFER_ELEMENTS = |
|
|
constexpr u32 MAX_CONSTBUFFER_ELEMENTS = |
|
|
static_cast<u32>(RasterizerOpenGL::MaxConstbufferSize) / (4 * sizeof(float)); |
|
|
static_cast<u32>(RasterizerOpenGL::MaxConstbufferSize) / (4 * sizeof(float)); |
|
|
constexpr u32 MAX_GLOBALMEMORY_ELEMENTS = |
|
|
constexpr u32 MAX_GLOBALMEMORY_ELEMENTS = |
|
|
static_cast<u32>(RasterizerOpenGL::MaxGlobalMemorySize) / sizeof(float); |
|
|
static_cast<u32>(RasterizerOpenGL::MaxGlobalMemorySize) / sizeof(float); |
|
|
|
|
|
|
|
|
enum class Type { Bool, Bool2, Float, Int, Uint, HalfFloat }; |
|
|
|
|
|
|
|
|
|
|
|
class ShaderWriter { |
|
|
class ShaderWriter { |
|
|
public: |
|
|
public: |
|
|
void AddExpression(std::string_view text) { |
|
|
void AddExpression(std::string_view text) { |
|
|
@ -718,8 +724,8 @@ private: |
|
|
result_type)); |
|
|
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"}; |
|
|
constexpr std::array<const char*, 4> coord_constructors = {"float", "vec2", "vec3", "vec4"}; |
|
|
|
|
|
|
|
|
const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); |
|
|
const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); |
|
|
@ -729,11 +735,11 @@ private: |
|
|
const bool has_array = meta->sampler.IsArray(); |
|
|
const bool has_array = meta->sampler.IsArray(); |
|
|
const bool has_shadow = meta->sampler.IsShadow(); |
|
|
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 += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow ? 1 : 0) - 1); |
|
|
expr += '('; |
|
|
expr += '('; |
|
|
for (std::size_t i = 0; i < count; ++i) { |
|
|
for (std::size_t i = 0; i < count; ++i) { |
|
|
@ -751,36 +757,74 @@ private: |
|
|
} |
|
|
} |
|
|
expr += ')'; |
|
|
expr += ')'; |
|
|
|
|
|
|
|
|
for (const auto& extra_pair : extras) { |
|
|
|
|
|
const auto [type, operand] = extra_pair; |
|
|
|
|
|
if (operand == nullptr) { |
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
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(); |
|
|
} |
|
|
} |
|
|
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 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 + ')'; |
|
|
|
|
|
|
|
|
return expr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::string Assign(Operation operation) { |
|
|
std::string Assign(Operation operation) { |
|
|
@ -1159,7 +1203,8 @@ private: |
|
|
const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); |
|
|
const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); |
|
|
ASSERT(meta); |
|
|
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()) { |
|
|
if (meta->sampler.IsShadow()) { |
|
|
expr = "vec4(" + expr + ')'; |
|
|
expr = "vec4(" + expr + ')'; |
|
|
} |
|
|
} |
|
|
@ -1170,7 +1215,8 @@ private: |
|
|
const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); |
|
|
const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); |
|
|
ASSERT(meta); |
|
|
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()) { |
|
|
if (meta->sampler.IsShadow()) { |
|
|
expr = "vec4(" + expr + ')'; |
|
|
expr = "vec4(" + expr + ')'; |
|
|
} |
|
|
} |
|
|
@ -1182,7 +1228,8 @@ private: |
|
|
ASSERT(meta); |
|
|
ASSERT(meta); |
|
|
|
|
|
|
|
|
const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int; |
|
|
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); |
|
|
GetSwizzle(meta->element); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1211,8 +1258,8 @@ private: |
|
|
ASSERT(meta); |
|
|
ASSERT(meta); |
|
|
|
|
|
|
|
|
if (meta->element < 2) { |
|
|
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"; |
|
|
return "0"; |
|
|
} |
|
|
} |
|
|
|