| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // DxilSignatureAllocator.h //
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- // This file is distributed under the University of Illinois Open Source //
- // License. See LICENSE.TXT for details. //
- // //
- // Classes used for allocating signature elements. //
- // //
- ///////////////////////////////////////////////////////////////////////////////
- #pragma once
- #include "dxc/DXIL/DxilConstants.h"
- #include <vector>
- namespace hlsl {
- class DxilSignatureAllocator {
- public:
- class PackElement {
- public:
- virtual ~PackElement() {}
- virtual uint32_t GetID() const = 0;
- virtual DXIL::SemanticKind GetKind() const = 0;
- virtual DXIL::InterpolationMode GetInterpolationMode() const = 0;
- virtual DXIL::SemanticInterpretationKind GetInterpretation() const = 0;
- virtual DXIL::SignatureDataWidth GetDataBitWidth() const = 0;
- virtual uint32_t GetRows() const = 0;
- virtual uint32_t GetCols() const = 0;
- virtual bool IsAllocated() const = 0;
- virtual uint32_t GetStartRow() const = 0;
- virtual uint32_t GetStartCol() const = 0;
- virtual void ClearLocation() = 0;
- virtual void SetLocation(uint32_t StartRow, uint32_t StartCol) = 0;
- };
- class DummyElement : public PackElement {
- public:
- uint32_t id;
- uint32_t rows, cols;
- uint32_t row, col;
- DXIL::SemanticKind kind;
- DXIL::InterpolationMode interpolation;
- DXIL::SemanticInterpretationKind interpretation;
- DXIL::SignatureDataWidth dataBitWidth;
- uint32_t indexFlags;
- public:
- DummyElement(uint32_t index = 0) : id(index), rows(1), cols(1), row((uint32_t)-1), col((uint32_t)-1),
- kind(DXIL::SemanticKind::Arbitrary),
- interpolation(DXIL::InterpolationMode::Undefined),
- interpretation(DXIL::SemanticInterpretationKind::Arb),
- dataBitWidth(DXIL::SignatureDataWidth::Undefined),
- indexFlags(0)
- {}
- ~DummyElement() override {}
- uint32_t GetID() const override { return id; }
- DXIL::SemanticKind GetKind() const override { return kind; }
- DXIL::InterpolationMode GetInterpolationMode() const override { return interpolation; }
- DXIL::SemanticInterpretationKind GetInterpretation() const override { return interpretation; }
- DXIL::SignatureDataWidth GetDataBitWidth() const override { return dataBitWidth; }
- uint32_t GetRows() const override { return rows; }
- uint32_t GetCols() const override { return cols; }
- bool IsAllocated() const override { return row != (uint32_t)-1; }
- uint32_t GetStartRow() const override { return row; }
- uint32_t GetStartCol() const override { return col; }
- void ClearLocation() override { row = col = (uint32_t)-1; }
- void SetLocation(uint32_t Row, uint32_t Col) override { row = Row; col = Col; }
- };
- // index flags
- static const uint8_t kIndexedUp = 1 << 0; // Indexing continues upwards
- static const uint8_t kIndexedDown = 1 << 1; // Indexing continues downwards
- static uint8_t GetIndexFlags(unsigned row, unsigned rows) {
- return ((row > 0) ? kIndexedUp : 0) | ((row < rows - 1) ? kIndexedDown : 0);
- }
- // element flags
- static const uint8_t kEFOccupied = 1 << 0;
- static const uint8_t kEFArbitrary = 1 << 1;
- static const uint8_t kEFSGV = 1 << 2;
- static const uint8_t kEFSV = 1 << 3;
- static const uint8_t kEFTessFactor = 1 << 4;
- static const uint8_t kEFClipCull = 1 << 5;
- static const uint8_t kEFConflictsWithIndexed = kEFSGV | kEFSV;
- static uint8_t GetElementFlags(const PackElement *SE);
- // The following two functions enforce the rules of component ordering when packing different
- // kinds of elements into the same register.
- // given element flags, return element flags that conflict when placed to the left of the element
- static uint8_t GetConflictFlagsLeft(uint8_t flags);
- // given element flags, return element flags that conflict when placed to the right of the element
- static uint8_t GetConflictFlagsRight(uint8_t flags);
- enum ConflictType {
- kNoConflict = 0,
- kConflictsWithIndexed,
- kConflictsWithIndexedTessFactor,
- kConflictsWithInterpolationMode,
- kInsufficientFreeComponents,
- kOverlapElement,
- kIllegalComponentOrder,
- kConflictFit,
- kConflictDataWidth,
- };
- struct PackedRegister {
- // Flags:
- // - for occupied components, they signify element flags
- // - for unoccupied components, they signify conflict flags
- uint8_t Flags[4];
- DXIL::InterpolationMode Interp : 8;
- uint8_t IndexFlags : 2;
- uint8_t IndexingFixed : 1;
- DXIL::SignatureDataWidth DataWidth; // length of each scalar type in bytes. (2 or 4 for now)
- PackedRegister();
- ConflictType DetectRowConflict(uint8_t flags, uint8_t indexFlags, DXIL::InterpolationMode interp, unsigned width, DXIL::SignatureDataWidth dataWidth);
- ConflictType DetectColConflict(uint8_t flags, unsigned col, unsigned width);
- void PlaceElement(uint8_t flags, uint8_t indexFlags, DXIL::InterpolationMode interp, unsigned col, unsigned width, DXIL::SignatureDataWidth dataWidth);
- };
- DxilSignatureAllocator(unsigned numRegisters, bool useMinPrecision);
- bool GetIgnoreIndexing() const { return m_bIgnoreIndexing; }
- void SetIgnoreIndexing(bool ignoreIndexing) { m_bIgnoreIndexing = ignoreIndexing; }
- ConflictType DetectRowConflict(const PackElement *SE, unsigned row);
- ConflictType DetectColConflict(const PackElement *SE, unsigned row, unsigned col);
- void PlaceElement(const PackElement *SE, unsigned row, unsigned col);
- // FindNext/PackNext return found/packed location + element rows if found,
- // otherwise, they return 0.
- unsigned FindNext(unsigned &foundRow, unsigned &foundCol,
- PackElement* SE, unsigned startRow, unsigned numRows, unsigned startCol = 0);
- unsigned PackNext(PackElement* SE, unsigned startRow, unsigned numRows, unsigned startCol = 0);
- // Simple greedy in-order packer used by PackOptimized
- unsigned PackGreedy(std::vector<PackElement*> elements, unsigned startRow, unsigned numRows, unsigned startCol = 0);
- // Optimized packing algorithm - appended elements may affect positions of prior elements.
- unsigned PackOptimized(std::vector<PackElement*> elements, unsigned startRow, unsigned numRows);
- // Pack in a prefix-stable way - appended elements do not affect positions of prior elements.
- unsigned PackPrefixStable(std::vector<PackElement*> elements, unsigned startRow, unsigned numRows);
- bool UseMinPrecision() const { return m_bUseMinPrecision; }
- protected:
- std::vector<PackedRegister> m_Registers;
- bool m_bIgnoreIndexing;
- bool m_bUseMinPrecision;
- };
- } // namespace hlsl
|