From 6954cfd84ccb173da0f31d68f8f9ab1eec9ab014 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 21 Oct 2017 17:58:58 +0200 Subject: [PATCH] [dxbc] Added helper classes for DXBC decoding --- src/dxbc/dxbc_chunk_shex.h | 10 +- src/dxbc/dxbc_compiler.cpp | 7 +- src/dxbc/dxbc_compiler.h | 19 +- src/dxbc/dxbc_decoder.cpp | 47 +++ src/dxbc/dxbc_decoder.h | 442 +++++++++++++++++++++++ src/dxbc/{dxbc_opcode.h => dxbc_enums.h} | 76 ++++ src/dxbc/dxbc_instruction.h | 85 ----- src/dxbc/meson.build | 1 + src/spirv/gen/spirv_gen_capability.cpp | 5 - src/spirv/gen/spirv_gen_capability.h | 4 +- src/spirv/gen/spirv_gen_constant.cpp | 13 + src/spirv/gen/spirv_gen_constant.h | 30 ++ src/spirv/gen/spirv_gen_debuginfo.cpp | 17 + src/spirv/gen/spirv_gen_debuginfo.h | 34 ++ src/spirv/gen/spirv_gen_decoration.cpp | 8 + src/spirv/gen/spirv_gen_decoration.h | 32 ++ src/spirv/gen/spirv_gen_entrypoint.h | 6 + src/spirv/gen/spirv_gen_typeinfo.cpp | 5 - src/spirv/gen/spirv_gen_typeinfo.h | 4 +- src/spirv/gen/spirv_gen_variable.cpp | 8 + src/spirv/gen/spirv_gen_variable.h | 31 ++ src/spirv/spirv_instruction.h | 2 +- src/util/util_bit.h | 6 +- 23 files changed, 782 insertions(+), 110 deletions(-) create mode 100644 src/dxbc/dxbc_decoder.cpp create mode 100644 src/dxbc/dxbc_decoder.h rename src/dxbc/{dxbc_opcode.h => dxbc_enums.h} (82%) delete mode 100644 src/dxbc/dxbc_instruction.h diff --git a/src/dxbc/dxbc_chunk_shex.h b/src/dxbc/dxbc_chunk_shex.h index e38d3f5fb..2ec577b97 100644 --- a/src/dxbc/dxbc_chunk_shex.h +++ b/src/dxbc/dxbc_chunk_shex.h @@ -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: diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index fc0620a02..9868db30c 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -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(ins.opcode()))); + bool DxbcCompiler::processInstruction(DxbcInstruction ins) { + return false; } diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index a81e71ee5..fabb53a2c 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -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(); diff --git a/src/dxbc/dxbc_decoder.cpp b/src/dxbc/dxbc_decoder.cpp new file mode 100644 index 000000000..0bc185d85 --- /dev/null +++ b/src/dxbc/dxbc_decoder.cpp @@ -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); + } + +} \ No newline at end of file diff --git a/src/dxbc/dxbc_decoder.h b/src/dxbc/dxbc_decoder.h new file mode 100644 index 000000000..f6554be81 --- /dev/null +++ b/src/dxbc/dxbc_decoder.h @@ -0,0 +1,442 @@ +#pragma once + +#include + +#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( + 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( + 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( + 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( + 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( + 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( + 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; + + }; + +} \ No newline at end of file diff --git a/src/dxbc/dxbc_opcode.h b/src/dxbc/dxbc_enums.h similarity index 82% rename from src/dxbc/dxbc_opcode.h rename to src/dxbc/dxbc_enums.h index 9f945a008..944fd7feb 100644 --- a/src/dxbc/dxbc_opcode.h +++ b/src/dxbc/dxbc_enums.h @@ -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, + }; + } \ No newline at end of file diff --git a/src/dxbc/dxbc_instruction.h b/src/dxbc/dxbc_instruction.h deleted file mode 100644 index 2e0dae27a..000000000 --- a/src/dxbc/dxbc_instruction.h +++ /dev/null @@ -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( - bit::extract(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(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; - - }; - -} \ No newline at end of file diff --git a/src/dxbc/meson.build b/src/dxbc/meson.build index d90b5fe60..22d37f5cf 100644 --- a/src/dxbc/meson.build +++ b/src/dxbc/meson.build @@ -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', diff --git a/src/spirv/gen/spirv_gen_capability.cpp b/src/spirv/gen/spirv_gen_capability.cpp index ea332847f..487205adc 100644 --- a/src/spirv/gen/spirv_gen_capability.cpp +++ b/src/spirv/gen/spirv_gen_capability.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. diff --git a/src/spirv/gen/spirv_gen_capability.h b/src/spirv/gen/spirv_gen_capability.h index b96273dc3..f47cecdd8 100644 --- a/src/spirv/gen/spirv_gen_capability.h +++ b/src/spirv/gen/spirv_gen_capability.h @@ -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 diff --git a/src/spirv/gen/spirv_gen_constant.cpp b/src/spirv/gen/spirv_gen_constant.cpp index e69de29bb..cf41273f4 100644 --- a/src/spirv/gen/spirv_gen_constant.cpp +++ b/src/spirv/gen/spirv_gen_constant.cpp @@ -0,0 +1,13 @@ +#include "spirv_gen_constant.h" + +namespace dxvk { + + SpirvConstants:: SpirvConstants() { } + SpirvConstants::~SpirvConstants() { } + + + SpirvCodeBuffer SpirvConstants::code() const { + return m_code; + } + +} \ No newline at end of file diff --git a/src/spirv/gen/spirv_gen_constant.h b/src/spirv/gen/spirv_gen_constant.h index e69de29bb..2981254a1 100644 --- a/src/spirv/gen/spirv_gen_constant.h +++ b/src/spirv/gen/spirv_gen_constant.h @@ -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; + + }; + +} \ No newline at end of file diff --git a/src/spirv/gen/spirv_gen_debuginfo.cpp b/src/spirv/gen/spirv_gen_debuginfo.cpp index e69de29bb..a8f383386 100644 --- a/src/spirv/gen/spirv_gen_debuginfo.cpp +++ b/src/spirv/gen/spirv_gen_debuginfo.cpp @@ -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); + } + +} \ No newline at end of file diff --git a/src/spirv/gen/spirv_gen_debuginfo.h b/src/spirv/gen/spirv_gen_debuginfo.h index e69de29bb..b3fbfb7a3 100644 --- a/src/spirv/gen/spirv_gen_debuginfo.h +++ b/src/spirv/gen/spirv_gen_debuginfo.h @@ -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; + + }; + +} \ No newline at end of file diff --git a/src/spirv/gen/spirv_gen_decoration.cpp b/src/spirv/gen/spirv_gen_decoration.cpp index e69de29bb..3c5406a29 100644 --- a/src/spirv/gen/spirv_gen_decoration.cpp +++ b/src/spirv/gen/spirv_gen_decoration.cpp @@ -0,0 +1,8 @@ +#include "spirv_gen_decoration.h" + +namespace dxvk { + + SpirvDecorations:: SpirvDecorations() { } + SpirvDecorations::~SpirvDecorations() { } + +} \ No newline at end of file diff --git a/src/spirv/gen/spirv_gen_decoration.h b/src/spirv/gen/spirv_gen_decoration.h index e69de29bb..c82d91509 100644 --- a/src/spirv/gen/spirv_gen_decoration.h +++ b/src/spirv/gen/spirv_gen_decoration.h @@ -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; + + }; + +} \ No newline at end of file diff --git a/src/spirv/gen/spirv_gen_entrypoint.h b/src/spirv/gen/spirv_gen_entrypoint.h index 5563acd21..492c184c7 100644 --- a/src/spirv/gen/spirv_gen_entrypoint.h +++ b/src/spirv/gen/spirv_gen_entrypoint.h @@ -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 * diff --git a/src/spirv/gen/spirv_gen_typeinfo.cpp b/src/spirv/gen/spirv_gen_typeinfo.cpp index 6335e9a8f..b78d1085c 100644 --- a/src/spirv/gen/spirv_gen_typeinfo.cpp +++ b/src/spirv/gen/spirv_gen_typeinfo.cpp @@ -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); diff --git a/src/spirv/gen/spirv_gen_typeinfo.h b/src/spirv/gen/spirv_gen_typeinfo.h index ae6094224..637f32fba 100644 --- a/src/spirv/gen/spirv_gen_typeinfo.h +++ b/src/spirv/gen/spirv_gen_typeinfo.h @@ -19,7 +19,9 @@ namespace dxvk { SpirvTypeInfo(); ~SpirvTypeInfo(); - SpirvCodeBuffer code() const; + const SpirvCodeBuffer& code() const { + return m_code; + } uint32_t typeVoid( SpirvIdCounter& ids); diff --git a/src/spirv/gen/spirv_gen_variable.cpp b/src/spirv/gen/spirv_gen_variable.cpp index e69de29bb..e41a33369 100644 --- a/src/spirv/gen/spirv_gen_variable.cpp +++ b/src/spirv/gen/spirv_gen_variable.cpp @@ -0,0 +1,8 @@ +#include "spirv_gen_variable.h" + +namespace dxvk { + + SpirvVariables:: SpirvVariables() { } + SpirvVariables::~SpirvVariables() { } + +} \ No newline at end of file diff --git a/src/spirv/gen/spirv_gen_variable.h b/src/spirv/gen/spirv_gen_variable.h index e69de29bb..a695ab9fd 100644 --- a/src/spirv/gen/spirv_gen_variable.h +++ b/src/spirv/gen/spirv_gen_variable.h @@ -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; + + }; + +} \ No newline at end of file diff --git a/src/spirv/spirv_instruction.h b/src/spirv/spirv_instruction.h index 8ee75694f..b3f341f37 100644 --- a/src/spirv/spirv_instruction.h +++ b/src/spirv/spirv_instruction.h @@ -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 { diff --git a/src/util/util_bit.h b/src/util/util_bit.h index 15b7496aa..ce9762c9b 100644 --- a/src/util/util_bit.h +++ b/src/util/util_bit.h @@ -2,9 +2,9 @@ namespace dxvk::bit { - template - constexpr T extract(T value) { - return (value >> Fst) & ~(~T(0) << (Lst - Fst + 1)); + template + inline T extract(T value, uint32_t fst, uint32_t lst) { + return (value >> fst) & ~(~T(0) << (lst - fst + 1)); } } \ No newline at end of file