summaryrefslogtreecommitdiffstats
path: root/src/video_core/shader
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2019-12-10 13:01:41 +0100
committerGitHub <noreply@github.com>2019-12-10 13:01:41 +0100
commit6edadef96d57cb021d0131929d5a122ae102ad9e (patch)
treee7f42fb2af3b1d83665725db9034d8fb6f3d6c78 /src/video_core/shader
parentMerge pull request #3205 from ReinUsesLisp/vk-device (diff)
parentvk_shader_decompiler: Fix build issues on old gcc versions (diff)
downloadyuzu-6edadef96d57cb021d0131929d5a122ae102ad9e.tar
yuzu-6edadef96d57cb021d0131929d5a122ae102ad9e.tar.gz
yuzu-6edadef96d57cb021d0131929d5a122ae102ad9e.tar.bz2
yuzu-6edadef96d57cb021d0131929d5a122ae102ad9e.tar.lz
yuzu-6edadef96d57cb021d0131929d5a122ae102ad9e.tar.xz
yuzu-6edadef96d57cb021d0131929d5a122ae102ad9e.tar.zst
yuzu-6edadef96d57cb021d0131929d5a122ae102ad9e.zip
Diffstat (limited to '')
-rw-r--r--src/video_core/shader/decode/memory.cpp34
-rw-r--r--src/video_core/shader/decode/other.cpp2
-rw-r--r--src/video_core/shader/decode/warp.cpp3
-rw-r--r--src/video_core/shader/node.h21
-rw-r--r--src/video_core/shader/shader_ir.h5
-rw-r--r--src/video_core/shader/track.cpp1
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;
using Tegra::Shader::Register;
namespace {
+
u32 GetUniformTypeElementsCount(Tegra::Shader::UniformType uniform_type) {
switch (uniform_type) {
case Tegra::Shader::UniformType::Single:
@@ -35,6 +36,7 @@ u32 GetUniformTypeElementsCount(Tegra::Shader::UniformType uniform_type) {
return 1;
}
}
+
} // Anonymous namespace
u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
@@ -196,28 +198,28 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0,
"Unaligned attribute loads are not supported");
- u64 next_element = instr.attribute.fmt20.element;
- auto next_index = static_cast<u64>(instr.attribute.fmt20.index.Value());
+ u64 element = instr.attribute.fmt20.element;
+ auto index = static_cast<u64>(instr.attribute.fmt20.index.Value());
- const auto StoreNextElement = [&](u32 reg_offset) {
- const auto dest = GetOutputAttribute(static_cast<Attribute::Index>(next_index),
- next_element, GetRegister(instr.gpr39));
+ const u32 num_words = static_cast<u32>(instr.attribute.fmt20.size.Value()) + 1;
+ for (u32 reg_offset = 0; reg_offset < num_words; ++reg_offset) {
+ Node dest;
+ if (instr.attribute.fmt20.patch) {
+ const u32 offset = static_cast<u32>(index) * 4 + static_cast<u32>(element);
+ dest = MakeNode<PatchNode>(offset);
+ } else {
+ dest = GetOutputAttribute(static_cast<Attribute::Index>(index), element,
+ GetRegister(instr.gpr39));
+ }
const auto src = GetRegister(instr.gpr0.Value() + reg_offset);
bb.push_back(Operation(OperationCode::Assign, dest, src));
- // Load the next attribute element into the following register. If the element
- // to load goes beyond the vec4 size, load the first element of the next
- // attribute.
- next_element = (next_element + 1) % 4;
- next_index = next_index + (next_element == 0 ? 1 : 0);
- };
-
- const u32 num_words = static_cast<u32>(instr.attribute.fmt20.size.Value()) + 1;
- for (u32 reg_offset = 0; reg_offset < num_words; ++reg_offset) {
- StoreNextElement(reg_offset);
+ // Load the next attribute element into the following register. If the element to load
+ // goes beyond the vec4 size, load the first element of the next attribute.
+ element = (element + 1) % 4;
+ index = index + (element == 0 ? 1 : 0);
}
-
break;
}
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) {
case OpCode::Id::MOV_SYS: {
const Node value = [this, instr] {
switch (instr.sys20) {
+ case SystemVariable::InvocationId:
+ return Operation(OperationCode::InvocationId);
case SystemVariable::Ydirection:
return Operation(OperationCode::YNegate);
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) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);
+ // Signal the backend that this shader uses warp instructions.
+ uses_warps = true;
+
switch (opcode->get().GetId()) {
case OpCode::Id::VOTE: {
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 {
EmitVertex, /// () -> void
EndPrimitive, /// () -> void
+ InvocationId, /// () -> int
YNegate, /// () -> float
LocalInvocationIdX, /// () -> uint
LocalInvocationIdY, /// () -> uint
@@ -213,13 +214,14 @@ class PredicateNode;
class AbufNode;
class CbufNode;
class LmemNode;
+class PatchNode;
class SmemNode;
class GmemNode;
class CommentNode;
-using NodeData =
- std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode,
- PredicateNode, AbufNode, CbufNode, LmemNode, SmemNode, GmemNode, CommentNode>;
+using NodeData = std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode,
+ InternalFlagNode, PredicateNode, AbufNode, PatchNode, CbufNode,
+ LmemNode, SmemNode, GmemNode, CommentNode>;
using Node = std::shared_ptr<NodeData>;
using Node4 = std::array<Node, 4>;
using NodeBlock = std::vector<Node>;
@@ -542,6 +544,19 @@ private:
u32 element{};
};
+/// Patch memory (used to communicate tessellation stages).
+class PatchNode final {
+public:
+ explicit PatchNode(u32 offset) : offset{offset} {}
+
+ u32 GetOffset() const {
+ return offset;
+ }
+
+private:
+ u32 offset{};
+};
+
/// Constant buffer node, usually mapped to uniform buffers in GLSL
class CbufNode final {
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:
return uses_vertex_id;
}
+ bool UsesWarps() const {
+ return uses_warps;
+ }
+
bool HasPhysicalAttributes() const {
return uses_physical_attributes;
}
@@ -415,6 +419,7 @@ private:
bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes
bool uses_instance_id{};
bool uses_vertex_id{};
+ bool uses_warps{};
Tegra::Shader::Header header;
};
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 @@
#include <variant>
#include "common/common_types.h"
+#include "video_core/shader/node.h"
#include "video_core/shader/shader_ir.h"
namespace VideoCommon::Shader {