mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-12 13:08:50 +01:00
276 lines
6.9 KiB
C++
276 lines
6.9 KiB
C++
#pragma once
|
|
|
|
#include "dxso_common.h"
|
|
#include "dxso_enums.h"
|
|
#include "dxso_code.h"
|
|
|
|
namespace dxvk {
|
|
|
|
constexpr size_t DxsoMaxTempRegs = 32;
|
|
constexpr size_t DxsoMaxTextureRegs = 10;
|
|
constexpr size_t DxsoMaxInterfaceRegs = 16;
|
|
constexpr size_t DxsoMaxOperandCount = 8;
|
|
|
|
constexpr uint32_t DxsoRegModifierShift = 24;
|
|
|
|
class DxsoDecodeContext;
|
|
|
|
/**
|
|
* \brief Source operand modifiers
|
|
*
|
|
* These are applied after loading
|
|
* an operand register.
|
|
*/
|
|
enum class DxsoRegModifier : uint32_t {
|
|
None = 0, // r
|
|
Neg = 1, // -r
|
|
Bias = 2, // r - 0.5
|
|
BiasNeg = 3, // -(r - 0.5)
|
|
Sign = 4, // fma(r, 2.0f, -1.0f)
|
|
SignNeg = 5, // -fma(r, 2.0f, -1.0f)
|
|
Comp = 6, // 1 - r
|
|
X2 = 7, // r * 2
|
|
X2Neg = 8, // -r * 2
|
|
Dz = 9, // r / r.z
|
|
Dw = 10, // r / r.w
|
|
Abs = 11, // abs(r)
|
|
AbsNeg = 12, // -abs(r)
|
|
Not = 13, // !r
|
|
};
|
|
|
|
enum class DxsoInstructionArgumentType : uint16_t {
|
|
Source,
|
|
Destination
|
|
};
|
|
|
|
enum class DxsoComparison : uint32_t {
|
|
// < = >
|
|
Never = 0, // 0 0 0
|
|
GreaterThan = 1, // 0 0 1
|
|
Equal = 2, // 0 1 0
|
|
GreaterEqual = 3, // 0 1 1
|
|
LessThan = 4, // 1 0 0
|
|
NotEqual = 5, // 1 0 1
|
|
LessEqual = 6, // 1 1 0
|
|
Always = 7 // 1 1 1
|
|
};
|
|
|
|
enum class DxsoTexLdMode : uint32_t {
|
|
Regular = 0,
|
|
Project = 1,
|
|
Bias = 2
|
|
};
|
|
|
|
union DxsoOpcodeSpecificData {
|
|
DxsoComparison comparison;
|
|
DxsoTexLdMode texld;
|
|
|
|
uint32_t uint32;
|
|
};
|
|
|
|
struct DxsoShaderInstruction {
|
|
DxsoOpcode opcode;
|
|
bool predicated;
|
|
bool coissue;
|
|
DxsoOpcodeSpecificData specificData;
|
|
|
|
uint32_t tokenLength;
|
|
};
|
|
|
|
struct DxsoRegisterId {
|
|
DxsoRegisterType type;
|
|
uint32_t num;
|
|
|
|
bool operator == (const DxsoRegisterId& other) const { return type == other.type && num == other.num; }
|
|
bool operator != (const DxsoRegisterId& other) const { return type != other.type || num != other.num; }
|
|
};
|
|
|
|
class DxsoRegMask {
|
|
|
|
public:
|
|
|
|
DxsoRegMask(uint8_t mask)
|
|
: m_mask(mask) { }
|
|
|
|
DxsoRegMask(bool x, bool y, bool z, bool w)
|
|
: m_mask((x ? 0x1 : 0) | (y ? 0x2 : 0)
|
|
| (z ? 0x4 : 0) | (w ? 0x8 : 0)) { }
|
|
|
|
bool operator [] (uint32_t id) const {
|
|
return ((m_mask & (1u << id)) != 0);
|
|
}
|
|
|
|
uint32_t popCount() const {
|
|
const uint8_t n[16] = { 0, 1, 1, 2, 1, 2, 2, 3,
|
|
1, 2, 2, 3, 2, 3, 3, 4 };
|
|
return n[m_mask & 0xF];
|
|
}
|
|
|
|
uint32_t firstSet() const {
|
|
const uint8_t n[16] = { 4, 0, 1, 0, 2, 0, 1, 0,
|
|
3, 0, 1, 0, 2, 0, 1, 0 };
|
|
return n[m_mask & 0xF];
|
|
}
|
|
|
|
uint32_t minComponents() const {
|
|
const uint8_t n[16] = { 0, 1, 2, 2, 3, 3, 3, 3,
|
|
4, 4, 4, 4, 4, 4, 4, 4 };
|
|
return n[m_mask & 0xF];
|
|
}
|
|
|
|
bool operator == (const DxsoRegMask& other) const { return m_mask == other.m_mask; }
|
|
bool operator != (const DxsoRegMask& other) const { return m_mask != other.m_mask; }
|
|
|
|
private:
|
|
|
|
uint8_t m_mask;
|
|
|
|
};
|
|
|
|
const DxsoRegMask IdentityWriteMask = DxsoRegMask(true, true, true, true);
|
|
|
|
class DxsoRegSwizzle {
|
|
|
|
public:
|
|
|
|
DxsoRegSwizzle(uint8_t mask)
|
|
: m_mask(mask) { }
|
|
|
|
DxsoRegSwizzle(uint32_t x, uint32_t y, uint32_t z, uint32_t w)
|
|
: m_mask((x << 0) | (y << 2) | (z << 4) | (w << 6)) {}
|
|
|
|
uint32_t operator [] (uint32_t id) const {
|
|
return (m_mask >> (id + id)) & 0x3;
|
|
}
|
|
|
|
bool operator == (const DxsoRegSwizzle& other) const { return m_mask == other.m_mask; }
|
|
bool operator != (const DxsoRegSwizzle& other) const { return m_mask != other.m_mask; }
|
|
|
|
private:
|
|
|
|
uint8_t m_mask;
|
|
|
|
};
|
|
|
|
const DxsoRegSwizzle IdentitySwizzle{ 0, 1, 2, 3 };
|
|
|
|
struct DxsoBaseRegister {
|
|
DxsoRegisterId id = { DxsoRegisterType::Temp, 0 };
|
|
bool centroid = false;
|
|
bool partialPrecision = false;
|
|
bool saturate = false;
|
|
DxsoRegModifier modifier = DxsoRegModifier::None;
|
|
DxsoRegMask mask = IdentityWriteMask;
|
|
DxsoRegSwizzle swizzle = IdentitySwizzle;
|
|
int8_t shift = 0;
|
|
};
|
|
|
|
struct DxsoRegister : public DxsoBaseRegister {
|
|
bool hasRelative = false;
|
|
DxsoBaseRegister relative;
|
|
};
|
|
|
|
struct DxsoSemantic {
|
|
DxsoUsage usage;
|
|
uint32_t usageIndex;
|
|
|
|
bool operator== (const DxsoSemantic& b) const;
|
|
bool operator!= (const DxsoSemantic& b) const;
|
|
};
|
|
|
|
struct DxsoDeclaration {
|
|
DxsoSemantic semantic;
|
|
|
|
DxsoTextureType textureType;
|
|
};
|
|
|
|
union DxsoDefinition {
|
|
float float32[4];
|
|
int32_t int32[4];
|
|
|
|
// Not a type we actually use in compiler, but used for decoding.
|
|
uint32_t uint32[4];
|
|
};
|
|
|
|
struct DxsoInstructionContext {
|
|
uint32_t instructionIdx;
|
|
|
|
DxsoShaderInstruction instruction;
|
|
|
|
DxsoRegister pred;
|
|
|
|
DxsoRegister dst;
|
|
std::array<
|
|
DxsoRegister,
|
|
DxsoMaxOperandCount> src;
|
|
|
|
DxsoDefinition def;
|
|
|
|
DxsoDeclaration dcl;
|
|
};
|
|
|
|
class DxsoDecodeContext {
|
|
|
|
public:
|
|
|
|
DxsoDecodeContext(const DxsoProgramInfo& programInfo)
|
|
: m_programInfo( programInfo ) {
|
|
m_ctx.instructionIdx = 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Retrieves current instruction context
|
|
*
|
|
* This is only valid after a call to \ref decode.
|
|
* \returns Reference to last decoded instruction & its context
|
|
*/
|
|
const DxsoInstructionContext& getInstructionContext() const {
|
|
return m_ctx;
|
|
}
|
|
|
|
const DxsoProgramInfo& getProgramInfo() const {
|
|
return m_programInfo;
|
|
}
|
|
|
|
/**
|
|
* \brief Decodes an instruction
|
|
*
|
|
* This also advances the given code slice by the
|
|
* number of dwords consumed by the instruction.
|
|
* \param [in] code Code slice
|
|
*/
|
|
bool decodeInstruction(DxsoCodeIter& iter);
|
|
|
|
private:
|
|
|
|
uint32_t decodeInstructionLength(uint32_t token);
|
|
|
|
void decodeBaseRegister(
|
|
DxsoBaseRegister& reg,
|
|
uint32_t token);
|
|
void decodeGenericRegister(
|
|
DxsoRegister& reg,
|
|
uint32_t token);
|
|
void decodeRelativeRegister(
|
|
DxsoBaseRegister& reg,
|
|
uint32_t token);
|
|
|
|
// Returns whether an extra token was read.
|
|
bool decodeDestinationRegister(DxsoCodeIter& iter);
|
|
bool decodeSourceRegister(uint32_t i, DxsoCodeIter& iter);
|
|
void decodePredicateRegister(DxsoCodeIter& iter);
|
|
|
|
void decodeDeclaration(DxsoCodeIter& iter);
|
|
void decodeDefinition(DxsoOpcode opcode, DxsoCodeIter& iter);
|
|
|
|
bool relativeAddressingUsesToken(DxsoInstructionArgumentType type);
|
|
|
|
const DxsoProgramInfo& m_programInfo;
|
|
|
|
DxsoInstructionContext m_ctx;
|
|
|
|
};
|
|
|
|
std::ostream& operator << (std::ostream& os, DxsoUsage usage);
|
|
|
|
} |