diff options
Diffstat (limited to 'src/video_core')
-rw-r--r-- | src/video_core/engines/shader_bytecode.h | 6 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 67 | ||||
-rw-r--r-- | src/video_core/shader/decode/xmad.cpp | 9 | ||||
-rw-r--r-- | src/video_core/shader/shader_ir.cpp | 85 | ||||
-rw-r--r-- | src/video_core/shader/shader_ir.h | 8 |
5 files changed, 124 insertions, 51 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index eba42deb4..49dc5abe0 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -82,6 +82,10 @@ union Attribute { Position = 7, Attribute_0 = 8, Attribute_31 = 39, + FrontColor = 40, + FrontSecondaryColor = 41, + BackColor = 42, + BackSecondaryColor = 43, ClipDistances0123 = 44, ClipDistances4567 = 45, PointCoord = 46, @@ -89,6 +93,8 @@ union Attribute { // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval // shader. TessCoordInstanceIDVertexID = 47, + TexCoord_0 = 48, + TexCoord_7 = 55, // This attribute contains a tuple of (Unk, Unk, Unk, gl_FrontFacing) when inside a fragment // shader. It is unknown what the other values contain. FrontFacing = 63, diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 2c38f57fd..8aa4a7ac9 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -366,10 +366,19 @@ constexpr bool IsGenericAttribute(Attribute::Index index) { return index >= Attribute::Index::Attribute_0 && index <= Attribute::Index::Attribute_31; } +constexpr bool IsLegacyTexCoord(Attribute::Index index) { + return static_cast<int>(index) >= static_cast<int>(Attribute::Index::TexCoord_0) && + static_cast<int>(index) <= static_cast<int>(Attribute::Index::TexCoord_7); +} + constexpr Attribute::Index ToGenericAttribute(u64 value) { return static_cast<Attribute::Index>(value + static_cast<u64>(Attribute::Index::Attribute_0)); } +constexpr int GetLegacyTexCoordIndex(Attribute::Index index) { + return static_cast<int>(index) - static_cast<int>(Attribute::Index::TexCoord_0); +} + u32 GetGenericAttributeIndex(Attribute::Index index) { ASSERT(IsGenericAttribute(index)); return static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0); @@ -498,7 +507,7 @@ private: if (!identifier.empty()) { code.AddLine("// {}", identifier); } - code.AddLine("#version 440 core"); + code.AddLine("#version 440 {}", ir.UsesLegacyVaryings() ? "compatibility" : "core"); code.AddLine("#extension GL_ARB_separate_shader_objects : enable"); if (device.HasShaderBallot()) { code.AddLine("#extension GL_ARB_shader_ballot : require"); @@ -561,6 +570,16 @@ private: if (stage != ShaderType::Fragment) { return; } + if (ir.UsesLegacyVaryings()) { + code.AddLine("in gl_PerFragment {{"); + ++code.scope; + code.AddLine("vec4 gl_TexCoord[8];"); + code.AddLine("vec4 gl_Color;"); + code.AddLine("vec4 gl_SecondaryColor;"); + --code.scope; + code.AddLine("}};"); + } + for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { code.AddLine("layout (location = {}) out vec4 frag_color{};", rt, rt); } @@ -617,12 +636,12 @@ private: code.AddLine("float gl_PointSize;"); } - if (ir.UsesInstanceId()) { - code.AddLine("int gl_InstanceID;"); - } - - if (ir.UsesVertexId()) { - code.AddLine("int gl_VertexID;"); + if (ir.UsesLegacyVaryings()) { + code.AddLine("vec4 gl_TexCoord[8];"); + code.AddLine("vec4 gl_FrontColor;"); + code.AddLine("vec4 gl_FrontSecondaryColor;"); + code.AddLine("vec4 gl_BackColor;"); + code.AddLine("vec4 gl_BackSecondaryColor;"); } --code.scope; @@ -1128,6 +1147,10 @@ private: default: UNREACHABLE(); } + case Attribute::Index::FrontColor: + return {"gl_Color"s + GetSwizzle(element), Type::Float}; + case Attribute::Index::FrontSecondaryColor: + return {"gl_SecondaryColor"s + GetSwizzle(element), Type::Float}; case Attribute::Index::PointCoord: switch (element) { case 0: @@ -1168,6 +1191,12 @@ private: return {GeometryPass(GetGenericInputAttribute(attribute)) + GetSwizzle(element), Type::Float}; } + if (IsLegacyTexCoord(attribute)) { + UNIMPLEMENTED_IF(stage == ShaderType::Geometry); + return {fmt::format("gl_TexCoord[{}]{}", GetLegacyTexCoordIndex(attribute), + GetSwizzle(element)), + Type::Float}; + } break; } UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute)); @@ -1206,11 +1235,12 @@ private: } std::optional<Expression> GetOutputAttribute(const AbufNode* abuf) { + const u32 element = abuf->GetElement(); switch (const auto attribute = abuf->GetIndex()) { case Attribute::Index::Position: - return {{"gl_Position"s + GetSwizzle(abuf->GetElement()), Type::Float}}; + return {{"gl_Position"s + GetSwizzle(element), Type::Float}}; case Attribute::Index::LayerViewportPointSize: - switch (abuf->GetElement()) { + switch (element) { case 0: UNIMPLEMENTED(); return {}; @@ -1228,13 +1258,26 @@ private: return {{"gl_PointSize", Type::Float}}; } return {}; + case Attribute::Index::FrontColor: + return {{"gl_FrontColor"s + GetSwizzle(element), Type::Float}}; + case Attribute::Index::FrontSecondaryColor: + return {{"gl_FrontSecondaryColor"s + GetSwizzle(element), Type::Float}}; + case Attribute::Index::BackColor: + return {{"gl_BackColor"s + GetSwizzle(element), Type::Float}}; + case Attribute::Index::BackSecondaryColor: + return {{"gl_BackSecondaryColor"s + GetSwizzle(element), Type::Float}}; case Attribute::Index::ClipDistances0123: - return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement()), Type::Float}}; + return {{fmt::format("gl_ClipDistance[{}]", element), Type::Float}}; case Attribute::Index::ClipDistances4567: - return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4), Type::Float}}; + return {{fmt::format("gl_ClipDistance[{}]", element + 4), Type::Float}}; default: if (IsGenericAttribute(attribute)) { - return {{GetGenericOutputAttribute(attribute, abuf->GetElement()), Type::Float}}; + return {{GetGenericOutputAttribute(attribute, element), Type::Float}}; + } + if (IsLegacyTexCoord(attribute)) { + return {{fmt::format("gl_TexCoord[{}]{}", GetLegacyTexCoordIndex(attribute), + GetSwizzle(element)), + Type::Float}}; } UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute)); return {}; diff --git a/src/video_core/shader/decode/xmad.cpp b/src/video_core/shader/decode/xmad.cpp index fbd7e9a17..6191ffba1 100644 --- a/src/video_core/shader/decode/xmad.cpp +++ b/src/video_core/shader/decode/xmad.cpp @@ -31,7 +31,7 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) { const bool is_signed_b = instr.xmad.sign_b == 1; const bool is_signed_c = is_signed_a; - auto [is_merge, is_psl, is_high_b, mode, op_b, + auto [is_merge, is_psl, is_high_b, mode, op_b_binding, op_c] = [&]() -> std::tuple<bool, bool, bool, Tegra::Shader::XmadMode, Node, Node> { switch (opcode->get().GetId()) { case OpCode::Id::XMAD_CR: @@ -67,9 +67,10 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) { op_a = SignedOperation(OperationCode::IBitfieldExtract, is_signed_a, std::move(op_a), instr.xmad.high_a ? Immediate(16) : Immediate(0), Immediate(16)); - const Node original_b = op_b; - op_b = SignedOperation(OperationCode::IBitfieldExtract, is_signed_b, std::move(op_b), - is_high_b ? Immediate(16) : Immediate(0), Immediate(16)); + const Node original_b = op_b_binding; + const Node op_b = + SignedOperation(OperationCode::IBitfieldExtract, is_signed_b, std::move(op_b_binding), + is_high_b ? Immediate(16) : Immediate(0), Immediate(16)); // we already check sign_a and sign_b is difference or not before so just use one in here. Node product = SignedOperation(OperationCode::IMul, is_signed_a, op_a, op_b); diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 425927777..baf7188d2 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -96,6 +96,7 @@ Node ShaderIR::GetPredicate(bool immediate) { } Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) { + MarkAttributeUsage(index, element); used_input_attributes.emplace(index); return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer)); } @@ -106,42 +107,8 @@ Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_addres } Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { - if (index == Attribute::Index::LayerViewportPointSize) { - switch (element) { - case 0: - UNIMPLEMENTED(); - break; - case 1: - uses_layer = true; - break; - case 2: - uses_viewport_index = true; - break; - case 3: - uses_point_size = true; - break; - } - } - if (index == Attribute::Index::TessCoordInstanceIDVertexID) { - switch (element) { - case 2: - uses_instance_id = true; - break; - case 3: - uses_vertex_id = true; - break; - default: - break; - } - } - if (index == Attribute::Index::ClipDistances0123 || - index == Attribute::Index::ClipDistances4567) { - const auto clip_index = - static_cast<u32>((index == Attribute::Index::ClipDistances4567 ? 1 : 0) + element); - used_clip_distances.at(clip_index) = true; - } + MarkAttributeUsage(index, element); used_output_attributes.insert(index); - return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer)); } @@ -452,6 +419,54 @@ Node ShaderIR::BitfieldInsert(Node base, Node insert, u32 offset, u32 bits) { Immediate(bits)); } +void ShaderIR::MarkAttributeUsage(Attribute::Index index, u64 element) { + switch (index) { + case Attribute::Index::LayerViewportPointSize: + switch (element) { + case 0: + UNIMPLEMENTED(); + break; + case 1: + uses_layer = true; + break; + case 2: + uses_viewport_index = true; + break; + case 3: + uses_point_size = true; + break; + } + break; + case Attribute::Index::TessCoordInstanceIDVertexID: + switch (element) { + case 2: + uses_instance_id = true; + break; + case 3: + uses_vertex_id = true; + break; + } + break; + case Attribute::Index::ClipDistances0123: + case Attribute::Index::ClipDistances4567: { + const u64 clip_index = (index == Attribute::Index::ClipDistances4567 ? 4 : 0) + element; + used_clip_distances.at(clip_index) = true; + break; + } + case Attribute::Index::FrontColor: + case Attribute::Index::FrontSecondaryColor: + case Attribute::Index::BackColor: + case Attribute::Index::BackSecondaryColor: + uses_legacy_varyings = true; + break; + default: + if (index >= Attribute::Index::TexCoord_0 && index <= Attribute::Index::TexCoord_7) { + uses_legacy_varyings = true; + } + break; + } +} + std::size_t ShaderIR::DeclareAmend(Node new_amend) { const std::size_t id = amend_code.size(); amend_code.push_back(new_amend); diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index dde036b40..80fc9b82c 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -137,6 +137,10 @@ public: return uses_vertex_id; } + bool UsesLegacyVaryings() const { + return uses_legacy_varyings; + } + bool UsesWarps() const { return uses_warps; } @@ -343,6 +347,9 @@ private: /// Inserts a sequence of bits from a node Node BitfieldInsert(Node base, Node insert, u32 offset, u32 bits); + /// Marks the usage of a input or output attribute. + void MarkAttributeUsage(Tegra::Shader::Attribute::Index index, u64 element); + void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, const Node4& components); @@ -443,6 +450,7 @@ private: bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes bool uses_instance_id{}; bool uses_vertex_id{}; + bool uses_legacy_varyings{}; bool uses_warps{}; bool uses_indexed_samplers{}; |