mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-18 11:52:12 +01:00
[dxbc] Added helper classes for DXBC decoding
This commit is contained in:
parent
1bf05d3687
commit
6954cfd84c
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxbc_common.h"
|
||||
#include "dxbc_instruction.h"
|
||||
#include "dxbc_decoder.h"
|
||||
#include "dxbc_reader.h"
|
||||
|
||||
namespace dxvk {
|
||||
@ -24,12 +24,12 @@ namespace dxvk {
|
||||
return m_version;
|
||||
}
|
||||
|
||||
DxbcInstructionIterator begin() const {
|
||||
return DxbcInstructionIterator(m_code.data());
|
||||
DxbcDecoder begin() const {
|
||||
return DxbcDecoder(m_code.data(), m_code.size());
|
||||
}
|
||||
|
||||
DxbcInstructionIterator end() const {
|
||||
return DxbcInstructionIterator(m_code.data() + m_code.size());
|
||||
DxbcDecoder end() const {
|
||||
return DxbcDecoder();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -4,6 +4,8 @@ namespace dxvk {
|
||||
|
||||
DxbcCompiler::DxbcCompiler(DxbcProgramVersion version)
|
||||
: m_version(version) {
|
||||
m_entryPointId = m_counter.nextId();
|
||||
|
||||
this->declareCapabilities();
|
||||
this->declareMemoryModel();
|
||||
}
|
||||
@ -14,9 +16,8 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxbcCompiler::processInstruction(DxbcInstruction ins) {
|
||||
Logger::info(str::format(
|
||||
static_cast<uint32_t>(ins.opcode())));
|
||||
bool DxbcCompiler::processInstruction(DxbcInstruction ins) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,8 +3,12 @@
|
||||
#include "dxbc_chunk_shex.h"
|
||||
|
||||
#include "../spirv/gen/spirv_gen_capability.h"
|
||||
#include "../spirv/gen/spirv_gen_constant.h"
|
||||
#include "../spirv/gen/spirv_gen_debuginfo.h"
|
||||
#include "../spirv/gen/spirv_gen_decoration.h"
|
||||
#include "../spirv/gen/spirv_gen_entrypoint.h"
|
||||
#include "../spirv/gen/spirv_gen_typeinfo.h"
|
||||
#include "../spirv/gen/spirv_gen_variable.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
@ -20,11 +24,16 @@ namespace dxvk {
|
||||
DxbcCompiler(DxbcProgramVersion version);
|
||||
~DxbcCompiler();
|
||||
|
||||
DxbcCompiler (DxbcCompiler&&) = delete;
|
||||
DxbcCompiler& operator = (DxbcCompiler&&) = delete;
|
||||
|
||||
/**
|
||||
* \brief Processes a single instruction
|
||||
*
|
||||
* \param [in] ins The instruction
|
||||
* \returns \c true on success
|
||||
*/
|
||||
void processInstruction(DxbcInstruction ins);
|
||||
bool processInstruction(DxbcInstruction ins);
|
||||
|
||||
/**
|
||||
* \brief Creates actual shader object
|
||||
@ -41,9 +50,17 @@ namespace dxvk {
|
||||
|
||||
SpirvCapabilities m_spvCapabilities;
|
||||
SpirvEntryPoint m_spvEntryPoints;
|
||||
SpirvDebugInfo m_spvDebugInfo;
|
||||
SpirvDecorations m_spvDecorations;
|
||||
SpirvTypeInfo m_spvTypeInfo;
|
||||
SpirvConstants m_spvConstants;
|
||||
SpirvVariables m_spvVariables;
|
||||
SpirvCodeBuffer m_spvCode;
|
||||
|
||||
uint32_t m_entryPointId = 0;
|
||||
|
||||
bool handleDcl(DxbcInstruction ins);
|
||||
|
||||
void declareCapabilities();
|
||||
void declareMemoryModel();
|
||||
|
||||
|
47
src/dxbc/dxbc_decoder.cpp
Normal file
47
src/dxbc/dxbc_decoder.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "dxbc_decoder.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxbcInstruction::DxbcInstruction(
|
||||
const uint32_t* code,
|
||||
uint32_t size)
|
||||
: m_code(code), m_size(size) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxbcInstruction::getWord(uint32_t id) const {
|
||||
return id < m_size ? m_code[id] : 0;
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxbcInstruction::length() const {
|
||||
const DxbcOpcodeToken token(getWord(0));
|
||||
return token.opcode() != DxbcOpcode::CustomData
|
||||
? token.length()
|
||||
: getWord(1);
|
||||
}
|
||||
|
||||
|
||||
DxbcDecoder::DxbcDecoder(const uint32_t* code, uint32_t size)
|
||||
: m_code(size != 0 ? code : nullptr), m_size(size) { }
|
||||
|
||||
|
||||
DxbcDecoder& DxbcDecoder::operator ++ () {
|
||||
auto len = DxbcInstruction(m_code, m_size).length();
|
||||
if (len < m_size) {
|
||||
m_code += len;
|
||||
m_size -= len;
|
||||
} else {
|
||||
m_code = nullptr;
|
||||
m_size = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DxbcInstruction DxbcDecoder::operator * () const {
|
||||
return DxbcInstruction(m_code, m_size);
|
||||
}
|
||||
|
||||
}
|
442
src/dxbc/dxbc_decoder.h
Normal file
442
src/dxbc/dxbc_decoder.h
Normal file
@ -0,0 +1,442 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "dxbc_enums.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief DXBC instruction token
|
||||
*
|
||||
* Initial token at the beginning of each instruction.
|
||||
* This encodes the actual op code, the length of the
|
||||
* entire instruction in DWORDs, as well as some flags
|
||||
* controlling the specific instruction.
|
||||
*/
|
||||
class DxbcOpcodeToken {
|
||||
|
||||
public:
|
||||
|
||||
DxbcOpcodeToken() { }
|
||||
DxbcOpcodeToken(uint32_t token)
|
||||
: m_token(token) { }
|
||||
|
||||
/**
|
||||
* \brief Opcode
|
||||
* \returns Opcode
|
||||
*/
|
||||
DxbcOpcode opcode() const {
|
||||
return static_cast<DxbcOpcode>(
|
||||
bit::extract(m_token, 0, 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Control info
|
||||
*
|
||||
* Instruction-specific control info. Undefined
|
||||
* if the opcode is \c DxbcOpcode::CustomData.
|
||||
* \returns Control info
|
||||
*/
|
||||
uint32_t control() const {
|
||||
return bit::extract(m_token, 11, 23);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Instruction length
|
||||
*
|
||||
* Undefind if the opcode is \c DxbcOpcode::CustomData.
|
||||
* In that case, the instruction length will be stored
|
||||
* in the DWORD immediately following the opcode token.
|
||||
* \returns Instruction length, in DWORDs
|
||||
*/
|
||||
uint32_t length() const {
|
||||
return bit::extract(m_token, 24, 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks whether the opcode is extended
|
||||
*
|
||||
* Additional information is encoded in extended
|
||||
* opcode tokens if this flag is set. Note that
|
||||
* multiple extended opcode tokens may be chained.
|
||||
* \returns \c true if the opcode is extended.
|
||||
*/
|
||||
bool isExtended() const {
|
||||
return !!bit::extract(m_token, 31, 31);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t m_token = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief DXBC extended instruction token
|
||||
*
|
||||
* Some instruction may encode additional control
|
||||
* modifiers in extended opcode tokens. The format
|
||||
* of these tokens differs from that of the the
|
||||
* initial opcode tokens.
|
||||
*/
|
||||
class DxbcOpcodeTokenExt {
|
||||
|
||||
public:
|
||||
|
||||
DxbcOpcodeTokenExt() { }
|
||||
DxbcOpcodeTokenExt(uint32_t token)
|
||||
: m_token(token) { }
|
||||
|
||||
/**
|
||||
* \brief Control info
|
||||
*
|
||||
* Instruction-specific control info. Undefined
|
||||
* if the opcode is \c DxbcOpcode::CustomData.
|
||||
* \returns Control info
|
||||
*/
|
||||
uint32_t control() const {
|
||||
return bit::extract(m_token, 6, 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Extended opcode length
|
||||
*
|
||||
* Number of DWORDs that belong to this extended
|
||||
* opcode information. Currently, there are no
|
||||
* extended opcodes with a length greater than 1.
|
||||
* \returns Exteded opcode length, in DWORDs
|
||||
*/
|
||||
uint32_t length() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks whether there are additional modifiers
|
||||
* \returns \c true if the extended opcode is extended
|
||||
*/
|
||||
bool isExtended() const {
|
||||
return !!bit::extract(m_token, 31, 31);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t m_token = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Operand token
|
||||
*
|
||||
* Stores general information about one operand of an
|
||||
* instruction. Like opcode tokens, operand tokens may
|
||||
* be extended.
|
||||
*/
|
||||
class DxbcOperandToken {
|
||||
|
||||
public:
|
||||
|
||||
DxbcOperandToken(uint32_t token)
|
||||
: m_token(token) { }
|
||||
|
||||
/**
|
||||
* \brief Number of operand components
|
||||
*
|
||||
* The number of components that the operand
|
||||
* has. Can be zero, one, or four.
|
||||
* \returns Number of components
|
||||
*/
|
||||
DxbcOperandNumComponents numComponents() const {
|
||||
return static_cast<DxbcOperandNumComponents>(
|
||||
bit::extract(m_token, 0, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Component selection mode
|
||||
*
|
||||
* Operands can be either masked so that some components
|
||||
* will not be used, or they can be swizzled so that only
|
||||
* a given set of components is used.
|
||||
* \returns Component selection mode
|
||||
*/
|
||||
DxbcOperandComponentSelectionMode selectionMode() const {
|
||||
return static_cast<DxbcOperandComponentSelectionMode>(
|
||||
bit::extract(m_token, 2, 3));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Operand type
|
||||
*
|
||||
* Selects the type of the operand, i.e. whether the
|
||||
* operand is a temporary register, a shader resource
|
||||
* or a builtin interface variable.
|
||||
* \returns Operand type
|
||||
*/
|
||||
DxbcOperandType type() const {
|
||||
return static_cast<DxbcOperandType>(
|
||||
bit::extract(m_token, 12, 19));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Index dimension
|
||||
*
|
||||
* Number of indices. In DXBC, each register file has
|
||||
* a dimensionality, e.g. the temporary registers are
|
||||
* one-dimensional and therefore require one index.
|
||||
* \returns Number of index dimensions
|
||||
*/
|
||||
uint32_t indexDimension() const {
|
||||
return bit::extract(m_token, 20, 21);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Index representation
|
||||
*
|
||||
* Stores whether an index is stored as an
|
||||
* immediate value or as a relative value
|
||||
* which requires another operand token.
|
||||
* \param [in] dim Index dimension to query
|
||||
* \returns Representation of that index
|
||||
*/
|
||||
DxbcOperandIndexRepresentation indexRepresentation(uint32_t dim) const {
|
||||
return static_cast<DxbcOperandIndexRepresentation>(
|
||||
bit::extract(m_token, 22 + 3 * dim, 24 + 3 * dim));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks whether the operand is extended
|
||||
*
|
||||
* Operands can be modified with extended tokens.
|
||||
* \returns \c true if the operand is extended
|
||||
*/
|
||||
bool isExtended() const {
|
||||
return !!bit::extract(m_token, 31, 31);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t m_token = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Extended operand token
|
||||
*
|
||||
* Stores additional properties for an operand that
|
||||
* cannot be stored in the initial operand token.
|
||||
*/
|
||||
class DxbcOperandTokenExt {
|
||||
|
||||
public:
|
||||
|
||||
DxbcOperandTokenExt() { }
|
||||
DxbcOperandTokenExt(uint32_t token)
|
||||
: m_token(token) { }
|
||||
|
||||
/**
|
||||
* \brief Operand extension type
|
||||
* \returns Operand extension type
|
||||
*/
|
||||
DxbcOperandExt type() const {
|
||||
return static_cast<DxbcOperandExt>(
|
||||
bit::extract(m_token, 0, 5));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Data flags
|
||||
* \returns Data flags
|
||||
*/
|
||||
uint32_t data() const {
|
||||
return bit::extract(m_token, 6, 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks whether the operand is extended
|
||||
*
|
||||
* Like extended opcode tokens, extended
|
||||
* operand tokens can be chained.
|
||||
* \returns \c true if extended
|
||||
*/
|
||||
bool isExtended() const {
|
||||
return !!bit::extract(m_token, 31, 31);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t m_token = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief DXBC instruction
|
||||
*
|
||||
* Provides convenience methods to extract the
|
||||
* opcode, instruction length, and instruction
|
||||
* arguments from an instruction.
|
||||
*/
|
||||
class DxbcInstruction {
|
||||
|
||||
public:
|
||||
|
||||
DxbcInstruction() { }
|
||||
DxbcInstruction(
|
||||
const uint32_t* code,
|
||||
uint32_t size);
|
||||
|
||||
/**
|
||||
* \brief Retrieves instruction word
|
||||
*
|
||||
* \param [in] Instruction word ID
|
||||
* \returns The instruction word
|
||||
*/
|
||||
uint32_t getWord(uint32_t id) const;
|
||||
|
||||
/**
|
||||
* \brief Instruction length
|
||||
*
|
||||
* Number of DWORDs for this instruction,
|
||||
* including the initial opcode token.
|
||||
* \returns Instruction length
|
||||
*/
|
||||
uint32_t length() const;
|
||||
|
||||
private:
|
||||
|
||||
const uint32_t* m_code = nullptr;
|
||||
uint32_t m_size = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Instruction decoder
|
||||
*
|
||||
* Helper class that provides methods to read typed
|
||||
* tokens and immediate values from the instruction
|
||||
* stream. This will read instructions word by word.
|
||||
*/
|
||||
class DxbcInstructionDecoder {
|
||||
|
||||
public:
|
||||
|
||||
DxbcInstructionDecoder() { }
|
||||
DxbcInstructionDecoder(
|
||||
const DxbcInstruction& inst)
|
||||
: m_inst(inst) { }
|
||||
|
||||
/**
|
||||
* \brief Reads opcode token
|
||||
*
|
||||
* Must be the very first call.
|
||||
* \returns The opcode token
|
||||
*/
|
||||
DxbcOpcodeToken readOpcode() {
|
||||
return DxbcOpcodeToken(m_inst.getWord(m_word++));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reads extended opcode token
|
||||
* \returns Extended opcode token
|
||||
*/
|
||||
DxbcOpcodeTokenExt readOpcodeExt() {
|
||||
return DxbcOpcodeTokenExt(m_inst.getWord(m_word++));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reads operand token
|
||||
* \returns Next operand token
|
||||
*/
|
||||
DxbcOperandToken readOperand() {
|
||||
return DxbcOperandToken(m_inst.getWord(m_word++));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reads extended operand token
|
||||
* \returns Extended operand token
|
||||
*/
|
||||
DxbcOperandTokenExt readOperandExt() {
|
||||
return DxbcOperandTokenExt(m_inst.getWord(m_word++));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reads immediate 32-bit integer
|
||||
* \returns The 32-bit integer constant
|
||||
*/
|
||||
uint32_t readu32() {
|
||||
return m_inst.getWord(m_word++);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reads immediate 64-bit integer
|
||||
* \returns The 64-bit integer constant
|
||||
*/
|
||||
uint64_t readu64() {
|
||||
uint64_t hi = readu32();
|
||||
uint64_t lo = readu32();
|
||||
return (hi << 32) | lo;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reads immediate 32-bit float
|
||||
* \returns The 32-bit float constant
|
||||
*/
|
||||
float readf32() {
|
||||
float result;
|
||||
uint32_t integer = readu32();
|
||||
std::memcpy(&result, &integer, sizeof(float));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reads immediate 64-bit float
|
||||
* \returns The 64-bit float constant
|
||||
*/
|
||||
double readf64() {
|
||||
double result;
|
||||
uint64_t integer = readu64();
|
||||
std::memcpy(&result, &integer, sizeof(double));
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
DxbcInstruction m_inst = { nullptr, 0u };
|
||||
uint32_t m_word = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief DXBC instruction decoder
|
||||
*
|
||||
* Iterator that walks over DXBC instructions.
|
||||
* Instruction boundaries are easy to find as
|
||||
* the length of each instruction is encoded
|
||||
* in the opcode token, much like in SPIR-V.
|
||||
*/
|
||||
class DxbcDecoder {
|
||||
|
||||
public:
|
||||
|
||||
DxbcDecoder() { }
|
||||
DxbcDecoder(const uint32_t* code, uint32_t size);
|
||||
|
||||
DxbcDecoder& operator ++ ();
|
||||
|
||||
DxbcInstruction operator * () const;
|
||||
|
||||
bool operator == (const DxbcDecoder& other) const { return m_code == other.m_code; }
|
||||
bool operator != (const DxbcDecoder& other) const { return m_code != other.m_code; }
|
||||
|
||||
private:
|
||||
|
||||
const uint32_t* m_code = nullptr;
|
||||
uint32_t m_size = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -217,4 +217,80 @@ namespace dxvk {
|
||||
DclGsInstanceCount = 206,
|
||||
};
|
||||
|
||||
|
||||
enum class DxbcOperandNumComponents : uint32_t {
|
||||
Component0 = 0,
|
||||
Component1 = 1,
|
||||
Component4 = 2,
|
||||
};
|
||||
|
||||
|
||||
enum class DxbcOperandComponentSelectionMode : uint32_t {
|
||||
Mask = 0,
|
||||
Swizzle = 1,
|
||||
Select1 = 2,
|
||||
};
|
||||
|
||||
enum class DxbcOperandType : uint32_t {
|
||||
Temp = 0,
|
||||
Input = 1,
|
||||
Output = 2,
|
||||
IndexableTemp = 3,
|
||||
Imm32 = 4,
|
||||
Imm64 = 5,
|
||||
Sampler = 6,
|
||||
Resource = 7,
|
||||
ConstantBuffer = 8,
|
||||
ImmediateConstantBuffer = 9,
|
||||
Label = 10,
|
||||
InputPrimitiveId = 11,
|
||||
OutputDepth = 12,
|
||||
Null = 13,
|
||||
Rasterizer = 14,
|
||||
OutputCoverageMask = 15,
|
||||
Stream = 16,
|
||||
FunctionBody = 17,
|
||||
FunctionTable = 18,
|
||||
Interface = 19,
|
||||
FunctionInput = 20,
|
||||
FunctionOutput = 21,
|
||||
OutputControlPointId = 22,
|
||||
InputForkInstanceId = 23,
|
||||
InputJoinInstanceId = 24,
|
||||
InputControlPoint = 25,
|
||||
OutputControlPoint = 26,
|
||||
InputPatchConstant = 27,
|
||||
InputDomainPoint = 28,
|
||||
ThisPointer = 29,
|
||||
UnorderedAccessView = 30,
|
||||
ThreadGroupSharedMemory = 31,
|
||||
InputThreadId = 32,
|
||||
InputThreadGroupId = 33,
|
||||
InputThreadIdInGroup = 34,
|
||||
InputCoverageMask = 35,
|
||||
InputThreadIndexInGroup = 36,
|
||||
InputGsInstanceId = 37,
|
||||
OutputDepthGe = 38,
|
||||
OutputDepthLe = 39,
|
||||
CycleCounter = 40,
|
||||
};
|
||||
|
||||
enum class DxbcOperandComponentName : uint32_t {
|
||||
X = 0, R = 0, Y = 1, G = 1,
|
||||
Z = 2, B = 2, W = 3, A = 3,
|
||||
};
|
||||
|
||||
|
||||
enum class DxbcOperandIndexRepresentation : uint32_t {
|
||||
Imm32 = 0,
|
||||
Imm64 = 1,
|
||||
Relative = 2,
|
||||
Imm32Relative = 3,
|
||||
Imm64Relative = 3,
|
||||
};
|
||||
|
||||
enum class DxbcOperandExt : uint32_t {
|
||||
OperandModifier = 1,
|
||||
};
|
||||
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxbc_opcode.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief DXBC instruction
|
||||
*
|
||||
* Provides convenience methods to extract the
|
||||
* opcode, instruction length, and instruction
|
||||
* arguments from an instruction.
|
||||
*/
|
||||
class DxbcInstruction {
|
||||
|
||||
public:
|
||||
|
||||
DxbcInstruction() { }
|
||||
DxbcInstruction(const uint32_t* code)
|
||||
: m_code(code) { }
|
||||
|
||||
/**
|
||||
* \brief Instruction code
|
||||
* \returns The operation code
|
||||
*/
|
||||
DxbcOpcode opcode() const {
|
||||
return static_cast<DxbcOpcode>(
|
||||
bit::extract<uint32_t, 0, 10>(m_code[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Instruction length
|
||||
*
|
||||
* Number of DWORDs for this instruction,
|
||||
* including the initial opcode token.
|
||||
* \returns Instruction length
|
||||
*/
|
||||
uint32_t length() const {
|
||||
return this->opcode() != DxbcOpcode::CustomData
|
||||
? bit::extract<uint32_t, 24, 30>(m_code[0])
|
||||
: m_code[1];
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const uint32_t* m_code = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief DXBC instruction iterator
|
||||
*
|
||||
* Iterator that walks over DXBC instructions.
|
||||
* Instruction boundaries are easy to find as
|
||||
* the length of each instruction is encoded
|
||||
* in the opcode token, much like in SPIR-V.
|
||||
*/
|
||||
class DxbcInstructionIterator {
|
||||
|
||||
public:
|
||||
|
||||
DxbcInstructionIterator() { }
|
||||
DxbcInstructionIterator(const uint32_t* code)
|
||||
: m_code(code) { }
|
||||
|
||||
DxbcInstructionIterator& operator ++ () {
|
||||
m_code += DxbcInstruction(m_code).length();
|
||||
return *this;
|
||||
}
|
||||
|
||||
DxbcInstruction operator * () const {
|
||||
return DxbcInstruction(m_code);
|
||||
}
|
||||
|
||||
bool operator == (const DxbcInstructionIterator& other) const { return m_code == other.m_code; }
|
||||
bool operator != (const DxbcInstructionIterator& other) const { return m_code != other.m_code; }
|
||||
|
||||
private:
|
||||
|
||||
const uint32_t* m_code = nullptr;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -2,6 +2,7 @@ dxbc_src = files([
|
||||
'dxbc_chunk_shex.cpp',
|
||||
'dxbc_common.cpp',
|
||||
'dxbc_compiler.cpp',
|
||||
'dxbc_decoder.cpp',
|
||||
'dxbc_header.cpp',
|
||||
'dxbc_module.cpp',
|
||||
'dxbc_reader.cpp',
|
||||
|
@ -6,11 +6,6 @@ namespace dxvk {
|
||||
SpirvCapabilities::~SpirvCapabilities() { }
|
||||
|
||||
|
||||
SpirvCodeBuffer SpirvCapabilities::code() const {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
|
||||
void SpirvCapabilities::enable(spv::Capability cap) {
|
||||
// Scan the generated instructions to check
|
||||
// whether we already enabled the capability.
|
||||
|
@ -24,7 +24,9 @@ namespace dxvk {
|
||||
* \c OpCapability instructions.
|
||||
* \returns Code buffer
|
||||
*/
|
||||
SpirvCodeBuffer code() const;
|
||||
const SpirvCodeBuffer& code() const {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enables a capability
|
||||
|
@ -0,0 +1,13 @@
|
||||
#include "spirv_gen_constant.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
SpirvConstants:: SpirvConstants() { }
|
||||
SpirvConstants::~SpirvConstants() { }
|
||||
|
||||
|
||||
SpirvCodeBuffer SpirvConstants::code() const {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "../spirv_code_buffer.h"
|
||||
|
||||
#include "spirv_gen_id.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief SPIR-V constant generator
|
||||
*
|
||||
* Provides convenient methods to
|
||||
* generate SPIR-V constants.
|
||||
*/
|
||||
class SpirvConstants {
|
||||
|
||||
public:
|
||||
|
||||
SpirvConstants();
|
||||
~SpirvConstants();
|
||||
|
||||
SpirvCodeBuffer code() const;
|
||||
|
||||
private:
|
||||
|
||||
SpirvCodeBuffer m_code;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
#include "spirv_gen_debuginfo.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
SpirvDebugInfo:: SpirvDebugInfo() { }
|
||||
SpirvDebugInfo::~SpirvDebugInfo() { }
|
||||
|
||||
|
||||
void SpirvDebugInfo::assignName(
|
||||
uint32_t id,
|
||||
const char* name) {
|
||||
m_code.putIns (spv::OpName, 2 + m_code.strLen(name));
|
||||
m_code.putWord(id);
|
||||
m_code.putStr (name);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "../spirv_code_buffer.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief SPIR-V debug info generator
|
||||
*
|
||||
* Can be used to assign names to result IDs,
|
||||
* such as variables, for debugging purposes.
|
||||
*/
|
||||
class SpirvDebugInfo {
|
||||
|
||||
public:
|
||||
|
||||
SpirvDebugInfo();
|
||||
~SpirvDebugInfo();
|
||||
|
||||
const SpirvCodeBuffer& code() const {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
void assignName(
|
||||
uint32_t id,
|
||||
const char* name);
|
||||
|
||||
private:
|
||||
|
||||
SpirvCodeBuffer m_code;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
#include "spirv_gen_decoration.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
SpirvDecorations:: SpirvDecorations() { }
|
||||
SpirvDecorations::~SpirvDecorations() { }
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "../spirv_code_buffer.h"
|
||||
|
||||
#include "spirv_gen_id.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief SPIR-V decoration generator
|
||||
*
|
||||
* Generates instructions for descriptor
|
||||
* bindings and builtin variable decorations.
|
||||
*/
|
||||
class SpirvDecorations {
|
||||
|
||||
public:
|
||||
|
||||
SpirvDecorations();
|
||||
~SpirvDecorations();
|
||||
|
||||
const SpirvCodeBuffer& code() const {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
SpirvCodeBuffer m_code;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -55,6 +55,12 @@ namespace dxvk {
|
||||
uint32_t interfaceCount,
|
||||
const uint32_t* interfaceIds);
|
||||
|
||||
/**
|
||||
* \brief Enables early fragment tests
|
||||
*/
|
||||
void enableEarlyFragmentTests(
|
||||
uint32_t functionId);
|
||||
|
||||
/**
|
||||
* \brief Sets local work group size for a compute shader
|
||||
*
|
||||
|
@ -8,11 +8,6 @@ namespace dxvk {
|
||||
SpirvTypeInfo::~SpirvTypeInfo() { }
|
||||
|
||||
|
||||
SpirvCodeBuffer SpirvTypeInfo::code() const {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvTypeInfo::typeVoid(SpirvIdCounter& ids) {
|
||||
return this->getTypeId(ids,
|
||||
spv::OpTypeVoid, 0, nullptr);
|
||||
|
@ -19,7 +19,9 @@ namespace dxvk {
|
||||
SpirvTypeInfo();
|
||||
~SpirvTypeInfo();
|
||||
|
||||
SpirvCodeBuffer code() const;
|
||||
const SpirvCodeBuffer& code() const {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
uint32_t typeVoid(
|
||||
SpirvIdCounter& ids);
|
||||
|
@ -0,0 +1,8 @@
|
||||
#include "spirv_gen_variable.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
SpirvVariables:: SpirvVariables() { }
|
||||
SpirvVariables::~SpirvVariables() { }
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "../spirv_code_buffer.h"
|
||||
|
||||
#include "spirv_gen_id.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief SPIR-V variable generator
|
||||
*
|
||||
* Generates global variable declarations.
|
||||
*/
|
||||
class SpirvVariables {
|
||||
|
||||
public:
|
||||
|
||||
SpirvVariables();
|
||||
~SpirvVariables();
|
||||
|
||||
const SpirvCodeBuffer& code() const {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
SpirvCodeBuffer m_code;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -103,7 +103,7 @@ namespace dxvk {
|
||||
uint32_t m_size = 0;
|
||||
|
||||
void advance(uint32_t n) {
|
||||
if (m_size >= n) {
|
||||
if (n < m_size) {
|
||||
m_code += n;
|
||||
m_size -= n;
|
||||
} else {
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace dxvk::bit {
|
||||
|
||||
template<typename T, T Fst, T Lst>
|
||||
constexpr T extract(T value) {
|
||||
return (value >> Fst) & ~(~T(0) << (Lst - Fst + 1));
|
||||
template<typename T>
|
||||
inline T extract(T value, uint32_t fst, uint32_t lst) {
|
||||
return (value >> fst) & ~(~T(0) << (lst - fst + 1));
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user