| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 |
- // Copyright 2019 yuzu Emulator Project
- // Licensed under GPLv2 or any later version
- // Refer to the license.txt file included.
- #pragma once
- #include <array>
- #include <cstddef>
- #include <memory>
- #include <optional>
- #include <string>
- #include <tuple>
- #include <utility>
- #include <variant>
- #include <vector>
- #include "common/common_types.h"
- #include "video_core/engines/shader_bytecode.h"
- namespace VideoCommon::Shader {
- enum class OperationCode {
- Assign, /// (float& dest, float src) -> void
- Select, /// (MetaArithmetic, bool pred, float a, float b) -> float
- FAdd, /// (MetaArithmetic, float a, float b) -> float
- FMul, /// (MetaArithmetic, float a, float b) -> float
- FDiv, /// (MetaArithmetic, float a, float b) -> float
- FFma, /// (MetaArithmetic, float a, float b, float c) -> float
- FNegate, /// (MetaArithmetic, float a) -> float
- FAbsolute, /// (MetaArithmetic, float a) -> float
- FClamp, /// (MetaArithmetic, float value, float min, float max) -> float
- FCastHalf0, /// (MetaArithmetic, f16vec2 a) -> float
- FCastHalf1, /// (MetaArithmetic, f16vec2 a) -> float
- FMin, /// (MetaArithmetic, float a, float b) -> float
- FMax, /// (MetaArithmetic, float a, float b) -> float
- FCos, /// (MetaArithmetic, float a) -> float
- FSin, /// (MetaArithmetic, float a) -> float
- FExp2, /// (MetaArithmetic, float a) -> float
- FLog2, /// (MetaArithmetic, float a) -> float
- FInverseSqrt, /// (MetaArithmetic, float a) -> float
- FSqrt, /// (MetaArithmetic, float a) -> float
- FRoundEven, /// (MetaArithmetic, float a) -> float
- FFloor, /// (MetaArithmetic, float a) -> float
- FCeil, /// (MetaArithmetic, float a) -> float
- FTrunc, /// (MetaArithmetic, float a) -> float
- FCastInteger, /// (MetaArithmetic, int a) -> float
- FCastUInteger, /// (MetaArithmetic, uint a) -> float
- FSwizzleAdd, /// (float a, float b, uint mask) -> float
- IAdd, /// (MetaArithmetic, int a, int b) -> int
- IMul, /// (MetaArithmetic, int a, int b) -> int
- IDiv, /// (MetaArithmetic, int a, int b) -> int
- INegate, /// (MetaArithmetic, int a) -> int
- IAbsolute, /// (MetaArithmetic, int a) -> int
- IMin, /// (MetaArithmetic, int a, int b) -> int
- IMax, /// (MetaArithmetic, int a, int b) -> int
- ICastFloat, /// (MetaArithmetic, float a) -> int
- ICastUnsigned, /// (MetaArithmetic, uint a) -> int
- ILogicalShiftLeft, /// (MetaArithmetic, int a, uint b) -> int
- ILogicalShiftRight, /// (MetaArithmetic, int a, uint b) -> int
- IArithmeticShiftRight, /// (MetaArithmetic, int a, uint b) -> int
- IBitwiseAnd, /// (MetaArithmetic, int a, int b) -> int
- IBitwiseOr, /// (MetaArithmetic, int a, int b) -> int
- IBitwiseXor, /// (MetaArithmetic, int a, int b) -> int
- IBitwiseNot, /// (MetaArithmetic, int a) -> int
- IBitfieldInsert, /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int
- IBitfieldExtract, /// (MetaArithmetic, int value, int offset, int offset) -> int
- IBitCount, /// (MetaArithmetic, int) -> int
- IBitMSB, /// (MetaArithmetic, int) -> int
- UAdd, /// (MetaArithmetic, uint a, uint b) -> uint
- UMul, /// (MetaArithmetic, uint a, uint b) -> uint
- UDiv, /// (MetaArithmetic, uint a, uint b) -> uint
- UMin, /// (MetaArithmetic, uint a, uint b) -> uint
- UMax, /// (MetaArithmetic, uint a, uint b) -> uint
- UCastFloat, /// (MetaArithmetic, float a) -> uint
- UCastSigned, /// (MetaArithmetic, int a) -> uint
- ULogicalShiftLeft, /// (MetaArithmetic, uint a, uint b) -> uint
- ULogicalShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint
- UArithmeticShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint
- UBitwiseAnd, /// (MetaArithmetic, uint a, uint b) -> uint
- UBitwiseOr, /// (MetaArithmetic, uint a, uint b) -> uint
- UBitwiseXor, /// (MetaArithmetic, uint a, uint b) -> uint
- UBitwiseNot, /// (MetaArithmetic, uint a) -> uint
- UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint
- UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
- UBitCount, /// (MetaArithmetic, uint) -> uint
- UBitMSB, /// (MetaArithmetic, uint) -> uint
- HAdd, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
- HMul, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
- HFma, /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2
- HAbsolute, /// (f16vec2 a) -> f16vec2
- HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2
- HClamp, /// (f16vec2 src, float min, float max) -> f16vec2
- HCastFloat, /// (MetaArithmetic, float a) -> f16vec2
- HUnpack, /// (Tegra::Shader::HalfType, T value) -> f16vec2
- HMergeF32, /// (f16vec2 src) -> float
- HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2
- HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2
- HPack2, /// (float a, float b) -> f16vec2
- LogicalAssign, /// (bool& dst, bool src) -> void
- LogicalAnd, /// (bool a, bool b) -> bool
- LogicalOr, /// (bool a, bool b) -> bool
- LogicalXor, /// (bool a, bool b) -> bool
- LogicalNegate, /// (bool a) -> bool
- LogicalPick2, /// (bool2 pair, uint index) -> bool
- LogicalAnd2, /// (bool2 a) -> bool
- LogicalFLessThan, /// (float a, float b) -> bool
- LogicalFEqual, /// (float a, float b) -> bool
- LogicalFLessEqual, /// (float a, float b) -> bool
- LogicalFGreaterThan, /// (float a, float b) -> bool
- LogicalFNotEqual, /// (float a, float b) -> bool
- LogicalFGreaterEqual, /// (float a, float b) -> bool
- LogicalFIsNan, /// (float a) -> bool
- LogicalILessThan, /// (int a, int b) -> bool
- LogicalIEqual, /// (int a, int b) -> bool
- LogicalILessEqual, /// (int a, int b) -> bool
- LogicalIGreaterThan, /// (int a, int b) -> bool
- LogicalINotEqual, /// (int a, int b) -> bool
- LogicalIGreaterEqual, /// (int a, int b) -> bool
- LogicalULessThan, /// (uint a, uint b) -> bool
- LogicalUEqual, /// (uint a, uint b) -> bool
- LogicalULessEqual, /// (uint a, uint b) -> bool
- LogicalUGreaterThan, /// (uint a, uint b) -> bool
- LogicalUNotEqual, /// (uint a, uint b) -> bool
- LogicalUGreaterEqual, /// (uint a, uint b) -> bool
- Logical2HLessThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Logical2HEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Logical2HLessEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Logical2HGreaterThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Logical2HNotEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Logical2HGreaterEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Logical2HLessThanWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Logical2HEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Logical2HLessEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Logical2HGreaterThanWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Logical2HNotEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Logical2HGreaterEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
- Texture, /// (MetaTexture, float[N] coords) -> float4
- TextureLod, /// (MetaTexture, float[N] coords) -> float4
- TextureGather, /// (MetaTexture, float[N] coords) -> float4
- TextureQueryDimensions, /// (MetaTexture, float a) -> float4
- TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4
- TexelFetch, /// (MetaTexture, int[N], int) -> float4
- TextureGradient, /// (MetaTexture, float[N] coords, float[N*2] derivates) -> float4
- ImageLoad, /// (MetaImage, int[N] coords) -> void
- ImageStore, /// (MetaImage, int[N] coords) -> void
- AtomicImageAdd, /// (MetaImage, int[N] coords) -> void
- AtomicImageAnd, /// (MetaImage, int[N] coords) -> void
- AtomicImageOr, /// (MetaImage, int[N] coords) -> void
- AtomicImageXor, /// (MetaImage, int[N] coords) -> void
- AtomicImageExchange, /// (MetaImage, int[N] coords) -> void
- Branch, /// (uint branch_target) -> void
- BranchIndirect, /// (uint branch_target) -> void
- PushFlowStack, /// (uint branch_target) -> void
- PopFlowStack, /// () -> void
- Exit, /// () -> void
- Discard, /// () -> void
- EmitVertex, /// () -> void
- EndPrimitive, /// () -> void
- InvocationId, /// () -> int
- YNegate, /// () -> float
- LocalInvocationIdX, /// () -> uint
- LocalInvocationIdY, /// () -> uint
- LocalInvocationIdZ, /// () -> uint
- WorkGroupIdX, /// () -> uint
- WorkGroupIdY, /// () -> uint
- WorkGroupIdZ, /// () -> uint
- BallotThread, /// (bool) -> uint
- VoteAll, /// (bool) -> bool
- VoteAny, /// (bool) -> bool
- VoteEqual, /// (bool) -> bool
- ThreadId, /// () -> uint
- ShuffleIndexed, /// (uint value, uint index) -> uint
- MemoryBarrierGL, /// () -> void
- Amount,
- };
- enum class InternalFlag {
- Zero = 0,
- Sign = 1,
- Carry = 2,
- Overflow = 3,
- Amount = 4,
- };
- enum class MetaStackClass {
- Ssy,
- Pbk,
- };
- class OperationNode;
- class ConditionalNode;
- class GprNode;
- class ImmediateNode;
- class InternalFlagNode;
- 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, PatchNode, CbufNode,
- LmemNode, SmemNode, GmemNode, CommentNode>;
- using Node = std::shared_ptr<NodeData>;
- using Node4 = std::array<Node, 4>;
- using NodeBlock = std::vector<Node>;
- class Sampler {
- public:
- /// This constructor is for bound samplers
- constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type,
- bool is_array, bool is_shadow, bool is_buffer)
- : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow},
- is_buffer{is_buffer} {}
- /// This constructor is for bindless samplers
- constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type,
- bool is_array, bool is_shadow, bool is_buffer)
- : index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array},
- is_shadow{is_shadow}, is_buffer{is_buffer}, is_bindless{true} {}
- constexpr u32 GetIndex() const {
- return index;
- }
- constexpr u32 GetOffset() const {
- return offset;
- }
- constexpr u32 GetBuffer() const {
- return buffer;
- }
- constexpr Tegra::Shader::TextureType GetType() const {
- return type;
- }
- constexpr bool IsArray() const {
- return is_array;
- }
- constexpr bool IsShadow() const {
- return is_shadow;
- }
- constexpr bool IsBuffer() const {
- return is_buffer;
- }
- constexpr bool IsBindless() const {
- return is_bindless;
- }
- private:
- u32 index{}; ///< Emulated index given for the this sampler.
- u32 offset{}; ///< Offset in the const buffer from where the sampler is being read.
- u32 buffer{}; ///< Buffer where the bindless sampler is being read (unused on bound samplers).
- Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc)
- bool is_array{}; ///< Whether the texture is being sampled as an array texture or not.
- bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not.
- bool is_buffer{}; ///< Whether the texture is a texture buffer without sampler.
- bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not.
- };
- class Image final {
- public:
- /// This constructor is for bound images
- constexpr explicit Image(u32 index, u32 offset, Tegra::Shader::ImageType type)
- : index{index}, offset{offset}, type{type} {}
- /// This constructor is for bindless samplers
- constexpr explicit Image(u32 index, u32 offset, u32 buffer, Tegra::Shader::ImageType type)
- : index{index}, offset{offset}, buffer{buffer}, type{type}, is_bindless{true} {}
- void MarkWrite() {
- is_written = true;
- }
- void MarkRead() {
- is_read = true;
- }
- void MarkAtomic() {
- MarkWrite();
- MarkRead();
- is_atomic = true;
- }
- constexpr u32 GetIndex() const {
- return index;
- }
- constexpr u32 GetOffset() const {
- return offset;
- }
- constexpr u32 GetBuffer() const {
- return buffer;
- }
- constexpr Tegra::Shader::ImageType GetType() const {
- return type;
- }
- constexpr bool IsBindless() const {
- return is_bindless;
- }
- constexpr bool IsWritten() const {
- return is_written;
- }
- constexpr bool IsRead() const {
- return is_read;
- }
- constexpr bool IsAtomic() const {
- return is_atomic;
- }
- private:
- u32 index{};
- u32 offset{};
- u32 buffer{};
- Tegra::Shader::ImageType type{};
- bool is_bindless{};
- bool is_written{};
- bool is_read{};
- bool is_atomic{};
- };
- struct GlobalMemoryBase {
- u32 cbuf_index{};
- u32 cbuf_offset{};
- bool operator<(const GlobalMemoryBase& rhs) const {
- return std::tie(cbuf_index, cbuf_offset) < std::tie(rhs.cbuf_index, rhs.cbuf_offset);
- }
- };
- /// Parameters describing an arithmetic operation
- struct MetaArithmetic {
- bool precise{}; ///< Whether the operation can be constraint or not
- };
- /// Parameters describing a texture sampler
- struct MetaTexture {
- const Sampler& sampler;
- Node array;
- Node depth_compare;
- std::vector<Node> aoffi;
- std::vector<Node> ptp;
- std::vector<Node> derivates;
- Node bias;
- Node lod;
- Node component{};
- u32 element{};
- };
- struct MetaImage {
- const Image& image;
- std::vector<Node> values;
- u32 element{};
- };
- /// Parameters that modify an operation but are not part of any particular operand
- using Meta =
- std::variant<MetaArithmetic, MetaTexture, MetaImage, MetaStackClass, Tegra::Shader::HalfType>;
- class AmendNode {
- public:
- std::optional<u32> GetAmendIndex() const {
- if (amend_index == amend_null_index) {
- return std::nullopt;
- }
- return {amend_index};
- }
- void SetAmendIndex(u32 index) {
- amend_index = index;
- }
- void ClearAmend() {
- amend_index = amend_null_index;
- }
- private:
- static constexpr u32 amend_null_index = 0xFFFFFFFF;
- u32 amend_index{amend_null_index};
- };
- /// Holds any kind of operation that can be done in the IR
- class OperationNode final : public AmendNode {
- public:
- explicit OperationNode(OperationCode code) : OperationNode(code, Meta{}) {}
- explicit OperationNode(OperationCode code, Meta meta)
- : OperationNode(code, std::move(meta), std::vector<Node>{}) {}
- explicit OperationNode(OperationCode code, std::vector<Node> operands)
- : OperationNode(code, Meta{}, std::move(operands)) {}
- explicit OperationNode(OperationCode code, Meta meta, std::vector<Node> operands)
- : code{code}, meta{std::move(meta)}, operands{std::move(operands)} {}
- template <typename... Args>
- explicit OperationNode(OperationCode code, Meta meta, Args&&... operands)
- : code{code}, meta{std::move(meta)}, operands{operands...} {}
- OperationCode GetCode() const {
- return code;
- }
- const Meta& GetMeta() const {
- return meta;
- }
- std::size_t GetOperandsCount() const {
- return operands.size();
- }
- const Node& operator[](std::size_t operand_index) const {
- return operands.at(operand_index);
- }
- private:
- OperationCode code{};
- Meta meta{};
- std::vector<Node> operands;
- };
- /// Encloses inside any kind of node that returns a boolean conditionally-executed code
- class ConditionalNode final : public AmendNode {
- public:
- explicit ConditionalNode(Node condition, std::vector<Node>&& code)
- : condition{std::move(condition)}, code{std::move(code)} {}
- const Node& GetCondition() const {
- return condition;
- }
- const std::vector<Node>& GetCode() const {
- return code;
- }
- private:
- Node condition; ///< Condition to be satisfied
- std::vector<Node> code; ///< Code to execute
- };
- /// A general purpose register
- class GprNode final {
- public:
- explicit constexpr GprNode(Tegra::Shader::Register index) : index{index} {}
- u32 GetIndex() const {
- return static_cast<u32>(index);
- }
- private:
- Tegra::Shader::Register index{};
- };
- /// A 32-bits value that represents an immediate value
- class ImmediateNode final {
- public:
- explicit constexpr ImmediateNode(u32 value) : value{value} {}
- u32 GetValue() const {
- return value;
- }
- private:
- u32 value{};
- };
- /// One of Maxwell's internal flags
- class InternalFlagNode final {
- public:
- explicit constexpr InternalFlagNode(InternalFlag flag) : flag{flag} {}
- InternalFlag GetFlag() const {
- return flag;
- }
- private:
- InternalFlag flag{};
- };
- /// A predicate register, it can be negated without additional nodes
- class PredicateNode final {
- public:
- explicit constexpr PredicateNode(Tegra::Shader::Pred index, bool negated)
- : index{index}, negated{negated} {}
- Tegra::Shader::Pred GetIndex() const {
- return index;
- }
- bool IsNegated() const {
- return negated;
- }
- private:
- Tegra::Shader::Pred index{};
- bool negated{};
- };
- /// Attribute buffer memory (known as attributes or varyings in GLSL terms)
- class AbufNode final {
- public:
- // Initialize for standard attributes (index is explicit).
- explicit AbufNode(Tegra::Shader::Attribute::Index index, u32 element, Node buffer = {})
- : buffer{std::move(buffer)}, index{index}, element{element} {}
- // Initialize for physical attributes (index is a variable value).
- explicit AbufNode(Node physical_address, Node buffer = {})
- : physical_address{std::move(physical_address)}, buffer{std::move(buffer)} {}
- Tegra::Shader::Attribute::Index GetIndex() const {
- return index;
- }
- u32 GetElement() const {
- return element;
- }
- const Node& GetBuffer() const {
- return buffer;
- }
- bool IsPhysicalBuffer() const {
- return static_cast<bool>(physical_address);
- }
- const Node& GetPhysicalAddress() const {
- return physical_address;
- }
- private:
- Node physical_address;
- Node buffer;
- Tegra::Shader::Attribute::Index index{};
- 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:
- explicit CbufNode(u32 index, Node offset) : index{index}, offset{std::move(offset)} {}
- u32 GetIndex() const {
- return index;
- }
- const Node& GetOffset() const {
- return offset;
- }
- private:
- u32 index{};
- Node offset;
- };
- /// Local memory node
- class LmemNode final {
- public:
- explicit LmemNode(Node address) : address{std::move(address)} {}
- const Node& GetAddress() const {
- return address;
- }
- private:
- Node address;
- };
- /// Shared memory node
- class SmemNode final {
- public:
- explicit SmemNode(Node address) : address{std::move(address)} {}
- const Node& GetAddress() const {
- return address;
- }
- private:
- Node address;
- };
- /// Global memory node
- class GmemNode final {
- public:
- explicit GmemNode(Node real_address, Node base_address, const GlobalMemoryBase& descriptor)
- : real_address{std::move(real_address)}, base_address{std::move(base_address)},
- descriptor{descriptor} {}
- const Node& GetRealAddress() const {
- return real_address;
- }
- const Node& GetBaseAddress() const {
- return base_address;
- }
- const GlobalMemoryBase& GetDescriptor() const {
- return descriptor;
- }
- private:
- Node real_address;
- Node base_address;
- GlobalMemoryBase descriptor;
- };
- /// Commentary, can be dropped
- class CommentNode final : public AmendNode {
- public:
- explicit CommentNode(std::string text) : text{std::move(text)} {}
- const std::string& GetText() const {
- return text;
- }
- private:
- std::string text;
- };
- } // namespace VideoCommon::Shader
|