diff options
author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2018-12-24 06:24:38 +0100 |
---|---|---|
committer | ReinUsesLisp <reinuseslisp@airmail.cc> | 2019-01-15 21:54:53 +0100 |
commit | e1fea1e0c594cc7c5a404e7006a4b4b2f29200ae (patch) | |
tree | 269b0a3512d9ee97bbe7ef1e0df9ec8697056939 /src/video_core/shader/glsl_decompiler.cpp | |
parent | shader_decode: Implement VMAD and VSETP (diff) | |
download | yuzu-e1fea1e0c594cc7c5a404e7006a4b4b2f29200ae.tar yuzu-e1fea1e0c594cc7c5a404e7006a4b4b2f29200ae.tar.gz yuzu-e1fea1e0c594cc7c5a404e7006a4b4b2f29200ae.tar.bz2 yuzu-e1fea1e0c594cc7c5a404e7006a4b4b2f29200ae.tar.lz yuzu-e1fea1e0c594cc7c5a404e7006a4b4b2f29200ae.tar.xz yuzu-e1fea1e0c594cc7c5a404e7006a4b4b2f29200ae.tar.zst yuzu-e1fea1e0c594cc7c5a404e7006a4b4b2f29200ae.zip |
Diffstat (limited to '')
-rw-r--r-- | src/video_core/shader/glsl_decompiler.cpp | 70 |
1 files changed, 68 insertions, 2 deletions
diff --git a/src/video_core/shader/glsl_decompiler.cpp b/src/video_core/shader/glsl_decompiler.cpp index 2e9323df7..9b443e61a 100644 --- a/src/video_core/shader/glsl_decompiler.cpp +++ b/src/video_core/shader/glsl_decompiler.cpp @@ -89,6 +89,22 @@ static std::string GetSwizzle(u32 elem) { return swizzle; } +/// Translate topology +static std::string GetTopologyName(Tegra::Shader::OutputTopology topology) { + switch (topology) { + case Tegra::Shader::OutputTopology::PointList: + return "points"; + case Tegra::Shader::OutputTopology::LineStrip: + return "line_strip"; + case Tegra::Shader::OutputTopology::TriangleStrip: + return "triangle_strip"; + default: + UNIMPLEMENTED_MSG("Unknown output topology: {}", static_cast<u32>(topology)); + return "points"; + } +} + +/// Returns true if an object has to be treated as precise static bool IsPrecise(Operation operand) { const auto& meta = operand.GetMeta(); @@ -115,6 +131,7 @@ public: void Decompile() { DeclareVertex(); + DeclareGeometry(); DeclareRegisters(); DeclarePredicates(); DeclareLocalMemory(); @@ -212,6 +229,16 @@ private: code.AddNewLine(); } + void DeclareGeometry() { + if (stage != ShaderStage::Geometry) + return; + + const auto topology = GetTopologyName(header.common3.output_topology); + const auto max_vertices = std::to_string(header.common4.max_output_vertices); + code.AddLine("layout (" + topology + ", max_vertices = " + max_vertices + ") out;"); + code.AddNewLine(); + } + void DeclareRegisters() { const auto& registers = ir.GetRegisters(); for (const u32 gpr : registers) { @@ -419,9 +446,24 @@ private: const auto attribute = abuf->GetIndex(); const auto element = abuf->GetElement(); + const auto GeometryPass = [&](const std::string& name) { + if (stage == ShaderStage::Geometry && abuf->GetBuffer()) { + // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games + // set an 0x80000000 index for those and the shader fails to build. Find out why + // this happens and what's its intent. + return "gs_" + name + "[ftou(" + Visit(abuf->GetBuffer()) + + ") % MAX_VERTEX_INPUT]"; + } + return name; + }; + switch (attribute) { case Attribute::Index::Position: - return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element); + if (stage != ShaderStage::Fragment) { + return GeometryPass("position") + GetSwizzle(element); + } else { + return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element); + } case Attribute::Index::PointCoord: switch (element) { case 0: @@ -460,7 +502,7 @@ private: default: if (attribute >= Attribute::Index::Attribute_0 && attribute <= Attribute::Index::Attribute_31) { - return GetInputAttribute(attribute) + GetSwizzle(abuf->GetElement()); + return GeometryPass(GetInputAttribute(attribute)) + GetSwizzle(element); } break; } @@ -1226,6 +1268,27 @@ private: return {}; } + std::string EmitVertex(Operation operation) { + ASSERT_MSG(stage == ShaderStage::Geometry, + "EmitVertex is expected to be used in a geometry shader."); + + // If a geometry shader is attached, it will always flip (it's the last stage before + // fragment). For more info about flipping, refer to gl_shader_gen.cpp. + code.AddLine("position.xy *= viewport_flip.xy;"); + code.AddLine("gl_Position = position;"); + code.AddLine("position.w = 1.0;"); + code.AddLine("EmitVertex();"); + return {}; + } + + std::string EndPrimitive(Operation operation) { + ASSERT_MSG(stage == ShaderStage::Geometry, + "EndPrimitive is expected to be used in a geometry shader."); + + code.AddLine("EndPrimitive();"); + return {}; + } + std::string YNegate(Operation operation) { // Config pack's third value is Y_NEGATE's state. return "uintBitsToFloat(config_pack[2])"; @@ -1361,6 +1424,9 @@ private: &Exit, &Kil, + &EmitVertex, + &EndPrimitive, + &YNegate, }; |