diff options
Diffstat (limited to 'src/video_core/shader/node.h')
| -rw-r--r-- | src/video_core/shader/node.h | 701 |
1 files changed, 0 insertions, 701 deletions
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h deleted file mode 100644 index b54d33763..000000000 --- a/src/video_core/shader/node.h +++ /dev/null | |||
| @@ -1,701 +0,0 @@ | |||
| 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 <optional> | ||
| 11 | #include <string> | ||
| 12 | #include <tuple> | ||
| 13 | #include <utility> | ||
| 14 | #include <variant> | ||
| 15 | #include <vector> | ||
| 16 | |||
| 17 | #include "common/common_types.h" | ||
| 18 | #include "video_core/engines/shader_bytecode.h" | ||
| 19 | |||
| 20 | namespace VideoCommon::Shader { | ||
| 21 | |||
| 22 | enum class OperationCode { | ||
| 23 | Assign, /// (float& dest, float src) -> void | ||
| 24 | |||
| 25 | Select, /// (MetaArithmetic, bool pred, float a, float b) -> float | ||
| 26 | |||
| 27 | FAdd, /// (MetaArithmetic, float a, float b) -> float | ||
| 28 | FMul, /// (MetaArithmetic, float a, float b) -> float | ||
| 29 | FDiv, /// (MetaArithmetic, float a, float b) -> float | ||
| 30 | FFma, /// (MetaArithmetic, float a, float b, float c) -> float | ||
| 31 | FNegate, /// (MetaArithmetic, float a) -> float | ||
| 32 | FAbsolute, /// (MetaArithmetic, float a) -> float | ||
| 33 | FClamp, /// (MetaArithmetic, float value, float min, float max) -> float | ||
| 34 | FCastHalf0, /// (MetaArithmetic, f16vec2 a) -> float | ||
| 35 | FCastHalf1, /// (MetaArithmetic, f16vec2 a) -> float | ||
| 36 | FMin, /// (MetaArithmetic, float a, float b) -> float | ||
| 37 | FMax, /// (MetaArithmetic, float a, float b) -> float | ||
| 38 | FCos, /// (MetaArithmetic, float a) -> float | ||
| 39 | FSin, /// (MetaArithmetic, float a) -> float | ||
| 40 | FExp2, /// (MetaArithmetic, float a) -> float | ||
| 41 | FLog2, /// (MetaArithmetic, float a) -> float | ||
| 42 | FInverseSqrt, /// (MetaArithmetic, float a) -> float | ||
| 43 | FSqrt, /// (MetaArithmetic, float a) -> float | ||
| 44 | FRoundEven, /// (MetaArithmetic, float a) -> float | ||
| 45 | FFloor, /// (MetaArithmetic, float a) -> float | ||
| 46 | FCeil, /// (MetaArithmetic, float a) -> float | ||
| 47 | FTrunc, /// (MetaArithmetic, float a) -> float | ||
| 48 | FCastInteger, /// (MetaArithmetic, int a) -> float | ||
| 49 | FCastUInteger, /// (MetaArithmetic, uint a) -> float | ||
| 50 | FSwizzleAdd, /// (float a, float b, uint mask) -> float | ||
| 51 | |||
| 52 | IAdd, /// (MetaArithmetic, int a, int b) -> int | ||
| 53 | IMul, /// (MetaArithmetic, int a, int b) -> int | ||
| 54 | IDiv, /// (MetaArithmetic, int a, int b) -> int | ||
| 55 | INegate, /// (MetaArithmetic, int a) -> int | ||
| 56 | IAbsolute, /// (MetaArithmetic, int a) -> int | ||
| 57 | IMin, /// (MetaArithmetic, int a, int b) -> int | ||
| 58 | IMax, /// (MetaArithmetic, int a, int b) -> int | ||
| 59 | ICastFloat, /// (MetaArithmetic, float a) -> int | ||
| 60 | ICastUnsigned, /// (MetaArithmetic, uint a) -> int | ||
| 61 | ILogicalShiftLeft, /// (MetaArithmetic, int a, uint b) -> int | ||
| 62 | ILogicalShiftRight, /// (MetaArithmetic, int a, uint b) -> int | ||
| 63 | IArithmeticShiftRight, /// (MetaArithmetic, int a, uint b) -> int | ||
| 64 | IBitwiseAnd, /// (MetaArithmetic, int a, int b) -> int | ||
| 65 | IBitwiseOr, /// (MetaArithmetic, int a, int b) -> int | ||
| 66 | IBitwiseXor, /// (MetaArithmetic, int a, int b) -> int | ||
| 67 | IBitwiseNot, /// (MetaArithmetic, int a) -> int | ||
| 68 | IBitfieldInsert, /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int | ||
| 69 | IBitfieldExtract, /// (MetaArithmetic, int value, int offset, int offset) -> int | ||
| 70 | IBitCount, /// (MetaArithmetic, int) -> int | ||
| 71 | IBitMSB, /// (MetaArithmetic, int) -> int | ||
| 72 | |||
| 73 | UAdd, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 74 | UMul, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 75 | UDiv, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 76 | UMin, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 77 | UMax, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 78 | UCastFloat, /// (MetaArithmetic, float a) -> uint | ||
| 79 | UCastSigned, /// (MetaArithmetic, int a) -> uint | ||
| 80 | ULogicalShiftLeft, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 81 | ULogicalShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 82 | UArithmeticShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 83 | UBitwiseAnd, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 84 | UBitwiseOr, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 85 | UBitwiseXor, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 86 | UBitwiseNot, /// (MetaArithmetic, uint a) -> uint | ||
| 87 | UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint | ||
| 88 | UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint | ||
| 89 | UBitCount, /// (MetaArithmetic, uint) -> uint | ||
| 90 | UBitMSB, /// (MetaArithmetic, uint) -> uint | ||
| 91 | |||
| 92 | HAdd, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 | ||
| 93 | HMul, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 | ||
| 94 | HFma, /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2 | ||
| 95 | HAbsolute, /// (f16vec2 a) -> f16vec2 | ||
| 96 | HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2 | ||
| 97 | HClamp, /// (f16vec2 src, float min, float max) -> f16vec2 | ||
| 98 | HCastFloat, /// (MetaArithmetic, float a) -> f16vec2 | ||
| 99 | HUnpack, /// (Tegra::Shader::HalfType, T value) -> f16vec2 | ||
| 100 | HMergeF32, /// (f16vec2 src) -> float | ||
| 101 | HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2 | ||
| 102 | HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2 | ||
| 103 | HPack2, /// (float a, float b) -> f16vec2 | ||
| 104 | |||
| 105 | LogicalAssign, /// (bool& dst, bool src) -> void | ||
| 106 | LogicalAnd, /// (bool a, bool b) -> bool | ||
| 107 | LogicalOr, /// (bool a, bool b) -> bool | ||
| 108 | LogicalXor, /// (bool a, bool b) -> bool | ||
| 109 | LogicalNegate, /// (bool a) -> bool | ||
| 110 | LogicalPick2, /// (bool2 pair, uint index) -> bool | ||
| 111 | LogicalAnd2, /// (bool2 a) -> bool | ||
| 112 | |||
| 113 | LogicalFOrdLessThan, /// (float a, float b) -> bool | ||
| 114 | LogicalFOrdEqual, /// (float a, float b) -> bool | ||
| 115 | LogicalFOrdLessEqual, /// (float a, float b) -> bool | ||
| 116 | LogicalFOrdGreaterThan, /// (float a, float b) -> bool | ||
| 117 | LogicalFOrdNotEqual, /// (float a, float b) -> bool | ||
| 118 | LogicalFOrdGreaterEqual, /// (float a, float b) -> bool | ||
| 119 | LogicalFOrdered, /// (float a, float b) -> bool | ||
| 120 | LogicalFUnordered, /// (float a, float b) -> bool | ||
| 121 | LogicalFUnordLessThan, /// (float a, float b) -> bool | ||
| 122 | LogicalFUnordEqual, /// (float a, float b) -> bool | ||
| 123 | LogicalFUnordLessEqual, /// (float a, float b) -> bool | ||
| 124 | LogicalFUnordGreaterThan, /// (float a, float b) -> bool | ||
| 125 | LogicalFUnordNotEqual, /// (float a, float b) -> bool | ||
| 126 | LogicalFUnordGreaterEqual, /// (float a, float b) -> bool | ||
| 127 | |||
| 128 | LogicalILessThan, /// (int a, int b) -> bool | ||
| 129 | LogicalIEqual, /// (int a, int b) -> bool | ||
| 130 | LogicalILessEqual, /// (int a, int b) -> bool | ||
| 131 | LogicalIGreaterThan, /// (int a, int b) -> bool | ||
| 132 | LogicalINotEqual, /// (int a, int b) -> bool | ||
| 133 | LogicalIGreaterEqual, /// (int a, int b) -> bool | ||
| 134 | |||
| 135 | LogicalULessThan, /// (uint a, uint b) -> bool | ||
| 136 | LogicalUEqual, /// (uint a, uint b) -> bool | ||
| 137 | LogicalULessEqual, /// (uint a, uint b) -> bool | ||
| 138 | LogicalUGreaterThan, /// (uint a, uint b) -> bool | ||
| 139 | LogicalUNotEqual, /// (uint a, uint b) -> bool | ||
| 140 | LogicalUGreaterEqual, /// (uint a, uint b) -> bool | ||
| 141 | |||
| 142 | LogicalAddCarry, /// (uint a, uint b) -> bool | ||
| 143 | |||
| 144 | Logical2HLessThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 145 | Logical2HEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 146 | Logical2HLessEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 147 | Logical2HGreaterThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 148 | Logical2HNotEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 149 | Logical2HGreaterEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 150 | Logical2HLessThanWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 151 | Logical2HEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 152 | Logical2HLessEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 153 | Logical2HGreaterThanWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 154 | Logical2HNotEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 155 | Logical2HGreaterEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | ||
| 156 | |||
| 157 | Texture, /// (MetaTexture, float[N] coords) -> float4 | ||
| 158 | TextureLod, /// (MetaTexture, float[N] coords) -> float4 | ||
| 159 | TextureGather, /// (MetaTexture, float[N] coords) -> float4 | ||
| 160 | TextureQueryDimensions, /// (MetaTexture, float a) -> float4 | ||
| 161 | TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4 | ||
| 162 | TexelFetch, /// (MetaTexture, int[N], int) -> float4 | ||
| 163 | TextureGradient, /// (MetaTexture, float[N] coords, float[N*2] derivates) -> float4 | ||
| 164 | |||
| 165 | ImageLoad, /// (MetaImage, int[N] coords) -> void | ||
| 166 | ImageStore, /// (MetaImage, int[N] coords) -> void | ||
| 167 | |||
| 168 | AtomicImageAdd, /// (MetaImage, int[N] coords) -> void | ||
| 169 | AtomicImageAnd, /// (MetaImage, int[N] coords) -> void | ||
| 170 | AtomicImageOr, /// (MetaImage, int[N] coords) -> void | ||
| 171 | AtomicImageXor, /// (MetaImage, int[N] coords) -> void | ||
| 172 | AtomicImageExchange, /// (MetaImage, int[N] coords) -> void | ||
| 173 | |||
| 174 | AtomicUExchange, /// (memory, uint) -> uint | ||
| 175 | AtomicUAdd, /// (memory, uint) -> uint | ||
| 176 | AtomicUMin, /// (memory, uint) -> uint | ||
| 177 | AtomicUMax, /// (memory, uint) -> uint | ||
| 178 | AtomicUAnd, /// (memory, uint) -> uint | ||
| 179 | AtomicUOr, /// (memory, uint) -> uint | ||
| 180 | AtomicUXor, /// (memory, uint) -> uint | ||
| 181 | |||
| 182 | AtomicIExchange, /// (memory, int) -> int | ||
| 183 | AtomicIAdd, /// (memory, int) -> int | ||
| 184 | AtomicIMin, /// (memory, int) -> int | ||
| 185 | AtomicIMax, /// (memory, int) -> int | ||
| 186 | AtomicIAnd, /// (memory, int) -> int | ||
| 187 | AtomicIOr, /// (memory, int) -> int | ||
| 188 | AtomicIXor, /// (memory, int) -> int | ||
| 189 | |||
| 190 | ReduceUAdd, /// (memory, uint) -> void | ||
| 191 | ReduceUMin, /// (memory, uint) -> void | ||
| 192 | ReduceUMax, /// (memory, uint) -> void | ||
| 193 | ReduceUAnd, /// (memory, uint) -> void | ||
| 194 | ReduceUOr, /// (memory, uint) -> void | ||
| 195 | ReduceUXor, /// (memory, uint) -> void | ||
| 196 | |||
| 197 | ReduceIAdd, /// (memory, int) -> void | ||
| 198 | ReduceIMin, /// (memory, int) -> void | ||
| 199 | ReduceIMax, /// (memory, int) -> void | ||
| 200 | ReduceIAnd, /// (memory, int) -> void | ||
| 201 | ReduceIOr, /// (memory, int) -> void | ||
| 202 | ReduceIXor, /// (memory, int) -> void | ||
| 203 | |||
| 204 | Branch, /// (uint branch_target) -> void | ||
| 205 | BranchIndirect, /// (uint branch_target) -> void | ||
| 206 | PushFlowStack, /// (uint branch_target) -> void | ||
| 207 | PopFlowStack, /// () -> void | ||
| 208 | Exit, /// () -> void | ||
| 209 | Discard, /// () -> void | ||
| 210 | |||
| 211 | EmitVertex, /// () -> void | ||
| 212 | EndPrimitive, /// () -> void | ||
| 213 | |||
| 214 | InvocationId, /// () -> int | ||
| 215 | YNegate, /// () -> float | ||
| 216 | LocalInvocationIdX, /// () -> uint | ||
| 217 | LocalInvocationIdY, /// () -> uint | ||
| 218 | LocalInvocationIdZ, /// () -> uint | ||
| 219 | WorkGroupIdX, /// () -> uint | ||
| 220 | WorkGroupIdY, /// () -> uint | ||
| 221 | WorkGroupIdZ, /// () -> uint | ||
| 222 | |||
| 223 | BallotThread, /// (bool) -> uint | ||
| 224 | VoteAll, /// (bool) -> bool | ||
| 225 | VoteAny, /// (bool) -> bool | ||
| 226 | VoteEqual, /// (bool) -> bool | ||
| 227 | |||
| 228 | ThreadId, /// () -> uint | ||
| 229 | ThreadEqMask, /// () -> uint | ||
| 230 | ThreadGeMask, /// () -> uint | ||
| 231 | ThreadGtMask, /// () -> uint | ||
| 232 | ThreadLeMask, /// () -> uint | ||
| 233 | ThreadLtMask, /// () -> uint | ||
| 234 | ShuffleIndexed, /// (uint value, uint index) -> uint | ||
| 235 | |||
| 236 | Barrier, /// () -> void | ||
| 237 | MemoryBarrierGroup, /// () -> void | ||
| 238 | MemoryBarrierGlobal, /// () -> void | ||
| 239 | |||
| 240 | Amount, | ||
| 241 | }; | ||
| 242 | |||
| 243 | enum class InternalFlag { | ||
| 244 | Zero = 0, | ||
| 245 | Sign = 1, | ||
| 246 | Carry = 2, | ||
| 247 | Overflow = 3, | ||
| 248 | Amount = 4, | ||
| 249 | }; | ||
| 250 | |||
| 251 | enum class MetaStackClass { | ||
| 252 | Ssy, | ||
| 253 | Pbk, | ||
| 254 | }; | ||
| 255 | |||
| 256 | class OperationNode; | ||
| 257 | class ConditionalNode; | ||
| 258 | class GprNode; | ||
| 259 | class CustomVarNode; | ||
| 260 | class ImmediateNode; | ||
| 261 | class InternalFlagNode; | ||
| 262 | class PredicateNode; | ||
| 263 | class AbufNode; | ||
| 264 | class CbufNode; | ||
| 265 | class LmemNode; | ||
| 266 | class PatchNode; | ||
| 267 | class SmemNode; | ||
| 268 | class GmemNode; | ||
| 269 | class CommentNode; | ||
| 270 | |||
| 271 | using NodeData = std::variant<OperationNode, ConditionalNode, GprNode, CustomVarNode, ImmediateNode, | ||
| 272 | InternalFlagNode, PredicateNode, AbufNode, PatchNode, CbufNode, | ||
| 273 | LmemNode, SmemNode, GmemNode, CommentNode>; | ||
| 274 | using Node = std::shared_ptr<NodeData>; | ||
| 275 | using Node4 = std::array<Node, 4>; | ||
| 276 | using NodeBlock = std::vector<Node>; | ||
| 277 | |||
| 278 | struct ArraySamplerNode; | ||
| 279 | struct BindlessSamplerNode; | ||
| 280 | struct SeparateSamplerNode; | ||
| 281 | |||
| 282 | using TrackSamplerData = std::variant<BindlessSamplerNode, SeparateSamplerNode, ArraySamplerNode>; | ||
| 283 | using TrackSampler = std::shared_ptr<TrackSamplerData>; | ||
| 284 | |||
| 285 | struct SamplerEntry { | ||
| 286 | /// Bound samplers constructor | ||
| 287 | explicit SamplerEntry(u32 index_, u32 offset_, Tegra::Shader::TextureType type_, bool is_array_, | ||
| 288 | bool is_shadow_, bool is_buffer_, bool is_indexed_) | ||
| 289 | : index{index_}, offset{offset_}, type{type_}, is_array{is_array_}, is_shadow{is_shadow_}, | ||
| 290 | is_buffer{is_buffer_}, is_indexed{is_indexed_} {} | ||
| 291 | |||
| 292 | /// Separate sampler constructor | ||
| 293 | explicit SamplerEntry(u32 index_, std::pair<u32, u32> offsets, std::pair<u32, u32> buffers, | ||
| 294 | Tegra::Shader::TextureType type_, bool is_array_, bool is_shadow_, | ||
| 295 | bool is_buffer_) | ||
| 296 | : index{index_}, offset{offsets.first}, secondary_offset{offsets.second}, | ||
| 297 | buffer{buffers.first}, secondary_buffer{buffers.second}, type{type_}, is_array{is_array_}, | ||
| 298 | is_shadow{is_shadow_}, is_buffer{is_buffer_}, is_separated{true} {} | ||
| 299 | |||
| 300 | /// Bindless samplers constructor | ||
| 301 | explicit SamplerEntry(u32 index_, u32 offset_, u32 buffer_, Tegra::Shader::TextureType type_, | ||
| 302 | bool is_array_, bool is_shadow_, bool is_buffer_, bool is_indexed_) | ||
| 303 | : index{index_}, offset{offset_}, buffer{buffer_}, type{type_}, is_array{is_array_}, | ||
| 304 | is_shadow{is_shadow_}, is_buffer{is_buffer_}, is_bindless{true}, is_indexed{is_indexed_} { | ||
| 305 | } | ||
| 306 | |||
| 307 | u32 index = 0; ///< Emulated index given for the this sampler. | ||
| 308 | u32 offset = 0; ///< Offset in the const buffer from where the sampler is being read. | ||
| 309 | u32 secondary_offset = 0; ///< Secondary offset in the const buffer. | ||
| 310 | u32 buffer = 0; ///< Buffer where the bindless sampler is read. | ||
| 311 | u32 secondary_buffer = 0; ///< Secondary buffer where the bindless sampler is read. | ||
| 312 | u32 size = 1; ///< Size of the sampler. | ||
| 313 | |||
| 314 | Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) | ||
| 315 | bool is_array = false; ///< Whether the texture is being sampled as an array texture or not. | ||
| 316 | bool is_shadow = false; ///< Whether the texture is being sampled as a depth texture or not. | ||
| 317 | bool is_buffer = false; ///< Whether the texture is a texture buffer without sampler. | ||
| 318 | bool is_bindless = false; ///< Whether this sampler belongs to a bindless texture or not. | ||
| 319 | bool is_indexed = false; ///< Whether this sampler is an indexed array of textures. | ||
| 320 | bool is_separated = false; ///< Whether the image and sampler is separated or not. | ||
| 321 | }; | ||
| 322 | |||
| 323 | /// Represents a tracked bindless sampler into a direct const buffer | ||
| 324 | struct ArraySamplerNode { | ||
| 325 | u32 index; | ||
| 326 | u32 base_offset; | ||
| 327 | u32 bindless_var; | ||
| 328 | }; | ||
| 329 | |||
| 330 | /// Represents a tracked separate sampler image pair that was folded statically | ||
| 331 | struct SeparateSamplerNode { | ||
| 332 | std::pair<u32, u32> indices; | ||
| 333 | std::pair<u32, u32> offsets; | ||
| 334 | }; | ||
| 335 | |||
| 336 | /// Represents a tracked bindless sampler into a direct const buffer | ||
| 337 | struct BindlessSamplerNode { | ||
| 338 | u32 index; | ||
| 339 | u32 offset; | ||
| 340 | }; | ||
| 341 | |||
| 342 | struct ImageEntry { | ||
| 343 | public: | ||
| 344 | /// Bound images constructor | ||
| 345 | explicit ImageEntry(u32 index_, u32 offset_, Tegra::Shader::ImageType type_) | ||
| 346 | : index{index_}, offset{offset_}, type{type_} {} | ||
| 347 | |||
| 348 | /// Bindless samplers constructor | ||
| 349 | explicit ImageEntry(u32 index_, u32 offset_, u32 buffer_, Tegra::Shader::ImageType type_) | ||
| 350 | : index{index_}, offset{offset_}, buffer{buffer_}, type{type_}, is_bindless{true} {} | ||
| 351 | |||
| 352 | void MarkWrite() { | ||
| 353 | is_written = true; | ||
| 354 | } | ||
| 355 | |||
| 356 | void MarkRead() { | ||
| 357 | is_read = true; | ||
| 358 | } | ||
| 359 | |||
| 360 | void MarkAtomic() { | ||
| 361 | MarkWrite(); | ||
| 362 | MarkRead(); | ||
| 363 | is_atomic = true; | ||
| 364 | } | ||
| 365 | |||
| 366 | u32 index = 0; | ||
| 367 | u32 offset = 0; | ||
| 368 | u32 buffer = 0; | ||
| 369 | |||
| 370 | Tegra::Shader::ImageType type{}; | ||
| 371 | bool is_bindless = false; | ||
| 372 | bool is_written = false; | ||
| 373 | bool is_read = false; | ||
| 374 | bool is_atomic = false; | ||
| 375 | }; | ||
| 376 | |||
| 377 | struct GlobalMemoryBase { | ||
| 378 | u32 cbuf_index = 0; | ||
| 379 | u32 cbuf_offset = 0; | ||
| 380 | |||
| 381 | [[nodiscard]] bool operator<(const GlobalMemoryBase& rhs) const { | ||
| 382 | return std::tie(cbuf_index, cbuf_offset) < std::tie(rhs.cbuf_index, rhs.cbuf_offset); | ||
| 383 | } | ||
| 384 | }; | ||
| 385 | |||
| 386 | /// Parameters describing an arithmetic operation | ||
| 387 | struct MetaArithmetic { | ||
| 388 | bool precise{}; ///< Whether the operation can be constraint or not | ||
| 389 | }; | ||
| 390 | |||
| 391 | /// Parameters describing a texture sampler | ||
| 392 | struct MetaTexture { | ||
| 393 | SamplerEntry sampler; | ||
| 394 | Node array; | ||
| 395 | Node depth_compare; | ||
| 396 | std::vector<Node> aoffi; | ||
| 397 | std::vector<Node> ptp; | ||
| 398 | std::vector<Node> derivates; | ||
| 399 | Node bias; | ||
| 400 | Node lod; | ||
| 401 | Node component; | ||
| 402 | u32 element{}; | ||
| 403 | Node index; | ||
| 404 | }; | ||
| 405 | |||
| 406 | struct MetaImage { | ||
| 407 | const ImageEntry& image; | ||
| 408 | std::vector<Node> values; | ||
| 409 | u32 element{}; | ||
| 410 | }; | ||
| 411 | |||
| 412 | /// Parameters that modify an operation but are not part of any particular operand | ||
| 413 | using Meta = | ||
| 414 | std::variant<MetaArithmetic, MetaTexture, MetaImage, MetaStackClass, Tegra::Shader::HalfType>; | ||
| 415 | |||
| 416 | class AmendNode { | ||
| 417 | public: | ||
| 418 | [[nodiscard]] std::optional<std::size_t> GetAmendIndex() const { | ||
| 419 | if (amend_index == amend_null_index) { | ||
| 420 | return std::nullopt; | ||
| 421 | } | ||
| 422 | return {amend_index}; | ||
| 423 | } | ||
| 424 | |||
| 425 | void SetAmendIndex(std::size_t index) { | ||
| 426 | amend_index = index; | ||
| 427 | } | ||
| 428 | |||
| 429 | void ClearAmend() { | ||
| 430 | amend_index = amend_null_index; | ||
| 431 | } | ||
| 432 | |||
| 433 | private: | ||
| 434 | static constexpr std::size_t amend_null_index = 0xFFFFFFFFFFFFFFFFULL; | ||
| 435 | std::size_t amend_index{amend_null_index}; | ||
| 436 | }; | ||
| 437 | |||
| 438 | /// Holds any kind of operation that can be done in the IR | ||
| 439 | class OperationNode final : public AmendNode { | ||
| 440 | public: | ||
| 441 | explicit OperationNode(OperationCode code_) : OperationNode(code_, Meta{}) {} | ||
| 442 | |||
| 443 | explicit OperationNode(OperationCode code_, Meta meta_) | ||
| 444 | : OperationNode(code_, std::move(meta_), std::vector<Node>{}) {} | ||
| 445 | |||
| 446 | explicit OperationNode(OperationCode code_, std::vector<Node> operands_) | ||
| 447 | : OperationNode(code_, Meta{}, std::move(operands_)) {} | ||
| 448 | |||
| 449 | explicit OperationNode(OperationCode code_, Meta meta_, std::vector<Node> operands_) | ||
| 450 | : code{code_}, meta{std::move(meta_)}, operands{std::move(operands_)} {} | ||
| 451 | |||
| 452 | template <typename... Args> | ||
| 453 | explicit OperationNode(OperationCode code_, Meta meta_, Args&&... operands_) | ||
| 454 | : code{code_}, meta{std::move(meta_)}, operands{operands_...} {} | ||
| 455 | |||
| 456 | [[nodiscard]] OperationCode GetCode() const { | ||
| 457 | return code; | ||
| 458 | } | ||
| 459 | |||
| 460 | [[nodiscard]] const Meta& GetMeta() const { | ||
| 461 | return meta; | ||
| 462 | } | ||
| 463 | |||
| 464 | [[nodiscard]] std::size_t GetOperandsCount() const { | ||
| 465 | return operands.size(); | ||
| 466 | } | ||
| 467 | |||
| 468 | [[nodiscard]] const Node& operator[](std::size_t operand_index) const { | ||
| 469 | return operands.at(operand_index); | ||
| 470 | } | ||
| 471 | |||
| 472 | private: | ||
| 473 | OperationCode code{}; | ||
| 474 | Meta meta{}; | ||
| 475 | std::vector<Node> operands; | ||
| 476 | }; | ||
| 477 | |||
| 478 | /// Encloses inside any kind of node that returns a boolean conditionally-executed code | ||
| 479 | class ConditionalNode final : public AmendNode { | ||
| 480 | public: | ||
| 481 | explicit ConditionalNode(Node condition_, std::vector<Node>&& code_) | ||
| 482 | : condition{std::move(condition_)}, code{std::move(code_)} {} | ||
| 483 | |||
| 484 | [[nodiscard]] const Node& GetCondition() const { | ||
| 485 | return condition; | ||
| 486 | } | ||
| 487 | |||
| 488 | [[nodiscard]] const std::vector<Node>& GetCode() const { | ||
| 489 | return code; | ||
| 490 | } | ||
| 491 | |||
| 492 | private: | ||
| 493 | Node condition; ///< Condition to be satisfied | ||
| 494 | std::vector<Node> code; ///< Code to execute | ||
| 495 | }; | ||
| 496 | |||
| 497 | /// A general purpose register | ||
| 498 | class GprNode final { | ||
| 499 | public: | ||
| 500 | explicit constexpr GprNode(Tegra::Shader::Register index_) : index{index_} {} | ||
| 501 | |||
| 502 | [[nodiscard]] constexpr u32 GetIndex() const { | ||
| 503 | return static_cast<u32>(index); | ||
| 504 | } | ||
| 505 | |||
| 506 | private: | ||
| 507 | Tegra::Shader::Register index{}; | ||
| 508 | }; | ||
| 509 | |||
| 510 | /// A custom variable | ||
| 511 | class CustomVarNode final { | ||
| 512 | public: | ||
| 513 | explicit constexpr CustomVarNode(u32 index_) : index{index_} {} | ||
| 514 | |||
| 515 | [[nodiscard]] constexpr u32 GetIndex() const { | ||
| 516 | return index; | ||
| 517 | } | ||
| 518 | |||
| 519 | private: | ||
| 520 | u32 index{}; | ||
| 521 | }; | ||
| 522 | |||
| 523 | /// A 32-bits value that represents an immediate value | ||
| 524 | class ImmediateNode final { | ||
| 525 | public: | ||
| 526 | explicit constexpr ImmediateNode(u32 value_) : value{value_} {} | ||
| 527 | |||
| 528 | [[nodiscard]] constexpr u32 GetValue() const { | ||
| 529 | return value; | ||
| 530 | } | ||
| 531 | |||
| 532 | private: | ||
| 533 | u32 value{}; | ||
| 534 | }; | ||
| 535 | |||
| 536 | /// One of Maxwell's internal flags | ||
| 537 | class InternalFlagNode final { | ||
| 538 | public: | ||
| 539 | explicit constexpr InternalFlagNode(InternalFlag flag_) : flag{flag_} {} | ||
| 540 | |||
| 541 | [[nodiscard]] constexpr InternalFlag GetFlag() const { | ||
| 542 | return flag; | ||
| 543 | } | ||
| 544 | |||
| 545 | private: | ||
| 546 | InternalFlag flag{}; | ||
| 547 | }; | ||
| 548 | |||
| 549 | /// A predicate register, it can be negated without additional nodes | ||
| 550 | class PredicateNode final { | ||
| 551 | public: | ||
| 552 | explicit constexpr PredicateNode(Tegra::Shader::Pred index_, bool negated_) | ||
| 553 | : index{index_}, negated{negated_} {} | ||
| 554 | |||
| 555 | [[nodiscard]] constexpr Tegra::Shader::Pred GetIndex() const { | ||
| 556 | return index; | ||
| 557 | } | ||
| 558 | |||
| 559 | [[nodiscard]] constexpr bool IsNegated() const { | ||
| 560 | return negated; | ||
| 561 | } | ||
| 562 | |||
| 563 | private: | ||
| 564 | Tegra::Shader::Pred index{}; | ||
| 565 | bool negated{}; | ||
| 566 | }; | ||
| 567 | |||
| 568 | /// Attribute buffer memory (known as attributes or varyings in GLSL terms) | ||
| 569 | class AbufNode final { | ||
| 570 | public: | ||
| 571 | // Initialize for standard attributes (index is explicit). | ||
| 572 | explicit AbufNode(Tegra::Shader::Attribute::Index index_, u32 element_, Node buffer_ = {}) | ||
| 573 | : buffer{std::move(buffer_)}, index{index_}, element{element_} {} | ||
| 574 | |||
| 575 | // Initialize for physical attributes (index is a variable value). | ||
| 576 | explicit AbufNode(Node physical_address_, Node buffer_ = {}) | ||
| 577 | : physical_address{std::move(physical_address_)}, buffer{std::move(buffer_)} {} | ||
| 578 | |||
| 579 | [[nodiscard]] Tegra::Shader::Attribute::Index GetIndex() const { | ||
| 580 | return index; | ||
| 581 | } | ||
| 582 | |||
| 583 | [[nodiscard]] u32 GetElement() const { | ||
| 584 | return element; | ||
| 585 | } | ||
| 586 | |||
| 587 | [[nodiscard]] const Node& GetBuffer() const { | ||
| 588 | return buffer; | ||
| 589 | } | ||
| 590 | |||
| 591 | [[nodiscard]] bool IsPhysicalBuffer() const { | ||
| 592 | return static_cast<bool>(physical_address); | ||
| 593 | } | ||
| 594 | |||
| 595 | [[nodiscard]] const Node& GetPhysicalAddress() const { | ||
| 596 | return physical_address; | ||
| 597 | } | ||
| 598 | |||
| 599 | private: | ||
| 600 | Node physical_address; | ||
| 601 | Node buffer; | ||
| 602 | Tegra::Shader::Attribute::Index index{}; | ||
| 603 | u32 element{}; | ||
| 604 | }; | ||
| 605 | |||
| 606 | /// Patch memory (used to communicate tessellation stages). | ||
| 607 | class PatchNode final { | ||
| 608 | public: | ||
| 609 | explicit constexpr PatchNode(u32 offset_) : offset{offset_} {} | ||
| 610 | |||
| 611 | [[nodiscard]] constexpr u32 GetOffset() const { | ||
| 612 | return offset; | ||
| 613 | } | ||
| 614 | |||
| 615 | private: | ||
| 616 | u32 offset{}; | ||
| 617 | }; | ||
| 618 | |||
| 619 | /// Constant buffer node, usually mapped to uniform buffers in GLSL | ||
| 620 | class CbufNode final { | ||
| 621 | public: | ||
| 622 | explicit CbufNode(u32 index_, Node offset_) : index{index_}, offset{std::move(offset_)} {} | ||
| 623 | |||
| 624 | [[nodiscard]] u32 GetIndex() const { | ||
| 625 | return index; | ||
| 626 | } | ||
| 627 | |||
| 628 | [[nodiscard]] const Node& GetOffset() const { | ||
| 629 | return offset; | ||
| 630 | } | ||
| 631 | |||
| 632 | private: | ||
| 633 | u32 index{}; | ||
| 634 | Node offset; | ||
| 635 | }; | ||
| 636 | |||
| 637 | /// Local memory node | ||
| 638 | class LmemNode final { | ||
| 639 | public: | ||
| 640 | explicit LmemNode(Node address_) : address{std::move(address_)} {} | ||
| 641 | |||
| 642 | [[nodiscard]] const Node& GetAddress() const { | ||
| 643 | return address; | ||
| 644 | } | ||
| 645 | |||
| 646 | private: | ||
| 647 | Node address; | ||
| 648 | }; | ||
| 649 | |||
| 650 | /// Shared memory node | ||
| 651 | class SmemNode final { | ||
| 652 | public: | ||
| 653 | explicit SmemNode(Node address_) : address{std::move(address_)} {} | ||
| 654 | |||
| 655 | [[nodiscard]] const Node& GetAddress() const { | ||
| 656 | return address; | ||
| 657 | } | ||
| 658 | |||
| 659 | private: | ||
| 660 | Node address; | ||
| 661 | }; | ||
| 662 | |||
| 663 | /// Global memory node | ||
| 664 | class GmemNode final { | ||
| 665 | public: | ||
| 666 | explicit GmemNode(Node real_address_, Node base_address_, const GlobalMemoryBase& descriptor_) | ||
| 667 | : real_address{std::move(real_address_)}, base_address{std::move(base_address_)}, | ||
| 668 | descriptor{descriptor_} {} | ||
| 669 | |||
| 670 | [[nodiscard]] const Node& GetRealAddress() const { | ||
| 671 | return real_address; | ||
| 672 | } | ||
| 673 | |||
| 674 | [[nodiscard]] const Node& GetBaseAddress() const { | ||
| 675 | return base_address; | ||
| 676 | } | ||
| 677 | |||
| 678 | [[nodiscard]] const GlobalMemoryBase& GetDescriptor() const { | ||
| 679 | return descriptor; | ||
| 680 | } | ||
| 681 | |||
| 682 | private: | ||
| 683 | Node real_address; | ||
| 684 | Node base_address; | ||
| 685 | GlobalMemoryBase descriptor; | ||
| 686 | }; | ||
| 687 | |||
| 688 | /// Commentary, can be dropped | ||
| 689 | class CommentNode final { | ||
| 690 | public: | ||
| 691 | explicit CommentNode(std::string text_) : text{std::move(text_)} {} | ||
| 692 | |||
| 693 | [[nodiscard]] const std::string& GetText() const { | ||
| 694 | return text; | ||
| 695 | } | ||
| 696 | |||
| 697 | private: | ||
| 698 | std::string text; | ||
| 699 | }; | ||
| 700 | |||
| 701 | } // namespace VideoCommon::Shader | ||