diff options
author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2019-07-15 03:25:13 +0200 |
---|---|---|
committer | ReinUsesLisp <reinuseslisp@airmail.cc> | 2019-07-15 22:38:25 +0200 |
commit | 725ba6cf6336fb0f1be4e5250c15767d60e28259 (patch) | |
tree | ed9c302a2b7735f64b09434469f4e9714122e789 /src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |
parent | Merge pull request #2695 from ReinUsesLisp/layer-viewport (diff) | |
download | yuzu-725ba6cf6336fb0f1be4e5250c15767d60e28259.tar yuzu-725ba6cf6336fb0f1be4e5250c15767d60e28259.tar.gz yuzu-725ba6cf6336fb0f1be4e5250c15767d60e28259.tar.bz2 yuzu-725ba6cf6336fb0f1be4e5250c15767d60e28259.tar.lz yuzu-725ba6cf6336fb0f1be4e5250c15767d60e28259.tar.xz yuzu-725ba6cf6336fb0f1be4e5250c15767d60e28259.tar.zst yuzu-725ba6cf6336fb0f1be4e5250c15767d60e28259.zip |
Diffstat (limited to '')
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 60 |
1 files changed, 34 insertions, 26 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 119073776..6236c5cdd 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -37,7 +37,6 @@ using namespace std::string_literals; using namespace VideoCommon::Shader; 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 }; @@ -162,9 +161,13 @@ std::string FlowStackTopName(MetaStackClass stack) { return fmt::format("{}_flow_stack_top", GetFlowStackPrefix(stack)); } +constexpr bool IsVertexShader(ProgramType stage) { + return stage == ProgramType::VertexA || stage == ProgramType::VertexB; +} + class GLSLDecompiler final { public: - explicit GLSLDecompiler(const Device& device, const ShaderIR& ir, ShaderStage stage, + explicit GLSLDecompiler(const Device& device, const ShaderIR& ir, ProgramType stage, std::string suffix) : device{device}, ir{ir}, stage{stage}, suffix{suffix}, header{ir.GetHeader()} {} @@ -248,7 +251,7 @@ public: } entries.clip_distances = ir.GetClipDistances(); entries.shader_viewport_layer_array = - stage == ShaderStage::Vertex && (ir.UsesLayer() || ir.UsesViewportIndex()); + IsVertexShader(stage) && (ir.UsesLayer() || ir.UsesViewportIndex()); entries.shader_length = ir.GetLength(); return entries; } @@ -259,14 +262,14 @@ private: std::array<OperationDecompilerFn, static_cast<std::size_t>(OperationCode::Amount)>; void DeclareVertex() { - if (stage != ShaderStage::Vertex) + if (!IsVertexShader(stage)) return; DeclareVertexRedeclarations(); } void DeclareGeometry() { - if (stage != ShaderStage::Geometry) { + if (stage != ProgramType::Geometry) { return; } @@ -297,14 +300,14 @@ private: break; } } - if (stage != ShaderStage::Vertex || device.HasVertexViewportLayer()) { + if (!IsVertexShader(stage) || device.HasVertexViewportLayer()) { if (ir.UsesLayer()) { code.AddLine("int gl_Layer;"); } if (ir.UsesViewportIndex()) { code.AddLine("int gl_ViewportIndex;"); } - } else if ((ir.UsesLayer() || ir.UsesViewportIndex()) && stage == ShaderStage::Vertex && + } else if ((ir.UsesLayer() || ir.UsesViewportIndex()) && IsVertexShader(stage) && !device.HasVertexViewportLayer()) { LOG_ERROR( Render_OpenGL, @@ -341,6 +344,9 @@ private: } void DeclareLocalMemory() { + if (stage == ProgramType::Compute) { + return; + } if (const u64 local_memory_size = header.GetLocalMemorySize(); local_memory_size > 0) { const auto element_count = Common::AlignUp(local_memory_size, 4) / 4; code.AddLine("float {}[{}];", GetLocalMemory(), element_count); @@ -399,12 +405,12 @@ private: const u32 location{GetGenericAttributeIndex(index)}; std::string name{GetInputAttribute(index)}; - if (stage == ShaderStage::Geometry) { + if (stage == ProgramType::Geometry) { name = "gs_" + name + "[]"; } std::string suffix; - if (stage == ShaderStage::Fragment) { + if (stage == ProgramType::Fragment) { const auto input_mode{header.ps.GetAttributeUse(location)}; if (skip_unused && input_mode == AttributeUse::Unused) { return; @@ -416,7 +422,7 @@ private: } void DeclareOutputAttributes() { - if (ir.HasPhysicalAttributes() && stage != ShaderStage::Fragment) { + if (ir.HasPhysicalAttributes() && stage != ProgramType::Fragment) { for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) { DeclareOutputAttribute(ToGenericAttribute(i)); } @@ -538,7 +544,7 @@ private: constexpr u32 element_stride{4}; const u32 address{generic_base + index * generic_stride + element * element_stride}; - const bool declared{stage != ShaderStage::Fragment || + const bool declared{stage != ProgramType::Fragment || header.ps.GetAttributeUse(index) != AttributeUse::Unused}; const std::string value{declared ? ReadAttribute(attribute, element) : "0"}; code.AddLine("case 0x{:x}: return {};", address, value); @@ -642,7 +648,7 @@ private: } if (const auto abuf = std::get_if<AbufNode>(&*node)) { - UNIMPLEMENTED_IF_MSG(abuf->IsPhysicalBuffer() && stage == ShaderStage::Geometry, + UNIMPLEMENTED_IF_MSG(abuf->IsPhysicalBuffer() && stage == ProgramType::Geometry, "Physical attributes in geometry shaders are not implemented"); if (abuf->IsPhysicalBuffer()) { return fmt::format("readPhysicalAttribute(ftou({}))", @@ -697,6 +703,7 @@ private: } if (const auto lmem = std::get_if<LmemNode>(&*node)) { + UNIMPLEMENTED_IF(stage == ProgramType::Compute); return fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress())); } @@ -726,7 +733,7 @@ private: std::string ReadAttribute(Attribute::Index attribute, u32 element, const Node& buffer = {}) { const auto GeometryPass = [&](std::string_view name) { - if (stage == ShaderStage::Geometry && buffer) { + if (stage == ProgramType::Geometry && buffer) { // 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. @@ -738,10 +745,10 @@ private: switch (attribute) { case Attribute::Index::Position: switch (stage) { - case ShaderStage::Geometry: + case ProgramType::Geometry: return fmt::format("gl_in[ftou({})].gl_Position{}", Visit(buffer), GetSwizzle(element)); - case ShaderStage::Fragment: + case ProgramType::Fragment: return element == 3 ? "1.0f" : ("gl_FragCoord"s + GetSwizzle(element)); default: UNREACHABLE(); @@ -762,7 +769,7 @@ private: // TODO(Subv): Find out what the values are for the first two elements when inside a // vertex shader, and what's the value of the fourth element when inside a Tess Eval // shader. - ASSERT(stage == ShaderStage::Vertex); + ASSERT(IsVertexShader(stage)); switch (element) { case 2: // Config pack's first value is instance_id. @@ -774,7 +781,7 @@ private: return "0"; case Attribute::Index::FrontFacing: // TODO(Subv): Find out what the values are for the other elements. - ASSERT(stage == ShaderStage::Fragment); + ASSERT(stage == ProgramType::Fragment); switch (element) { case 3: return "itof(gl_FrontFacing ? -1 : 0)"; @@ -796,7 +803,7 @@ private: return value; } // There's a bug in NVidia's proprietary drivers that makes precise fail on fragment shaders - const std::string precise = stage != ShaderStage::Fragment ? "precise " : ""; + const std::string precise = stage != ProgramType::Fragment ? "precise " : ""; const std::string temporary = code.GenerateTemporary(); code.AddLine("{}float {} = {};", precise, temporary, value); @@ -831,12 +838,12 @@ private: UNIMPLEMENTED(); return {}; case 1: - if (stage == ShaderStage::Vertex && !device.HasVertexViewportLayer()) { + if (IsVertexShader(stage) && !device.HasVertexViewportLayer()) { return {}; } return std::make_pair("gl_Layer", true); case 2: - if (stage == ShaderStage::Vertex && !device.HasVertexViewportLayer()) { + if (IsVertexShader(stage) && !device.HasVertexViewportLayer()) { return {}; } return std::make_pair("gl_ViewportIndex", true); @@ -1073,6 +1080,7 @@ private: target = result->first; is_integer = result->second; } else if (const auto lmem = std::get_if<LmemNode>(&*dest)) { + UNIMPLEMENTED_IF(stage == ProgramType::Compute); target = fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress())); } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) { const std::string real = Visit(gmem->GetRealAddress()); @@ -1630,7 +1638,7 @@ private: } std::string Exit(Operation operation) { - if (stage != ShaderStage::Fragment) { + if (stage != ProgramType::Fragment) { code.AddLine("return;"); return {}; } @@ -1681,7 +1689,7 @@ private: } std::string EmitVertex(Operation operation) { - ASSERT_MSG(stage == ShaderStage::Geometry, + ASSERT_MSG(stage == ProgramType::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 @@ -1692,7 +1700,7 @@ private: } std::string EndPrimitive(Operation operation) { - ASSERT_MSG(stage == ShaderStage::Geometry, + ASSERT_MSG(stage == ProgramType::Geometry, "EndPrimitive is expected to be used in a geometry shader."); code.AddLine("EndPrimitive();"); @@ -1927,7 +1935,7 @@ private: } u32 GetNumPhysicalInputAttributes() const { - return stage == ShaderStage::Vertex ? GetNumPhysicalAttributes() : GetNumPhysicalVaryings(); + return IsVertexShader(stage) ? GetNumPhysicalAttributes() : GetNumPhysicalVaryings(); } u32 GetNumPhysicalAttributes() const { @@ -1940,7 +1948,7 @@ private: const Device& device; const ShaderIR& ir; - const ShaderStage stage; + const ProgramType stage; const std::string suffix; const Header header; @@ -1971,7 +1979,7 @@ std::string GetCommonDeclarations() { MAX_CONSTBUFFER_ELEMENTS); } -ProgramResult Decompile(const Device& device, const ShaderIR& ir, Maxwell::ShaderStage stage, +ProgramResult Decompile(const Device& device, const ShaderIR& ir, ProgramType stage, const std::string& suffix) { GLSLDecompiler decompiler(device, ir, stage, suffix); decompiler.Decompile(); |