diff options
| author | 2020-01-05 15:23:24 -0400 | |
|---|---|---|
| committer | 2020-01-24 16:43:30 -0400 | |
| commit | 603c861532ed1a89254556ff84bbe121bd700765 (patch) | |
| tree | 8bf8f67ff6393ce7b00b04a3b4b2d596cd8eb5bc /src | |
| parent | Shader_IR: Address Feedback (diff) | |
| download | yuzu-603c861532ed1a89254556ff84bbe121bd700765.tar.gz yuzu-603c861532ed1a89254556ff84bbe121bd700765.tar.xz yuzu-603c861532ed1a89254556ff84bbe121bd700765.zip | |
Shader_IR: Implement initial code for tracking indexed samplers.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/shader/node.h | 48 | ||||
| -rw-r--r-- | src/video_core/shader/node_helper.h | 6 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 3 | ||||
| -rw-r--r-- | src/video_core/shader/track.cpp | 82 |
4 files changed, 139 insertions, 0 deletions
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index 075c7d07c..b370df8f9 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -230,6 +230,12 @@ using Node = std::shared_ptr<NodeData>; | |||
| 230 | using Node4 = std::array<Node, 4>; | 230 | using Node4 = std::array<Node, 4>; |
| 231 | using NodeBlock = std::vector<Node>; | 231 | using NodeBlock = std::vector<Node>; |
| 232 | 232 | ||
| 233 | class BindlessSamplerNode; | ||
| 234 | class ArraySamplerNode; | ||
| 235 | |||
| 236 | using TrackSamplerData = std::variant<BindlessSamplerNode, ArraySamplerNode>; | ||
| 237 | using TrackSampler = std::shared_ptr<TrackSamplerData>; | ||
| 238 | |||
| 233 | class Sampler { | 239 | class Sampler { |
| 234 | public: | 240 | public: |
| 235 | /// This constructor is for bound samplers | 241 | /// This constructor is for bound samplers |
| @@ -288,6 +294,48 @@ private: | |||
| 288 | bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. | 294 | bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. |
| 289 | }; | 295 | }; |
| 290 | 296 | ||
| 297 | /// Represents a tracked bindless sampler into a direct const buffer | ||
| 298 | class ArraySamplerNode final { | ||
| 299 | public: | ||
| 300 | explicit ArraySamplerNode(u32 index, u32 base_offset, u32 bindless_var) | ||
| 301 | : index{index}, base_offset{base_offset}, bindless_var{bindless_var} {} | ||
| 302 | |||
| 303 | u32 GetIndex() const { | ||
| 304 | return index; | ||
| 305 | } | ||
| 306 | |||
| 307 | u32 GetBaseOffset() const { | ||
| 308 | return base_offset; | ||
| 309 | } | ||
| 310 | |||
| 311 | u32 GetIndexVar() const { | ||
| 312 | return bindless_var; | ||
| 313 | } | ||
| 314 | |||
| 315 | private: | ||
| 316 | u32 index; | ||
| 317 | u32 base_offset; | ||
| 318 | u32 bindless_var; | ||
| 319 | }; | ||
| 320 | |||
| 321 | /// Represents a tracked bindless sampler into a direct const buffer | ||
| 322 | class BindlessSamplerNode final { | ||
| 323 | public: | ||
| 324 | explicit BindlessSamplerNode(u32 index, u32 offset) : index{index}, offset{offset} {} | ||
| 325 | |||
| 326 | u32 GetIndex() const { | ||
| 327 | return index; | ||
| 328 | } | ||
| 329 | |||
| 330 | u32 GetOffset() const { | ||
| 331 | return offset; | ||
| 332 | } | ||
| 333 | |||
| 334 | private: | ||
| 335 | u32 index; | ||
| 336 | u32 offset; | ||
| 337 | }; | ||
| 338 | |||
| 291 | class Image final { | 339 | class Image final { |
| 292 | public: | 340 | public: |
| 293 | /// This constructor is for bound images | 341 | /// This constructor is for bound images |
diff --git a/src/video_core/shader/node_helper.h b/src/video_core/shader/node_helper.h index 0c2aa749b..11231bbea 100644 --- a/src/video_core/shader/node_helper.h +++ b/src/video_core/shader/node_helper.h | |||
| @@ -45,6 +45,12 @@ Node MakeNode(Args&&... args) { | |||
| 45 | return std::make_shared<NodeData>(T(std::forward<Args>(args)...)); | 45 | return std::make_shared<NodeData>(T(std::forward<Args>(args)...)); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | template <typename T, typename... Args> | ||
| 49 | TrackSampler MakeTrackSampler(Args&&... args) { | ||
| 50 | static_assert(std::is_convertible_v<T, TrackSamplerData>); | ||
| 51 | return std::make_shared<TrackSamplerData>(T(std::forward<Args>(args)...)); | ||
| 52 | } | ||
| 53 | |||
| 48 | template <typename... Args> | 54 | template <typename... Args> |
| 49 | Node Operation(OperationCode code, Args&&... args) { | 55 | Node Operation(OperationCode code, Args&&... args) { |
| 50 | if constexpr (sizeof...(args) == 0) { | 56 | if constexpr (sizeof...(args) == 0) { |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 92c24247d..d85f14c97 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -388,6 +388,9 @@ private: | |||
| 388 | 388 | ||
| 389 | std::tuple<Node, u32, u32> TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; | 389 | std::tuple<Node, u32, u32> TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; |
| 390 | 390 | ||
| 391 | std::tuple<Node, TrackSampler> TrackSampler(Node tracked, const NodeBlock& code, | ||
| 392 | s64 cursor) const; | ||
| 393 | |||
| 391 | std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const; | 394 | std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const; |
| 392 | 395 | ||
| 393 | std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, | 396 | std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, |
diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp index 165c79330..69a677394 100644 --- a/src/video_core/shader/track.cpp +++ b/src/video_core/shader/track.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 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/node.h" |
| 11 | #include "video_core/shader/node_helper.h" | ||
| 11 | #include "video_core/shader/shader_ir.h" | 12 | #include "video_core/shader/shader_ir.h" |
| 12 | 13 | ||
| 13 | namespace VideoCommon::Shader { | 14 | namespace VideoCommon::Shader { |
| @@ -37,6 +38,87 @@ std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor, | |||
| 37 | } | 38 | } |
| 38 | } // Anonymous namespace | 39 | } // Anonymous namespace |
| 39 | 40 | ||
| 41 | std::optional<std::pair<Node, Node>> DecoupleIndirectRead(const OperationNode& operation) { | ||
| 42 | if (operation.GetCode() != OperationCode::UAdd) { | ||
| 43 | return std::nullopt; | ||
| 44 | } | ||
| 45 | Node gpr{}; | ||
| 46 | Node offset{}; | ||
| 47 | if (operation.GetOperandsCount() != 2) { | ||
| 48 | return std::nullopt; | ||
| 49 | } | ||
| 50 | for (std::size_t i = 0; i < operation.GetOperandsCount(); i++) { | ||
| 51 | Node operand = operation[i]; | ||
| 52 | if (std::holds_alternative<ImmediateNode>(*operand)) { | ||
| 53 | offset = operation[i]; | ||
| 54 | } else if (std::holds_alternative<GprNode>(*operand)) { | ||
| 55 | gpr = operation[i]; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | if (offset && gpr) { | ||
| 59 | return {std::make_pair(gpr, offset)}; | ||
| 60 | } | ||
| 61 | return std::nullopt; | ||
| 62 | } | ||
| 63 | |||
| 64 | std::tuple<Node, TrackSampler> ShaderIR::TrackSampler(Node tracked, const NodeBlock& code, | ||
| 65 | s64 cursor) const { | ||
| 66 | if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { | ||
| 67 | // Constant buffer found, test if it's an immediate | ||
| 68 | const auto offset = cbuf->GetOffset(); | ||
| 69 | if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) { | ||
| 70 | auto track = | ||
| 71 | MakeTrackSampler<BindlessSamplerNode>(cbuf->GetIndex(), immediate->GetValue()); | ||
| 72 | return {tracked, track}; | ||
| 73 | } else if (const auto operation = std::get_if<OperationNode>(&*offset)) { | ||
| 74 | auto bound_buffer = locker.ObtainBoundBuffer(); | ||
| 75 | if (!bound_buffer) { | ||
| 76 | return {}; | ||
| 77 | } | ||
| 78 | if (*bound_buffer != cbuf->GetIndex()) { | ||
| 79 | return {}; | ||
| 80 | } | ||
| 81 | auto pair = DecoupleIndirectRead(*operation); | ||
| 82 | if (!pair) { | ||
| 83 | return {}; | ||
| 84 | } | ||
| 85 | auto [gpr, base_offset] = *pair; | ||
| 86 | const auto offset_inm = std::get_if<ImmediateNode>(&*base_offset); | ||
| 87 | // TODO Implement Bindless Index custom variable | ||
| 88 | auto track = | ||
| 89 | MakeTrackSampler<ArraySamplerNode>(cbuf->GetIndex(), offset_inm->GetValue(), 0); | ||
| 90 | return {tracked, track}; | ||
| 91 | } | ||
| 92 | return {}; | ||
| 93 | } | ||
| 94 | if (const auto gpr = std::get_if<GprNode>(&*tracked)) { | ||
| 95 | if (gpr->GetIndex() == Tegra::Shader::Register::ZeroIndex) { | ||
| 96 | return {}; | ||
| 97 | } | ||
| 98 | // Reduce the cursor in one to avoid infinite loops when the instruction sets the same | ||
| 99 | // register that it uses as operand | ||
| 100 | const auto [source, new_cursor] = TrackRegister(gpr, code, cursor - 1); | ||
| 101 | if (!source) { | ||
| 102 | return {}; | ||
| 103 | } | ||
| 104 | return TrackSampler(source, code, new_cursor); | ||
| 105 | } | ||
| 106 | if (const auto operation = std::get_if<OperationNode>(&*tracked)) { | ||
| 107 | for (std::size_t i = operation->GetOperandsCount(); i > 0; --i) { | ||
| 108 | if (auto found = TrackSampler((*operation)[i - 1], code, cursor); std::get<0>(found)) { | ||
| 109 | // Cbuf found in operand. | ||
| 110 | return found; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | return {}; | ||
| 114 | } | ||
| 115 | if (const auto conditional = std::get_if<ConditionalNode>(&*tracked)) { | ||
| 116 | const auto& conditional_code = conditional->GetCode(); | ||
| 117 | return TrackSampler(tracked, conditional_code, static_cast<s64>(conditional_code.size())); | ||
| 118 | } | ||
| 119 | return {}; | ||
| 120 | } | ||
| 121 | |||
| 40 | std::tuple<Node, u32, u32> ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, | 122 | std::tuple<Node, u32, u32> ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, |
| 41 | s64 cursor) const { | 123 | s64 cursor) const { |
| 42 | if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { | 124 | if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { |