diff options
| author | 2019-12-10 08:01:41 -0400 | |
|---|---|---|
| committer | 2019-12-10 08:01:41 -0400 | |
| commit | 6edadef96d57cb021d0131929d5a122ae102ad9e (patch) | |
| tree | e7f42fb2af3b1d83665725db9034d8fb6f3d6c78 /src/video_core/shader | |
| parent | Merge pull request #3205 from ReinUsesLisp/vk-device (diff) | |
| parent | vk_shader_decompiler: Fix build issues on old gcc versions (diff) | |
| download | yuzu-6edadef96d57cb021d0131929d5a122ae102ad9e.tar.gz yuzu-6edadef96d57cb021d0131929d5a122ae102ad9e.tar.xz yuzu-6edadef96d57cb021d0131929d5a122ae102ad9e.zip | |
Merge pull request #3208 from ReinUsesLisp/vk-shader-decompiler
vk_shader_decompiler: Add tessellation and misc changes
Diffstat (limited to 'src/video_core/shader')
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 34 | ||||
| -rw-r--r-- | src/video_core/shader/decode/other.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/shader/decode/warp.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 21 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 5 | ||||
| -rw-r--r-- | src/video_core/shader/track.cpp | 1 |
6 files changed, 47 insertions, 19 deletions
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index 335d78146..78e92f52e 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -21,6 +21,7 @@ using Tegra::Shader::OpCode; | |||
| 21 | using Tegra::Shader::Register; | 21 | using Tegra::Shader::Register; |
| 22 | 22 | ||
| 23 | namespace { | 23 | namespace { |
| 24 | |||
| 24 | u32 GetUniformTypeElementsCount(Tegra::Shader::UniformType uniform_type) { | 25 | u32 GetUniformTypeElementsCount(Tegra::Shader::UniformType uniform_type) { |
| 25 | switch (uniform_type) { | 26 | switch (uniform_type) { |
| 26 | case Tegra::Shader::UniformType::Single: | 27 | case Tegra::Shader::UniformType::Single: |
| @@ -35,6 +36,7 @@ u32 GetUniformTypeElementsCount(Tegra::Shader::UniformType uniform_type) { | |||
| 35 | return 1; | 36 | return 1; |
| 36 | } | 37 | } |
| 37 | } | 38 | } |
| 39 | |||
| 38 | } // Anonymous namespace | 40 | } // Anonymous namespace |
| 39 | 41 | ||
| 40 | u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | 42 | u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { |
| @@ -196,28 +198,28 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 196 | UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, | 198 | UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, |
| 197 | "Unaligned attribute loads are not supported"); | 199 | "Unaligned attribute loads are not supported"); |
| 198 | 200 | ||
| 199 | u64 next_element = instr.attribute.fmt20.element; | 201 | u64 element = instr.attribute.fmt20.element; |
| 200 | auto next_index = static_cast<u64>(instr.attribute.fmt20.index.Value()); | 202 | auto index = static_cast<u64>(instr.attribute.fmt20.index.Value()); |
| 201 | 203 | ||
| 202 | const auto StoreNextElement = [&](u32 reg_offset) { | 204 | const u32 num_words = static_cast<u32>(instr.attribute.fmt20.size.Value()) + 1; |
| 203 | const auto dest = GetOutputAttribute(static_cast<Attribute::Index>(next_index), | 205 | for (u32 reg_offset = 0; reg_offset < num_words; ++reg_offset) { |
| 204 | next_element, GetRegister(instr.gpr39)); | 206 | Node dest; |
| 207 | if (instr.attribute.fmt20.patch) { | ||
| 208 | const u32 offset = static_cast<u32>(index) * 4 + static_cast<u32>(element); | ||
| 209 | dest = MakeNode<PatchNode>(offset); | ||
| 210 | } else { | ||
| 211 | dest = GetOutputAttribute(static_cast<Attribute::Index>(index), element, | ||
| 212 | GetRegister(instr.gpr39)); | ||
| 213 | } | ||
| 205 | const auto src = GetRegister(instr.gpr0.Value() + reg_offset); | 214 | const auto src = GetRegister(instr.gpr0.Value() + reg_offset); |
| 206 | 215 | ||
| 207 | bb.push_back(Operation(OperationCode::Assign, dest, src)); | 216 | bb.push_back(Operation(OperationCode::Assign, dest, src)); |
| 208 | 217 | ||
| 209 | // Load the next attribute element into the following register. If the element | 218 | // Load the next attribute element into the following register. If the element to load |
| 210 | // to load goes beyond the vec4 size, load the first element of the next | 219 | // goes beyond the vec4 size, load the first element of the next attribute. |
| 211 | // attribute. | 220 | element = (element + 1) % 4; |
| 212 | next_element = (next_element + 1) % 4; | 221 | index = index + (element == 0 ? 1 : 0); |
| 213 | next_index = next_index + (next_element == 0 ? 1 : 0); | ||
| 214 | }; | ||
| 215 | |||
| 216 | const u32 num_words = static_cast<u32>(instr.attribute.fmt20.size.Value()) + 1; | ||
| 217 | for (u32 reg_offset = 0; reg_offset < num_words; ++reg_offset) { | ||
| 218 | StoreNextElement(reg_offset); | ||
| 219 | } | 222 | } |
| 220 | |||
| 221 | break; | 223 | break; |
| 222 | } | 224 | } |
| 223 | case OpCode::Id::ST_L: | 225 | case OpCode::Id::ST_L: |
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index 17cd45d3c..5c802886b 100644 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp | |||
| @@ -69,6 +69,8 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 69 | case OpCode::Id::MOV_SYS: { | 69 | case OpCode::Id::MOV_SYS: { |
| 70 | const Node value = [this, instr] { | 70 | const Node value = [this, instr] { |
| 71 | switch (instr.sys20) { | 71 | switch (instr.sys20) { |
| 72 | case SystemVariable::InvocationId: | ||
| 73 | return Operation(OperationCode::InvocationId); | ||
| 72 | case SystemVariable::Ydirection: | 74 | case SystemVariable::Ydirection: |
| 73 | return Operation(OperationCode::YNegate); | 75 | return Operation(OperationCode::YNegate); |
| 74 | case SystemVariable::InvocationInfo: | 76 | case SystemVariable::InvocationInfo: |
diff --git a/src/video_core/shader/decode/warp.cpp b/src/video_core/shader/decode/warp.cpp index d98d0e1dd..11b77f795 100644 --- a/src/video_core/shader/decode/warp.cpp +++ b/src/video_core/shader/decode/warp.cpp | |||
| @@ -38,6 +38,9 @@ u32 ShaderIR::DecodeWarp(NodeBlock& bb, u32 pc) { | |||
| 38 | const Instruction instr = {program_code[pc]}; | 38 | const Instruction instr = {program_code[pc]}; |
| 39 | const auto opcode = OpCode::Decode(instr); | 39 | const auto opcode = OpCode::Decode(instr); |
| 40 | 40 | ||
| 41 | // Signal the backend that this shader uses warp instructions. | ||
| 42 | uses_warps = true; | ||
| 43 | |||
| 41 | switch (opcode->get().GetId()) { | 44 | switch (opcode->get().GetId()) { |
| 42 | case OpCode::Id::VOTE: { | 45 | case OpCode::Id::VOTE: { |
| 43 | const Node value = GetPredicate(instr.vote.value, instr.vote.negate_value != 0); | 46 | const Node value = GetPredicate(instr.vote.value, instr.vote.negate_value != 0); |
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index b2576bdd6..1a4d28ae9 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -172,6 +172,7 @@ enum class OperationCode { | |||
| 172 | EmitVertex, /// () -> void | 172 | EmitVertex, /// () -> void |
| 173 | EndPrimitive, /// () -> void | 173 | EndPrimitive, /// () -> void |
| 174 | 174 | ||
| 175 | InvocationId, /// () -> int | ||
| 175 | YNegate, /// () -> float | 176 | YNegate, /// () -> float |
| 176 | LocalInvocationIdX, /// () -> uint | 177 | LocalInvocationIdX, /// () -> uint |
| 177 | LocalInvocationIdY, /// () -> uint | 178 | LocalInvocationIdY, /// () -> uint |
| @@ -213,13 +214,14 @@ class PredicateNode; | |||
| 213 | class AbufNode; | 214 | class AbufNode; |
| 214 | class CbufNode; | 215 | class CbufNode; |
| 215 | class LmemNode; | 216 | class LmemNode; |
| 217 | class PatchNode; | ||
| 216 | class SmemNode; | 218 | class SmemNode; |
| 217 | class GmemNode; | 219 | class GmemNode; |
| 218 | class CommentNode; | 220 | class CommentNode; |
| 219 | 221 | ||
| 220 | using NodeData = | 222 | using NodeData = std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, |
| 221 | std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode, | 223 | InternalFlagNode, PredicateNode, AbufNode, PatchNode, CbufNode, |
| 222 | PredicateNode, AbufNode, CbufNode, LmemNode, SmemNode, GmemNode, CommentNode>; | 224 | LmemNode, SmemNode, GmemNode, CommentNode>; |
| 223 | using Node = std::shared_ptr<NodeData>; | 225 | using Node = std::shared_ptr<NodeData>; |
| 224 | using Node4 = std::array<Node, 4>; | 226 | using Node4 = std::array<Node, 4>; |
| 225 | using NodeBlock = std::vector<Node>; | 227 | using NodeBlock = std::vector<Node>; |
| @@ -542,6 +544,19 @@ private: | |||
| 542 | u32 element{}; | 544 | u32 element{}; |
| 543 | }; | 545 | }; |
| 544 | 546 | ||
| 547 | /// Patch memory (used to communicate tessellation stages). | ||
| 548 | class PatchNode final { | ||
| 549 | public: | ||
| 550 | explicit PatchNode(u32 offset) : offset{offset} {} | ||
| 551 | |||
| 552 | u32 GetOffset() const { | ||
| 553 | return offset; | ||
| 554 | } | ||
| 555 | |||
| 556 | private: | ||
| 557 | u32 offset{}; | ||
| 558 | }; | ||
| 559 | |||
| 545 | /// Constant buffer node, usually mapped to uniform buffers in GLSL | 560 | /// Constant buffer node, usually mapped to uniform buffers in GLSL |
| 546 | class CbufNode final { | 561 | class CbufNode final { |
| 547 | public: | 562 | public: |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 2f71a50d2..580f84fcb 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -137,6 +137,10 @@ public: | |||
| 137 | return uses_vertex_id; | 137 | return uses_vertex_id; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | bool UsesWarps() const { | ||
| 141 | return uses_warps; | ||
| 142 | } | ||
| 143 | |||
| 140 | bool HasPhysicalAttributes() const { | 144 | bool HasPhysicalAttributes() const { |
| 141 | return uses_physical_attributes; | 145 | return uses_physical_attributes; |
| 142 | } | 146 | } |
| @@ -415,6 +419,7 @@ private: | |||
| 415 | bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes | 419 | bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes |
| 416 | bool uses_instance_id{}; | 420 | bool uses_instance_id{}; |
| 417 | bool uses_vertex_id{}; | 421 | bool uses_vertex_id{}; |
| 422 | bool uses_warps{}; | ||
| 418 | 423 | ||
| 419 | Tegra::Shader::Header header; | 424 | Tegra::Shader::Header header; |
| 420 | }; | 425 | }; |
diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp index 55f5949e4..165c79330 100644 --- a/src/video_core/shader/track.cpp +++ b/src/video_core/shader/track.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <variant> | 7 | #include <variant> |
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "video_core/shader/node.h" | ||
| 10 | #include "video_core/shader/shader_ir.h" | 11 | #include "video_core/shader/shader_ir.h" |
| 11 | 12 | ||
| 12 | namespace VideoCommon::Shader { | 13 | namespace VideoCommon::Shader { |