diff options
| author | 2019-06-06 22:31:46 -0400 | |
|---|---|---|
| committer | 2019-06-06 22:31:46 -0400 | |
| commit | cd2d9628c99db1944b44b5699bfc40bee582301d (patch) | |
| tree | e395a8a535f94b31cfb72f415065b1bf65139bbe /src | |
| parent | Merge pull request #2552 from ReinUsesLisp/shader-shared-ptr (diff) | |
| parent | cmake: Add missing shader hash file entries (diff) | |
| download | yuzu-cd2d9628c99db1944b44b5699bfc40bee582301d.tar.gz yuzu-cd2d9628c99db1944b44b5699bfc40bee582301d.tar.xz yuzu-cd2d9628c99db1944b44b5699bfc40bee582301d.zip | |
Merge pull request #2558 from ReinUsesLisp/shader-nodes
shader: Move Node declarations out of the shader IR header
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/video_core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 514 | ||||
| -rw-r--r-- | src/video_core/shader/node_helper.h | 7 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 493 |
5 files changed, 525 insertions, 493 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index cb514a0d2..198b3fe07 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -56,6 +56,9 @@ add_custom_command(OUTPUT scm_rev.cpp | |||
| 56 | "${VIDEO_CORE}/shader/decode/video.cpp" | 56 | "${VIDEO_CORE}/shader/decode/video.cpp" |
| 57 | "${VIDEO_CORE}/shader/decode/xmad.cpp" | 57 | "${VIDEO_CORE}/shader/decode/xmad.cpp" |
| 58 | "${VIDEO_CORE}/shader/decode.cpp" | 58 | "${VIDEO_CORE}/shader/decode.cpp" |
| 59 | "${VIDEO_CORE}/shader/node.h" | ||
| 60 | "${VIDEO_CORE}/shader/node_helper.cpp" | ||
| 61 | "${VIDEO_CORE}/shader/node_helper.h" | ||
| 59 | "${VIDEO_CORE}/shader/shader_ir.cpp" | 62 | "${VIDEO_CORE}/shader/shader_ir.cpp" |
| 60 | "${VIDEO_CORE}/shader/shader_ir.h" | 63 | "${VIDEO_CORE}/shader/shader_ir.h" |
| 61 | "${VIDEO_CORE}/shader/track.cpp" | 64 | "${VIDEO_CORE}/shader/track.cpp" |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index fa80c3814..24ce47682 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -104,6 +104,7 @@ add_library(video_core STATIC | |||
| 104 | shader/decode.cpp | 104 | shader/decode.cpp |
| 105 | shader/node_helper.cpp | 105 | shader/node_helper.cpp |
| 106 | shader/node_helper.h | 106 | shader/node_helper.h |
| 107 | shader/node.h | ||
| 107 | shader/shader_ir.cpp | 108 | shader/shader_ir.cpp |
| 108 | shader/shader_ir.h | 109 | shader/shader_ir.h |
| 109 | shader/track.cpp | 110 | shader/track.cpp |
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h new file mode 100644 index 000000000..c002f90f9 --- /dev/null +++ b/src/video_core/shader/node.h | |||
| @@ -0,0 +1,514 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <cstddef> | ||
| 9 | #include <memory> | ||
| 10 | #include <string> | ||
| 11 | #include <tuple> | ||
| 12 | #include <utility> | ||
| 13 | #include <variant> | ||
| 14 | #include <vector> | ||
| 15 | |||
| 16 | #include "common/common_types.h" | ||
| 17 | #include "video_core/engines/shader_bytecode.h" | ||
| 18 | |||
| 19 | namespace VideoCommon::Shader { | ||
| 20 | |||
| 21 | enum class OperationCode { | ||
| 22 | Assign, /// (float& dest, float src) -> void | ||
| 23 | |||
| 24 | Select, /// (MetaArithmetic, bool pred, float a, float b) -> float | ||
| 25 | |||
| 26 | FAdd, /// (MetaArithmetic, float a, float b) -> float | ||
| 27 | FMul, /// (MetaArithmetic, float a, float b) -> float | ||
| 28 | FDiv, /// (MetaArithmetic, float a, float b) -> float | ||
| 29 | FFma, /// (MetaArithmetic, float a, float b, float c) -> float | ||
| 30 | FNegate, /// (MetaArithmetic, float a) -> float | ||
| 31 | FAbsolute, /// (MetaArithmetic, float a) -> float | ||
| 32 | FClamp, /// (MetaArithmetic, float value, float min, float max) -> float | ||
| 33 | FMin, /// (MetaArithmetic, float a, float b) -> float | ||
| 34 | FMax, /// (MetaArithmetic, float a, float b) -> float | ||
| 35 | FCos, /// (MetaArithmetic, float a) -> float | ||
| 36 | FSin, /// (MetaArithmetic, float a) -> float | ||
| 37 | FExp2, /// (MetaArithmetic, float a) -> float | ||
| 38 | FLog2, /// (MetaArithmetic, float a) -> float | ||
| 39 | FInverseSqrt, /// (MetaArithmetic, float a) -> float | ||
| 40 | FSqrt, /// (MetaArithmetic, float a) -> float | ||
| 41 | FRoundEven, /// (MetaArithmetic, float a) -> float | ||
| 42 | FFloor, /// (MetaArithmetic, float a) -> float | ||
| 43 | FCeil, /// (MetaArithmetic, float a) -> float | ||
| 44 | FTrunc, /// (MetaArithmetic, float a) -> float | ||
| 45 | FCastInteger, /// (MetaArithmetic, int a) -> float | ||
| 46 | FCastUInteger, /// (MetaArithmetic, uint a) -> float | ||
| 47 | |||
| 48 | IAdd, /// (MetaArithmetic, int a, int b) -> int | ||
| 49 | IMul, /// (MetaArithmetic, int a, int b) -> int | ||
| 50 | IDiv, /// (MetaArithmetic, int a, int b) -> int | ||
| 51 | INegate, /// (MetaArithmetic, int a) -> int | ||
| 52 | IAbsolute, /// (MetaArithmetic, int a) -> int | ||
| 53 | IMin, /// (MetaArithmetic, int a, int b) -> int | ||
| 54 | IMax, /// (MetaArithmetic, int a, int b) -> int | ||
| 55 | ICastFloat, /// (MetaArithmetic, float a) -> int | ||
| 56 | ICastUnsigned, /// (MetaArithmetic, uint a) -> int | ||
| 57 | ILogicalShiftLeft, /// (MetaArithmetic, int a, uint b) -> int | ||
| 58 | ILogicalShiftRight, /// (MetaArithmetic, int a, uint b) -> int | ||
| 59 | IArithmeticShiftRight, /// (MetaArithmetic, int a, uint b) -> int | ||
| 60 | IBitwiseAnd, /// (MetaArithmetic, int a, int b) -> int | ||
| 61 | IBitwiseOr, /// (MetaArithmetic, int a, int b) -> int | ||
| 62 | IBitwiseXor, /// (MetaArithmetic, int a, int b) -> int | ||
| 63 | IBitwiseNot, /// (MetaArithmetic, int a) -> int | ||
| 64 | IBitfieldInsert, /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int | ||
| 65 | IBitfieldExtract, /// (MetaArithmetic, int value, int offset, int offset) -> int | ||
| 66 | IBitCount, /// (MetaArithmetic, int) -> int | ||
| 67 | |||
| 68 | UAdd, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 69 | UMul, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 70 | UDiv, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 71 | UMin, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 72 | UMax, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 73 | UCastFloat, /// (MetaArithmetic, float a) -> uint | ||
| 74 | UCastSigned, /// (MetaArithmetic, int a) -> uint | ||
| 75 | ULogicalShiftLeft, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 76 | ULogicalShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 77 | UArithmeticShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 78 | UBitwiseAnd, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 79 | UBitwiseOr, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 80 | UBitwiseXor, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 81 | UBitwiseNot, /// (MetaArithmetic, uint a) -> uint | ||
| 82 | UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint | ||
| 83 | UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint | ||
| 84 | UBitCount, /// (MetaArithmetic, uint) -> uint | ||
| 85 | |||
| 86 | HAdd, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 | ||
| 87 | HMul, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 | ||
| 88 | HFma, /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2 | ||
| 89 | HAbsolute, /// (f16vec2 a) -> f16vec2 | ||
| 90 | HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2 | ||
| 91 | HClamp, /// (f16vec2 src, float min, float max) -> f16vec2 | ||
| 92 | HUnpack, /// (Tegra::Shader::HalfType, T value) -> f16vec2 | ||
| 93 | HMergeF32, /// (f16vec2 src) -> float | ||
| 94 | HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2 | ||
| 95 | HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2 | ||
| 96 | HPack2, /// (float a, float b) -> f16vec2 | ||
| 97 | |||
| 98 | LogicalAssign, /// (bool& dst, bool src) -> void | ||
| 99 | LogicalAnd, /// (bool a, bool b) -> bool | ||
| 100 | LogicalOr, /// (bool a, bool b) -> bool | ||
| 101 | LogicalXor, /// (bool a, bool b) -> bool | ||
| 102 | LogicalNegate, /// (bool a) -> bool | ||
| 103 | LogicalPick2, /// (bool2 pair, uint index) -> bool | ||
| 104 | LogicalAll2, /// (bool2 a) -> bool | ||
| 105 | LogicalAny2, /// (bool2 a) -> bool | ||
| 106 | |||
| 107 | LogicalFLessThan, /// (float a, float b) -> bool | ||
| 108 | LogicalFEqual, /// (float a, float b) -> bool | ||
| 109 | LogicalFLessEqual, /// (float a, float b) -> bool | ||
| 110 | LogicalFGreaterThan, /// (float a, float b) -> bool | ||
| 111 | LogicalFNotEqual, /// (float a, float b) -> bool | ||
| 112 | LogicalFGreaterEqual, /// (float a, float b) -> bool | ||
| 113 | LogicalFIsNan, /// (float a) -> bool | ||
| 114 | |||
| 115 | LogicalILessThan, /// (int a, int b) -> bool | ||
| 116 | LogicalIEqual, /// (int a, int b) -> bool | ||
| 117 | LogicalILessEqual, /// (int a, int b) -> bool | ||
| 118 | LogicalIGreaterThan, /// (int a, int b) -> bool | ||
| 119 | LogicalINotEqual, /// (int a, int b) -> bool | ||
| 120 | LogicalIGreaterEqual, /// (int a, int b) -> bool | ||
| 121 | |||
| 122 | LogicalULessThan, /// (uint a, uint b) -> bool | ||
| 123 | LogicalUEqual, /// (uint a, uint b) -> bool | ||
| 124 | LogicalULessEqual, /// (uint a, uint b) -> bool | ||
| 125 | LogicalUGreaterThan, /// (uint a, uint b) -> bool | ||
| 126 | LogicalUNotEqual, /// (uint a, uint b) -> bool | ||
| 127 | LogicalUGreaterEqual, /// (uint a, uint b) -> bool | ||
| 128 | |||
| 129 | Logical2HLessThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 130 | Logical2HEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 131 | Logical2HLessEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 132 | Logical2HGreaterThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 133 | Logical2HNotEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 134 | Logical2HGreaterEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 135 | Logical2HLessThanWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 136 | Logical2HEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 137 | Logical2HLessEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 138 | Logical2HGreaterThanWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 139 | Logical2HNotEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 140 | Logical2HGreaterEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 141 | |||
| 142 | Texture, /// (MetaTexture, float[N] coords) -> float4 | ||
| 143 | TextureLod, /// (MetaTexture, float[N] coords) -> float4 | ||
| 144 | TextureGather, /// (MetaTexture, float[N] coords) -> float4 | ||
| 145 | TextureQueryDimensions, /// (MetaTexture, float a) -> float4 | ||
| 146 | TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4 | ||
| 147 | TexelFetch, /// (MetaTexture, int[N], int) -> float4 | ||
| 148 | |||
| 149 | Branch, /// (uint branch_target) -> void | ||
| 150 | PushFlowStack, /// (uint branch_target) -> void | ||
| 151 | PopFlowStack, /// () -> void | ||
| 152 | Exit, /// () -> void | ||
| 153 | Discard, /// () -> void | ||
| 154 | |||
| 155 | EmitVertex, /// () -> void | ||
| 156 | EndPrimitive, /// () -> void | ||
| 157 | |||
| 158 | YNegate, /// () -> float | ||
| 159 | LocalInvocationIdX, /// () -> uint | ||
| 160 | LocalInvocationIdY, /// () -> uint | ||
| 161 | LocalInvocationIdZ, /// () -> uint | ||
| 162 | WorkGroupIdX, /// () -> uint | ||
| 163 | WorkGroupIdY, /// () -> uint | ||
| 164 | WorkGroupIdZ, /// () -> uint | ||
| 165 | |||
| 166 | Amount, | ||
| 167 | }; | ||
| 168 | |||
| 169 | enum class InternalFlag { | ||
| 170 | Zero = 0, | ||
| 171 | Sign = 1, | ||
| 172 | Carry = 2, | ||
| 173 | Overflow = 3, | ||
| 174 | Amount = 4, | ||
| 175 | }; | ||
| 176 | |||
| 177 | class OperationNode; | ||
| 178 | class ConditionalNode; | ||
| 179 | class GprNode; | ||
| 180 | class ImmediateNode; | ||
| 181 | class InternalFlagNode; | ||
| 182 | class PredicateNode; | ||
| 183 | class AbufNode; | ||
| 184 | class CbufNode; | ||
| 185 | class LmemNode; | ||
| 186 | class GmemNode; | ||
| 187 | class CommentNode; | ||
| 188 | |||
| 189 | using NodeData = | ||
| 190 | std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode, | ||
| 191 | PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>; | ||
| 192 | using Node = std::shared_ptr<NodeData>; | ||
| 193 | using Node4 = std::array<Node, 4>; | ||
| 194 | using NodeBlock = std::vector<Node>; | ||
| 195 | |||
| 196 | class Sampler { | ||
| 197 | public: | ||
| 198 | /// This constructor is for bound samplers | ||
| 199 | explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, | ||
| 200 | bool is_array, bool is_shadow) | ||
| 201 | : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, | ||
| 202 | is_bindless{false} {} | ||
| 203 | |||
| 204 | /// This constructor is for bindless samplers | ||
| 205 | explicit Sampler(u32 cbuf_index, u32 cbuf_offset, std::size_t index, | ||
| 206 | Tegra::Shader::TextureType type, bool is_array, bool is_shadow) | ||
| 207 | : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, | ||
| 208 | is_array{is_array}, is_shadow{is_shadow}, is_bindless{true} {} | ||
| 209 | |||
| 210 | /// This constructor is for serialization/deserialization | ||
| 211 | explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, | ||
| 212 | bool is_array, bool is_shadow, bool is_bindless) | ||
| 213 | : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, | ||
| 214 | is_bindless{is_bindless} {} | ||
| 215 | |||
| 216 | std::size_t GetOffset() const { | ||
| 217 | return offset; | ||
| 218 | } | ||
| 219 | |||
| 220 | std::size_t GetIndex() const { | ||
| 221 | return index; | ||
| 222 | } | ||
| 223 | |||
| 224 | Tegra::Shader::TextureType GetType() const { | ||
| 225 | return type; | ||
| 226 | } | ||
| 227 | |||
| 228 | bool IsArray() const { | ||
| 229 | return is_array; | ||
| 230 | } | ||
| 231 | |||
| 232 | bool IsShadow() const { | ||
| 233 | return is_shadow; | ||
| 234 | } | ||
| 235 | |||
| 236 | bool IsBindless() const { | ||
| 237 | return is_bindless; | ||
| 238 | } | ||
| 239 | |||
| 240 | std::pair<u32, u32> GetBindlessCBuf() const { | ||
| 241 | return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)}; | ||
| 242 | } | ||
| 243 | |||
| 244 | bool operator<(const Sampler& rhs) const { | ||
| 245 | return std::tie(index, offset, type, is_array, is_shadow, is_bindless) < | ||
| 246 | std::tie(rhs.index, rhs.offset, rhs.type, rhs.is_array, rhs.is_shadow, | ||
| 247 | rhs.is_bindless); | ||
| 248 | } | ||
| 249 | |||
| 250 | private: | ||
| 251 | /// Offset in TSC memory from which to read the sampler object, as specified by the sampling | ||
| 252 | /// instruction. | ||
| 253 | std::size_t offset{}; | ||
| 254 | std::size_t index{}; ///< Value used to index into the generated GLSL sampler array. | ||
| 255 | Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) | ||
| 256 | bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. | ||
| 257 | bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. | ||
| 258 | bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. | ||
| 259 | }; | ||
| 260 | |||
| 261 | struct GlobalMemoryBase { | ||
| 262 | u32 cbuf_index{}; | ||
| 263 | u32 cbuf_offset{}; | ||
| 264 | |||
| 265 | bool operator<(const GlobalMemoryBase& rhs) const { | ||
| 266 | return std::tie(cbuf_index, cbuf_offset) < std::tie(rhs.cbuf_index, rhs.cbuf_offset); | ||
| 267 | } | ||
| 268 | }; | ||
| 269 | |||
| 270 | /// Parameters describing an arithmetic operation | ||
| 271 | struct MetaArithmetic { | ||
| 272 | bool precise{}; ///< Whether the operation can be constraint or not | ||
| 273 | }; | ||
| 274 | |||
| 275 | /// Parameters describing a texture sampler | ||
| 276 | struct MetaTexture { | ||
| 277 | const Sampler& sampler; | ||
| 278 | Node array; | ||
| 279 | Node depth_compare; | ||
| 280 | std::vector<Node> aoffi; | ||
| 281 | Node bias; | ||
| 282 | Node lod; | ||
| 283 | Node component{}; | ||
| 284 | u32 element{}; | ||
| 285 | }; | ||
| 286 | |||
| 287 | /// Parameters that modify an operation but are not part of any particular operand | ||
| 288 | using Meta = std::variant<MetaArithmetic, MetaTexture, Tegra::Shader::HalfType>; | ||
| 289 | |||
| 290 | /// Holds any kind of operation that can be done in the IR | ||
| 291 | class OperationNode final { | ||
| 292 | public: | ||
| 293 | explicit OperationNode(OperationCode code) : OperationNode(code, Meta{}) {} | ||
| 294 | |||
| 295 | explicit OperationNode(OperationCode code, Meta meta) | ||
| 296 | : OperationNode(code, meta, std::vector<Node>{}) {} | ||
| 297 | |||
| 298 | explicit OperationNode(OperationCode code, std::vector<Node> operands) | ||
| 299 | : OperationNode(code, Meta{}, std::move(operands)) {} | ||
| 300 | |||
| 301 | explicit OperationNode(OperationCode code, Meta meta, std::vector<Node> operands) | ||
| 302 | : code{code}, meta{std::move(meta)}, operands{std::move(operands)} {} | ||
| 303 | |||
| 304 | template <typename... Args> | ||
| 305 | explicit OperationNode(OperationCode code, Meta meta, Args&&... operands) | ||
| 306 | : code{code}, meta{std::move(meta)}, operands{operands...} {} | ||
| 307 | |||
| 308 | OperationCode GetCode() const { | ||
| 309 | return code; | ||
| 310 | } | ||
| 311 | |||
| 312 | const Meta& GetMeta() const { | ||
| 313 | return meta; | ||
| 314 | } | ||
| 315 | |||
| 316 | std::size_t GetOperandsCount() const { | ||
| 317 | return operands.size(); | ||
| 318 | } | ||
| 319 | |||
| 320 | const Node& operator[](std::size_t operand_index) const { | ||
| 321 | return operands.at(operand_index); | ||
| 322 | } | ||
| 323 | |||
| 324 | private: | ||
| 325 | OperationCode code{}; | ||
| 326 | Meta meta{}; | ||
| 327 | std::vector<Node> operands; | ||
| 328 | }; | ||
| 329 | |||
| 330 | /// Encloses inside any kind of node that returns a boolean conditionally-executed code | ||
| 331 | class ConditionalNode final { | ||
| 332 | public: | ||
| 333 | explicit ConditionalNode(Node condition, std::vector<Node>&& code) | ||
| 334 | : condition{std::move(condition)}, code{std::move(code)} {} | ||
| 335 | |||
| 336 | const Node& GetCondition() const { | ||
| 337 | return condition; | ||
| 338 | } | ||
| 339 | |||
| 340 | const std::vector<Node>& GetCode() const { | ||
| 341 | return code; | ||
| 342 | } | ||
| 343 | |||
| 344 | private: | ||
| 345 | Node condition; ///< Condition to be satisfied | ||
| 346 | std::vector<Node> code; ///< Code to execute | ||
| 347 | }; | ||
| 348 | |||
| 349 | /// A general purpose register | ||
| 350 | class GprNode final { | ||
| 351 | public: | ||
| 352 | explicit constexpr GprNode(Tegra::Shader::Register index) : index{index} {} | ||
| 353 | |||
| 354 | u32 GetIndex() const { | ||
| 355 | return static_cast<u32>(index); | ||
| 356 | } | ||
| 357 | |||
| 358 | private: | ||
| 359 | Tegra::Shader::Register index{}; | ||
| 360 | }; | ||
| 361 | |||
| 362 | /// A 32-bits value that represents an immediate value | ||
| 363 | class ImmediateNode final { | ||
| 364 | public: | ||
| 365 | explicit constexpr ImmediateNode(u32 value) : value{value} {} | ||
| 366 | |||
| 367 | u32 GetValue() const { | ||
| 368 | return value; | ||
| 369 | } | ||
| 370 | |||
| 371 | private: | ||
| 372 | u32 value{}; | ||
| 373 | }; | ||
| 374 | |||
| 375 | /// One of Maxwell's internal flags | ||
| 376 | class InternalFlagNode final { | ||
| 377 | public: | ||
| 378 | explicit constexpr InternalFlagNode(InternalFlag flag) : flag{flag} {} | ||
| 379 | |||
| 380 | InternalFlag GetFlag() const { | ||
| 381 | return flag; | ||
| 382 | } | ||
| 383 | |||
| 384 | private: | ||
| 385 | InternalFlag flag{}; | ||
| 386 | }; | ||
| 387 | |||
| 388 | /// A predicate register, it can be negated without additional nodes | ||
| 389 | class PredicateNode final { | ||
| 390 | public: | ||
| 391 | explicit constexpr PredicateNode(Tegra::Shader::Pred index, bool negated) | ||
| 392 | : index{index}, negated{negated} {} | ||
| 393 | |||
| 394 | Tegra::Shader::Pred GetIndex() const { | ||
| 395 | return index; | ||
| 396 | } | ||
| 397 | |||
| 398 | bool IsNegated() const { | ||
| 399 | return negated; | ||
| 400 | } | ||
| 401 | |||
| 402 | private: | ||
| 403 | Tegra::Shader::Pred index{}; | ||
| 404 | bool negated{}; | ||
| 405 | }; | ||
| 406 | |||
| 407 | /// Attribute buffer memory (known as attributes or varyings in GLSL terms) | ||
| 408 | class AbufNode final { | ||
| 409 | public: | ||
| 410 | // Initialize for standard attributes (index is explicit). | ||
| 411 | explicit AbufNode(Tegra::Shader::Attribute::Index index, u32 element, Node buffer = {}) | ||
| 412 | : buffer{std::move(buffer)}, index{index}, element{element} {} | ||
| 413 | |||
| 414 | // Initialize for physical attributes (index is a variable value). | ||
| 415 | explicit AbufNode(Node physical_address, Node buffer = {}) | ||
| 416 | : physical_address{std::move(physical_address)}, buffer{std::move(buffer)} {} | ||
| 417 | |||
| 418 | Tegra::Shader::Attribute::Index GetIndex() const { | ||
| 419 | return index; | ||
| 420 | } | ||
| 421 | |||
| 422 | u32 GetElement() const { | ||
| 423 | return element; | ||
| 424 | } | ||
| 425 | |||
| 426 | const Node& GetBuffer() const { | ||
| 427 | return buffer; | ||
| 428 | } | ||
| 429 | |||
| 430 | bool IsPhysicalBuffer() const { | ||
| 431 | return static_cast<bool>(physical_address); | ||
| 432 | } | ||
| 433 | |||
| 434 | const Node& GetPhysicalAddress() const { | ||
| 435 | return physical_address; | ||
| 436 | } | ||
| 437 | |||
| 438 | private: | ||
| 439 | Node physical_address; | ||
| 440 | Node buffer; | ||
| 441 | Tegra::Shader::Attribute::Index index{}; | ||
| 442 | u32 element{}; | ||
| 443 | }; | ||
| 444 | |||
| 445 | /// Constant buffer node, usually mapped to uniform buffers in GLSL | ||
| 446 | class CbufNode final { | ||
| 447 | public: | ||
| 448 | explicit CbufNode(u32 index, Node offset) : index{index}, offset{std::move(offset)} {} | ||
| 449 | |||
| 450 | u32 GetIndex() const { | ||
| 451 | return index; | ||
| 452 | } | ||
| 453 | |||
| 454 | const Node& GetOffset() const { | ||
| 455 | return offset; | ||
| 456 | } | ||
| 457 | |||
| 458 | private: | ||
| 459 | u32 index{}; | ||
| 460 | Node offset; | ||
| 461 | }; | ||
| 462 | |||
| 463 | /// Local memory node | ||
| 464 | class LmemNode final { | ||
| 465 | public: | ||
| 466 | explicit LmemNode(Node address) : address{std::move(address)} {} | ||
| 467 | |||
| 468 | const Node& GetAddress() const { | ||
| 469 | return address; | ||
| 470 | } | ||
| 471 | |||
| 472 | private: | ||
| 473 | Node address; | ||
| 474 | }; | ||
| 475 | |||
| 476 | /// Global memory node | ||
| 477 | class GmemNode final { | ||
| 478 | public: | ||
| 479 | explicit GmemNode(Node real_address, Node base_address, const GlobalMemoryBase& descriptor) | ||
| 480 | : real_address{std::move(real_address)}, base_address{std::move(base_address)}, | ||
| 481 | descriptor{descriptor} {} | ||
| 482 | |||
| 483 | const Node& GetRealAddress() const { | ||
| 484 | return real_address; | ||
| 485 | } | ||
| 486 | |||
| 487 | const Node& GetBaseAddress() const { | ||
| 488 | return base_address; | ||
| 489 | } | ||
| 490 | |||
| 491 | const GlobalMemoryBase& GetDescriptor() const { | ||
| 492 | return descriptor; | ||
| 493 | } | ||
| 494 | |||
| 495 | private: | ||
| 496 | Node real_address; | ||
| 497 | Node base_address; | ||
| 498 | GlobalMemoryBase descriptor; | ||
| 499 | }; | ||
| 500 | |||
| 501 | /// Commentary, can be dropped | ||
| 502 | class CommentNode final { | ||
| 503 | public: | ||
| 504 | explicit CommentNode(std::string text) : text{std::move(text)} {} | ||
| 505 | |||
| 506 | const std::string& GetText() const { | ||
| 507 | return text; | ||
| 508 | } | ||
| 509 | |||
| 510 | private: | ||
| 511 | std::string text; | ||
| 512 | }; | ||
| 513 | |||
| 514 | } // namespace VideoCommon::Shader | ||
diff --git a/src/video_core/shader/node_helper.h b/src/video_core/shader/node_helper.h index 70547a03d..0c2aa749b 100644 --- a/src/video_core/shader/node_helper.h +++ b/src/video_core/shader/node_helper.h | |||
| @@ -12,10 +12,15 @@ | |||
| 12 | #include <vector> | 12 | #include <vector> |
| 13 | 13 | ||
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "video_core/shader/shader_ir.h" | 15 | #include "video_core/shader/node.h" |
| 16 | 16 | ||
| 17 | namespace VideoCommon::Shader { | 17 | namespace VideoCommon::Shader { |
| 18 | 18 | ||
| 19 | /// This arithmetic operation cannot be constraint | ||
| 20 | inline constexpr MetaArithmetic PRECISE = {true}; | ||
| 21 | /// This arithmetic operation can be optimized away | ||
| 22 | inline constexpr MetaArithmetic NO_PRECISE = {false}; | ||
| 23 | |||
| 19 | /// Creates a conditional node | 24 | /// Creates a conditional node |
| 20 | Node Conditional(Node condition, std::vector<Node> code); | 25 | Node Conditional(Node condition, std::vector<Node> code); |
| 21 | 26 | ||
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 1b2745c23..edcf2288e 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -18,188 +18,14 @@ | |||
| 18 | #include "video_core/engines/maxwell_3d.h" | 18 | #include "video_core/engines/maxwell_3d.h" |
| 19 | #include "video_core/engines/shader_bytecode.h" | 19 | #include "video_core/engines/shader_bytecode.h" |
| 20 | #include "video_core/engines/shader_header.h" | 20 | #include "video_core/engines/shader_header.h" |
| 21 | #include "video_core/shader/node.h" | ||
| 21 | 22 | ||
| 22 | namespace VideoCommon::Shader { | 23 | namespace VideoCommon::Shader { |
| 23 | 24 | ||
| 24 | class OperationNode; | ||
| 25 | class ConditionalNode; | ||
| 26 | class GprNode; | ||
| 27 | class ImmediateNode; | ||
| 28 | class InternalFlagNode; | ||
| 29 | class PredicateNode; | ||
| 30 | class AbufNode; ///< Attribute buffer | ||
| 31 | class CbufNode; ///< Constant buffer | ||
| 32 | class LmemNode; ///< Local memory | ||
| 33 | class GmemNode; ///< Global memory | ||
| 34 | class CommentNode; | ||
| 35 | |||
| 36 | using ProgramCode = std::vector<u64>; | 25 | using ProgramCode = std::vector<u64>; |
| 37 | 26 | ||
| 38 | using NodeData = | ||
| 39 | std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode, | ||
| 40 | PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>; | ||
| 41 | using Node = std::shared_ptr<NodeData>; | ||
| 42 | using Node4 = std::array<Node, 4>; | ||
| 43 | using NodeBlock = std::vector<Node>; | ||
| 44 | |||
| 45 | constexpr u32 MAX_PROGRAM_LENGTH = 0x1000; | 27 | constexpr u32 MAX_PROGRAM_LENGTH = 0x1000; |
| 46 | 28 | ||
| 47 | enum class OperationCode { | ||
| 48 | Assign, /// (float& dest, float src) -> void | ||
| 49 | |||
| 50 | Select, /// (MetaArithmetic, bool pred, float a, float b) -> float | ||
| 51 | |||
| 52 | FAdd, /// (MetaArithmetic, float a, float b) -> float | ||
| 53 | FMul, /// (MetaArithmetic, float a, float b) -> float | ||
| 54 | FDiv, /// (MetaArithmetic, float a, float b) -> float | ||
| 55 | FFma, /// (MetaArithmetic, float a, float b, float c) -> float | ||
| 56 | FNegate, /// (MetaArithmetic, float a) -> float | ||
| 57 | FAbsolute, /// (MetaArithmetic, float a) -> float | ||
| 58 | FClamp, /// (MetaArithmetic, float value, float min, float max) -> float | ||
| 59 | FMin, /// (MetaArithmetic, float a, float b) -> float | ||
| 60 | FMax, /// (MetaArithmetic, float a, float b) -> float | ||
| 61 | FCos, /// (MetaArithmetic, float a) -> float | ||
| 62 | FSin, /// (MetaArithmetic, float a) -> float | ||
| 63 | FExp2, /// (MetaArithmetic, float a) -> float | ||
| 64 | FLog2, /// (MetaArithmetic, float a) -> float | ||
| 65 | FInverseSqrt, /// (MetaArithmetic, float a) -> float | ||
| 66 | FSqrt, /// (MetaArithmetic, float a) -> float | ||
| 67 | FRoundEven, /// (MetaArithmetic, float a) -> float | ||
| 68 | FFloor, /// (MetaArithmetic, float a) -> float | ||
| 69 | FCeil, /// (MetaArithmetic, float a) -> float | ||
| 70 | FTrunc, /// (MetaArithmetic, float a) -> float | ||
| 71 | FCastInteger, /// (MetaArithmetic, int a) -> float | ||
| 72 | FCastUInteger, /// (MetaArithmetic, uint a) -> float | ||
| 73 | |||
| 74 | IAdd, /// (MetaArithmetic, int a, int b) -> int | ||
| 75 | IMul, /// (MetaArithmetic, int a, int b) -> int | ||
| 76 | IDiv, /// (MetaArithmetic, int a, int b) -> int | ||
| 77 | INegate, /// (MetaArithmetic, int a) -> int | ||
| 78 | IAbsolute, /// (MetaArithmetic, int a) -> int | ||
| 79 | IMin, /// (MetaArithmetic, int a, int b) -> int | ||
| 80 | IMax, /// (MetaArithmetic, int a, int b) -> int | ||
| 81 | ICastFloat, /// (MetaArithmetic, float a) -> int | ||
| 82 | ICastUnsigned, /// (MetaArithmetic, uint a) -> int | ||
| 83 | ILogicalShiftLeft, /// (MetaArithmetic, int a, uint b) -> int | ||
| 84 | ILogicalShiftRight, /// (MetaArithmetic, int a, uint b) -> int | ||
| 85 | IArithmeticShiftRight, /// (MetaArithmetic, int a, uint b) -> int | ||
| 86 | IBitwiseAnd, /// (MetaArithmetic, int a, int b) -> int | ||
| 87 | IBitwiseOr, /// (MetaArithmetic, int a, int b) -> int | ||
| 88 | IBitwiseXor, /// (MetaArithmetic, int a, int b) -> int | ||
| 89 | IBitwiseNot, /// (MetaArithmetic, int a) -> int | ||
| 90 | IBitfieldInsert, /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int | ||
| 91 | IBitfieldExtract, /// (MetaArithmetic, int value, int offset, int offset) -> int | ||
| 92 | IBitCount, /// (MetaArithmetic, int) -> int | ||
| 93 | |||
| 94 | UAdd, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 95 | UMul, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 96 | UDiv, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 97 | UMin, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 98 | UMax, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 99 | UCastFloat, /// (MetaArithmetic, float a) -> uint | ||
| 100 | UCastSigned, /// (MetaArithmetic, int a) -> uint | ||
| 101 | ULogicalShiftLeft, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 102 | ULogicalShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 103 | UArithmeticShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 104 | UBitwiseAnd, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 105 | UBitwiseOr, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 106 | UBitwiseXor, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 107 | UBitwiseNot, /// (MetaArithmetic, uint a) -> uint | ||
| 108 | UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint | ||
| 109 | UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint | ||
| 110 | UBitCount, /// (MetaArithmetic, uint) -> uint | ||
| 111 | |||
| 112 | HAdd, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 | ||
| 113 | HMul, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 | ||
| 114 | HFma, /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2 | ||
| 115 | HAbsolute, /// (f16vec2 a) -> f16vec2 | ||
| 116 | HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2 | ||
| 117 | HClamp, /// (f16vec2 src, float min, float max) -> f16vec2 | ||
| 118 | HUnpack, /// (Tegra::Shader::HalfType, T value) -> f16vec2 | ||
| 119 | HMergeF32, /// (f16vec2 src) -> float | ||
| 120 | HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2 | ||
| 121 | HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2 | ||
| 122 | HPack2, /// (float a, float b) -> f16vec2 | ||
| 123 | |||
| 124 | LogicalAssign, /// (bool& dst, bool src) -> void | ||
| 125 | LogicalAnd, /// (bool a, bool b) -> bool | ||
| 126 | LogicalOr, /// (bool a, bool b) -> bool | ||
| 127 | LogicalXor, /// (bool a, bool b) -> bool | ||
| 128 | LogicalNegate, /// (bool a) -> bool | ||
| 129 | LogicalPick2, /// (bool2 pair, uint index) -> bool | ||
| 130 | LogicalAll2, /// (bool2 a) -> bool | ||
| 131 | LogicalAny2, /// (bool2 a) -> bool | ||
| 132 | |||
| 133 | LogicalFLessThan, /// (float a, float b) -> bool | ||
| 134 | LogicalFEqual, /// (float a, float b) -> bool | ||
| 135 | LogicalFLessEqual, /// (float a, float b) -> bool | ||
| 136 | LogicalFGreaterThan, /// (float a, float b) -> bool | ||
| 137 | LogicalFNotEqual, /// (float a, float b) -> bool | ||
| 138 | LogicalFGreaterEqual, /// (float a, float b) -> bool | ||
| 139 | LogicalFIsNan, /// (float a) -> bool | ||
| 140 | |||
| 141 | LogicalILessThan, /// (int a, int b) -> bool | ||
| 142 | LogicalIEqual, /// (int a, int b) -> bool | ||
| 143 | LogicalILessEqual, /// (int a, int b) -> bool | ||
| 144 | LogicalIGreaterThan, /// (int a, int b) -> bool | ||
| 145 | LogicalINotEqual, /// (int a, int b) -> bool | ||
| 146 | LogicalIGreaterEqual, /// (int a, int b) -> bool | ||
| 147 | |||
| 148 | LogicalULessThan, /// (uint a, uint b) -> bool | ||
| 149 | LogicalUEqual, /// (uint a, uint b) -> bool | ||
| 150 | LogicalULessEqual, /// (uint a, uint b) -> bool | ||
| 151 | LogicalUGreaterThan, /// (uint a, uint b) -> bool | ||
| 152 | LogicalUNotEqual, /// (uint a, uint b) -> bool | ||
| 153 | LogicalUGreaterEqual, /// (uint a, uint b) -> bool | ||
| 154 | |||
| 155 | Logical2HLessThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 156 | Logical2HEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 157 | Logical2HLessEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 158 | Logical2HGreaterThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 159 | Logical2HNotEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 160 | Logical2HGreaterEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 161 | Logical2HLessThanWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 162 | Logical2HEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 163 | Logical2HLessEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 164 | Logical2HGreaterThanWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 165 | Logical2HNotEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 166 | Logical2HGreaterEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 167 | |||
| 168 | Texture, /// (MetaTexture, float[N] coords) -> float4 | ||
| 169 | TextureLod, /// (MetaTexture, float[N] coords) -> float4 | ||
| 170 | TextureGather, /// (MetaTexture, float[N] coords) -> float4 | ||
| 171 | TextureQueryDimensions, /// (MetaTexture, float a) -> float4 | ||
| 172 | TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4 | ||
| 173 | TexelFetch, /// (MetaTexture, int[N], int) -> float4 | ||
| 174 | |||
| 175 | Branch, /// (uint branch_target) -> void | ||
| 176 | PushFlowStack, /// (uint branch_target) -> void | ||
| 177 | PopFlowStack, /// () -> void | ||
| 178 | Exit, /// () -> void | ||
| 179 | Discard, /// () -> void | ||
| 180 | |||
| 181 | EmitVertex, /// () -> void | ||
| 182 | EndPrimitive, /// () -> void | ||
| 183 | |||
| 184 | YNegate, /// () -> float | ||
| 185 | LocalInvocationIdX, /// () -> uint | ||
| 186 | LocalInvocationIdY, /// () -> uint | ||
| 187 | LocalInvocationIdZ, /// () -> uint | ||
| 188 | WorkGroupIdX, /// () -> uint | ||
| 189 | WorkGroupIdY, /// () -> uint | ||
| 190 | WorkGroupIdZ, /// () -> uint | ||
| 191 | |||
| 192 | Amount, | ||
| 193 | }; | ||
| 194 | |||
| 195 | enum class InternalFlag { | ||
| 196 | Zero = 0, | ||
| 197 | Sign = 1, | ||
| 198 | Carry = 2, | ||
| 199 | Overflow = 3, | ||
| 200 | Amount = 4, | ||
| 201 | }; | ||
| 202 | |||
| 203 | /// Describes the behaviour of code path of a given entry point and a return point. | 29 | /// Describes the behaviour of code path of a given entry point and a return point. |
| 204 | enum class ExitMethod { | 30 | enum class ExitMethod { |
| 205 | Undetermined, ///< Internal value. Only occur when analyzing JMP loop. | 31 | Undetermined, ///< Internal value. Only occur when analyzing JMP loop. |
| @@ -208,71 +34,6 @@ enum class ExitMethod { | |||
| 208 | AlwaysEnd, ///< All code paths reach a END instruction. | 34 | AlwaysEnd, ///< All code paths reach a END instruction. |
| 209 | }; | 35 | }; |
| 210 | 36 | ||
| 211 | class Sampler { | ||
| 212 | public: | ||
| 213 | // Use this constructor for bounded Samplers | ||
| 214 | explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, | ||
| 215 | bool is_array, bool is_shadow) | ||
| 216 | : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, | ||
| 217 | is_bindless{false} {} | ||
| 218 | |||
| 219 | // Use this constructor for bindless Samplers | ||
| 220 | explicit Sampler(u32 cbuf_index, u32 cbuf_offset, std::size_t index, | ||
| 221 | Tegra::Shader::TextureType type, bool is_array, bool is_shadow) | ||
| 222 | : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, | ||
| 223 | is_array{is_array}, is_shadow{is_shadow}, is_bindless{true} {} | ||
| 224 | |||
| 225 | // Use this only for serialization/deserialization | ||
| 226 | explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, | ||
| 227 | bool is_array, bool is_shadow, bool is_bindless) | ||
| 228 | : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, | ||
| 229 | is_bindless{is_bindless} {} | ||
| 230 | |||
| 231 | std::size_t GetOffset() const { | ||
| 232 | return offset; | ||
| 233 | } | ||
| 234 | |||
| 235 | std::size_t GetIndex() const { | ||
| 236 | return index; | ||
| 237 | } | ||
| 238 | |||
| 239 | Tegra::Shader::TextureType GetType() const { | ||
| 240 | return type; | ||
| 241 | } | ||
| 242 | |||
| 243 | bool IsArray() const { | ||
| 244 | return is_array; | ||
| 245 | } | ||
| 246 | |||
| 247 | bool IsShadow() const { | ||
| 248 | return is_shadow; | ||
| 249 | } | ||
| 250 | |||
| 251 | bool IsBindless() const { | ||
| 252 | return is_bindless; | ||
| 253 | } | ||
| 254 | |||
| 255 | std::pair<u32, u32> GetBindlessCBuf() const { | ||
| 256 | return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)}; | ||
| 257 | } | ||
| 258 | |||
| 259 | bool operator<(const Sampler& rhs) const { | ||
| 260 | return std::tie(index, offset, type, is_array, is_shadow, is_bindless) < | ||
| 261 | std::tie(rhs.index, rhs.offset, rhs.type, rhs.is_array, rhs.is_shadow, | ||
| 262 | rhs.is_bindless); | ||
| 263 | } | ||
| 264 | |||
| 265 | private: | ||
| 266 | /// Offset in TSC memory from which to read the sampler object, as specified by the sampling | ||
| 267 | /// instruction. | ||
| 268 | std::size_t offset{}; | ||
| 269 | std::size_t index{}; ///< Value used to index into the generated GLSL sampler array. | ||
| 270 | Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) | ||
| 271 | bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. | ||
| 272 | bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. | ||
| 273 | bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. | ||
| 274 | }; | ||
| 275 | |||
| 276 | class ConstBuffer { | 37 | class ConstBuffer { |
| 277 | public: | 38 | public: |
| 278 | explicit ConstBuffer(u32 max_offset, bool is_indirect) | 39 | explicit ConstBuffer(u32 max_offset, bool is_indirect) |
| @@ -305,263 +66,11 @@ private: | |||
| 305 | bool is_indirect{}; | 66 | bool is_indirect{}; |
| 306 | }; | 67 | }; |
| 307 | 68 | ||
| 308 | struct GlobalMemoryBase { | ||
| 309 | u32 cbuf_index{}; | ||
| 310 | u32 cbuf_offset{}; | ||
| 311 | |||
| 312 | bool operator<(const GlobalMemoryBase& rhs) const { | ||
| 313 | return std::tie(cbuf_index, cbuf_offset) < std::tie(rhs.cbuf_index, rhs.cbuf_offset); | ||
| 314 | } | ||
| 315 | }; | ||
| 316 | |||
| 317 | struct GlobalMemoryUsage { | 69 | struct GlobalMemoryUsage { |
| 318 | bool is_read{}; | 70 | bool is_read{}; |
| 319 | bool is_written{}; | 71 | bool is_written{}; |
| 320 | }; | 72 | }; |
| 321 | 73 | ||
| 322 | struct MetaArithmetic { | ||
| 323 | bool precise{}; | ||
| 324 | }; | ||
| 325 | |||
| 326 | struct MetaTexture { | ||
| 327 | const Sampler& sampler; | ||
| 328 | Node array{}; | ||
| 329 | Node depth_compare{}; | ||
| 330 | std::vector<Node> aoffi; | ||
| 331 | Node bias{}; | ||
| 332 | Node lod{}; | ||
| 333 | Node component{}; | ||
| 334 | u32 element{}; | ||
| 335 | }; | ||
| 336 | |||
| 337 | constexpr MetaArithmetic PRECISE = {true}; | ||
| 338 | constexpr MetaArithmetic NO_PRECISE = {false}; | ||
| 339 | |||
| 340 | using Meta = std::variant<MetaArithmetic, MetaTexture, Tegra::Shader::HalfType>; | ||
| 341 | |||
| 342 | /// Holds any kind of operation that can be done in the IR | ||
| 343 | class OperationNode final { | ||
| 344 | public: | ||
| 345 | explicit OperationNode(OperationCode code) : OperationNode(code, Meta{}) {} | ||
| 346 | |||
| 347 | explicit OperationNode(OperationCode code, Meta meta) | ||
| 348 | : OperationNode(code, meta, std::vector<Node>{}) {} | ||
| 349 | |||
| 350 | explicit OperationNode(OperationCode code, std::vector<Node> operands) | ||
| 351 | : OperationNode(code, Meta{}, std::move(operands)) {} | ||
| 352 | |||
| 353 | explicit OperationNode(OperationCode code, Meta meta, std::vector<Node> operands) | ||
| 354 | : code{code}, meta{std::move(meta)}, operands{std::move(operands)} {} | ||
| 355 | |||
| 356 | template <typename... Args> | ||
| 357 | explicit OperationNode(OperationCode code, Meta meta, Args&&... operands) | ||
| 358 | : code{code}, meta{std::move(meta)}, operands{operands...} {} | ||
| 359 | |||
| 360 | OperationCode GetCode() const { | ||
| 361 | return code; | ||
| 362 | } | ||
| 363 | |||
| 364 | const Meta& GetMeta() const { | ||
| 365 | return meta; | ||
| 366 | } | ||
| 367 | |||
| 368 | std::size_t GetOperandsCount() const { | ||
| 369 | return operands.size(); | ||
| 370 | } | ||
| 371 | |||
| 372 | const Node& operator[](std::size_t operand_index) const { | ||
| 373 | return operands.at(operand_index); | ||
| 374 | } | ||
| 375 | |||
| 376 | private: | ||
| 377 | OperationCode code{}; | ||
| 378 | Meta meta{}; | ||
| 379 | std::vector<Node> operands; | ||
| 380 | }; | ||
| 381 | |||
| 382 | /// Encloses inside any kind of node that returns a boolean conditionally-executed code | ||
| 383 | class ConditionalNode final { | ||
| 384 | public: | ||
| 385 | explicit ConditionalNode(Node condition, std::vector<Node>&& code) | ||
| 386 | : condition{condition}, code{std::move(code)} {} | ||
| 387 | |||
| 388 | Node GetCondition() const { | ||
| 389 | return condition; | ||
| 390 | } | ||
| 391 | |||
| 392 | const std::vector<Node>& GetCode() const { | ||
| 393 | return code; | ||
| 394 | } | ||
| 395 | |||
| 396 | private: | ||
| 397 | const Node condition; ///< Condition to be satisfied | ||
| 398 | std::vector<Node> code; ///< Code to execute | ||
| 399 | }; | ||
| 400 | |||
| 401 | /// A general purpose register | ||
| 402 | class GprNode final { | ||
| 403 | public: | ||
| 404 | explicit constexpr GprNode(Tegra::Shader::Register index) : index{index} {} | ||
| 405 | |||
| 406 | u32 GetIndex() const { | ||
| 407 | return static_cast<u32>(index); | ||
| 408 | } | ||
| 409 | |||
| 410 | private: | ||
| 411 | const Tegra::Shader::Register index; | ||
| 412 | }; | ||
| 413 | |||
| 414 | /// A 32-bits value that represents an immediate value | ||
| 415 | class ImmediateNode final { | ||
| 416 | public: | ||
| 417 | explicit constexpr ImmediateNode(u32 value) : value{value} {} | ||
| 418 | |||
| 419 | u32 GetValue() const { | ||
| 420 | return value; | ||
| 421 | } | ||
| 422 | |||
| 423 | private: | ||
| 424 | const u32 value; | ||
| 425 | }; | ||
| 426 | |||
| 427 | /// One of Maxwell's internal flags | ||
| 428 | class InternalFlagNode final { | ||
| 429 | public: | ||
| 430 | explicit constexpr InternalFlagNode(InternalFlag flag) : flag{flag} {} | ||
| 431 | |||
| 432 | InternalFlag GetFlag() const { | ||
| 433 | return flag; | ||
| 434 | } | ||
| 435 | |||
| 436 | private: | ||
| 437 | const InternalFlag flag; | ||
| 438 | }; | ||
| 439 | |||
| 440 | /// A predicate register, it can be negated without additional nodes | ||
| 441 | class PredicateNode final { | ||
| 442 | public: | ||
| 443 | explicit constexpr PredicateNode(Tegra::Shader::Pred index, bool negated) | ||
| 444 | : index{index}, negated{negated} {} | ||
| 445 | |||
| 446 | Tegra::Shader::Pred GetIndex() const { | ||
| 447 | return index; | ||
| 448 | } | ||
| 449 | |||
| 450 | bool IsNegated() const { | ||
| 451 | return negated; | ||
| 452 | } | ||
| 453 | |||
| 454 | private: | ||
| 455 | const Tegra::Shader::Pred index; | ||
| 456 | const bool negated; | ||
| 457 | }; | ||
| 458 | |||
| 459 | /// Attribute buffer memory (known as attributes or varyings in GLSL terms) | ||
| 460 | class AbufNode final { | ||
| 461 | public: | ||
| 462 | // Initialize for standard attributes (index is explicit). | ||
| 463 | explicit AbufNode(Tegra::Shader::Attribute::Index index, u32 element, Node buffer = {}) | ||
| 464 | : buffer{std::move(buffer)}, index{index}, element{element} {} | ||
| 465 | |||
| 466 | // Initialize for physical attributes (index is a variable value). | ||
| 467 | explicit AbufNode(Node physical_address, Node buffer = {}) | ||
| 468 | : physical_address{physical_address}, buffer{std::move(buffer)} {} | ||
| 469 | |||
| 470 | Tegra::Shader::Attribute::Index GetIndex() const { | ||
| 471 | return index; | ||
| 472 | } | ||
| 473 | |||
| 474 | u32 GetElement() const { | ||
| 475 | return element; | ||
| 476 | } | ||
| 477 | |||
| 478 | Node GetBuffer() const { | ||
| 479 | return buffer; | ||
| 480 | } | ||
| 481 | |||
| 482 | bool IsPhysicalBuffer() const { | ||
| 483 | return static_cast<bool>(physical_address); | ||
| 484 | } | ||
| 485 | |||
| 486 | const Node& GetPhysicalAddress() const { | ||
| 487 | return physical_address; | ||
| 488 | } | ||
| 489 | |||
| 490 | private: | ||
| 491 | Node physical_address; | ||
| 492 | Node buffer; | ||
| 493 | Tegra::Shader::Attribute::Index index{}; | ||
| 494 | u32 element{}; | ||
| 495 | }; | ||
| 496 | |||
| 497 | /// Constant buffer node, usually mapped to uniform buffers in GLSL | ||
| 498 | class CbufNode final { | ||
| 499 | public: | ||
| 500 | explicit CbufNode(u32 index, Node offset) : index{index}, offset{offset} {} | ||
| 501 | |||
| 502 | u32 GetIndex() const { | ||
| 503 | return index; | ||
| 504 | } | ||
| 505 | |||
| 506 | Node GetOffset() const { | ||
| 507 | return offset; | ||
| 508 | } | ||
| 509 | |||
| 510 | private: | ||
| 511 | const u32 index; | ||
| 512 | const Node offset; | ||
| 513 | }; | ||
| 514 | |||
| 515 | /// Local memory node | ||
| 516 | class LmemNode final { | ||
| 517 | public: | ||
| 518 | explicit LmemNode(Node address) : address{address} {} | ||
| 519 | |||
| 520 | Node GetAddress() const { | ||
| 521 | return address; | ||
| 522 | } | ||
| 523 | |||
| 524 | private: | ||
| 525 | const Node address; | ||
| 526 | }; | ||
| 527 | |||
| 528 | /// Global memory node | ||
| 529 | class GmemNode final { | ||
| 530 | public: | ||
| 531 | explicit GmemNode(Node real_address, Node base_address, const GlobalMemoryBase& descriptor) | ||
| 532 | : real_address{real_address}, base_address{base_address}, descriptor{descriptor} {} | ||
| 533 | |||
| 534 | Node GetRealAddress() const { | ||
| 535 | return real_address; | ||
| 536 | } | ||
| 537 | |||
| 538 | Node GetBaseAddress() const { | ||
| 539 | return base_address; | ||
| 540 | } | ||
| 541 | |||
| 542 | const GlobalMemoryBase& GetDescriptor() const { | ||
| 543 | return descriptor; | ||
| 544 | } | ||
| 545 | |||
| 546 | private: | ||
| 547 | const Node real_address; | ||
| 548 | const Node base_address; | ||
| 549 | const GlobalMemoryBase descriptor; | ||
| 550 | }; | ||
| 551 | |||
| 552 | /// Commentary, can be dropped | ||
| 553 | class CommentNode final { | ||
| 554 | public: | ||
| 555 | explicit CommentNode(std::string text) : text{std::move(text)} {} | ||
| 556 | |||
| 557 | const std::string& GetText() const { | ||
| 558 | return text; | ||
| 559 | } | ||
| 560 | |||
| 561 | private: | ||
| 562 | std::string text; | ||
| 563 | }; | ||
| 564 | |||
| 565 | class ShaderIR final { | 74 | class ShaderIR final { |
| 566 | public: | 75 | public: |
| 567 | explicit ShaderIR(const ProgramCode& program_code, u32 main_offset); | 76 | explicit ShaderIR(const ProgramCode& program_code, u32 main_offset); |