diff options
Diffstat (limited to '')
9 files changed, 5720 insertions, 0 deletions
diff --git a/src/libs/dxvk-native-1.9.2a/src/spirv/meson.build b/src/libs/dxvk-native-1.9.2a/src/spirv/meson.build new file mode 100644 index 00000000..7c180f98 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/src/spirv/meson.build @@ -0,0 +1,9 @@ +spirv_src = files([ + 'spirv_code_buffer.cpp', + 'spirv_compression.cpp', + 'spirv_module.cpp', +]) + +spirv_lib = static_library('spirv', spirv_src, + include_directories : [ dxvk_include_path ], + override_options : ['cpp_std='+dxvk_cpp_std]) diff --git a/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_code_buffer.cpp b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_code_buffer.cpp new file mode 100644 index 00000000..74d8dd97 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_code_buffer.cpp @@ -0,0 +1,154 @@ +#include <array> +#include <cstring> + +#include "spirv_code_buffer.h" + +namespace dxvk { + + SpirvCodeBuffer:: SpirvCodeBuffer() { } + SpirvCodeBuffer::~SpirvCodeBuffer() { } + + + SpirvCodeBuffer::SpirvCodeBuffer(uint32_t size) + : m_ptr(size) { + m_code.resize(size); + } + + + SpirvCodeBuffer::SpirvCodeBuffer(uint32_t size, const uint32_t* data) + : m_ptr(size) { + m_code.resize(size); + std::memcpy(m_code.data(), data, size * sizeof(uint32_t)); + } + + + SpirvCodeBuffer::SpirvCodeBuffer(std::istream& stream) { + stream.ignore(std::numeric_limits<std::streamsize>::max()); + std::streamsize length = stream.gcount(); + stream.clear(); + stream.seekg(0, std::ios_base::beg); + + std::vector<char> buffer(length); + stream.read(buffer.data(), length); + buffer.resize(stream.gcount()); + + m_code.resize(buffer.size() / sizeof(uint32_t)); + std::memcpy(reinterpret_cast<char*>(m_code.data()), + buffer.data(), m_code.size() * sizeof(uint32_t)); + + m_ptr = m_code.size(); + } + + + uint32_t SpirvCodeBuffer::allocId() { + constexpr size_t BoundIdsOffset = 3; + + if (m_code.size() <= BoundIdsOffset) + return 0; + + return m_code[BoundIdsOffset]++; + } + + + void SpirvCodeBuffer::append(const SpirvCodeBuffer& other) { + if (other.size() != 0) { + const size_t size = m_code.size(); + m_code.resize(size + other.m_code.size()); + + uint32_t* dst = this->m_code.data(); + const uint32_t* src = other.m_code.data(); + + std::memcpy(dst + size, src, other.size()); + m_ptr += other.m_code.size(); + } + } + + + void SpirvCodeBuffer::putWord(uint32_t word) { + m_code.insert(m_code.begin() + m_ptr, word); + m_ptr += 1; + } + + + void SpirvCodeBuffer::putIns(spv::Op opCode, uint16_t wordCount) { + this->putWord( + (static_cast<uint32_t>(opCode) << 0) + | (static_cast<uint32_t>(wordCount) << 16)); + } + + + void SpirvCodeBuffer::putInt32(uint32_t word) { + this->putWord(word); + } + + + void SpirvCodeBuffer::putInt64(uint64_t value) { + this->putWord(value >> 0); + this->putWord(value >> 32); + } + + + void SpirvCodeBuffer::putFloat32(float value) { + uint32_t tmp; + static_assert(sizeof(tmp) == sizeof(value)); + std::memcpy(&tmp, &value, sizeof(value)); + this->putInt32(tmp); + } + + + void SpirvCodeBuffer::putFloat64(double value) { + uint64_t tmp; + static_assert(sizeof(tmp) == sizeof(value)); + std::memcpy(&tmp, &value, sizeof(value)); + this->putInt64(tmp); + } + + + void SpirvCodeBuffer::putStr(const char* str) { + uint32_t word = 0; + uint32_t nbit = 0; + + for (uint32_t i = 0; str[i] != '\0'; str++) { + word |= (static_cast<uint32_t>(str[i]) & 0xFF) << nbit; + + if ((nbit += 8) == 32) { + this->putWord(word); + word = 0; + nbit = 0; + } + } + + // Commit current word + this->putWord(word); + } + + + void SpirvCodeBuffer::putHeader(uint32_t version, uint32_t boundIds) { + this->putWord(spv::MagicNumber); + this->putWord(version); + this->putWord(0); // Generator + this->putWord(boundIds); + this->putWord(0); // Schema + } + + + void SpirvCodeBuffer::erase(size_t size) { + m_code.erase( + m_code.begin() + m_ptr, + m_code.begin() + m_ptr + size); + } + + + uint32_t SpirvCodeBuffer::strLen(const char* str) { + // Null-termination plus padding + return (std::strlen(str) + 4) / 4; + } + + + void SpirvCodeBuffer::store(std::ostream& stream) const { + stream.write( + reinterpret_cast<const char*>(m_code.data()), + sizeof(uint32_t) * m_code.size()); + } + +}
\ No newline at end of file diff --git a/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_code_buffer.h b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_code_buffer.h new file mode 100644 index 00000000..a06b594c --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_code_buffer.h @@ -0,0 +1,223 @@ +#pragma once + +#include <spirv/spirv.hpp> + +#include <iostream> +#include <vector> + +#include "spirv_instruction.h" + +namespace dxvk { + + /** + * \brief SPIR-V code buffer + * + * Helper class for generating SPIR-V shaders. + * Stores arbitrary SPIR-V instructions in a + * format that can be read by Vulkan drivers. + */ + class SpirvCodeBuffer { + + public: + + SpirvCodeBuffer(); + explicit SpirvCodeBuffer(uint32_t size); + SpirvCodeBuffer(uint32_t size, const uint32_t* data); + SpirvCodeBuffer(std::istream& stream); + + template<size_t N> + SpirvCodeBuffer(const uint32_t (&data)[N]) + : SpirvCodeBuffer(N, data) { } + + ~SpirvCodeBuffer(); + + /** + * \brief Code data + * \returns Code data + */ + const uint32_t* data() const { return m_code.data(); } + uint32_t* data() { return m_code.data(); } + + /** + * \brief Code size, in dwords + * \returns Code size, in dwords + */ + uint32_t dwords() const { + return m_code.size(); + } + + /** + * \brief Code size, in bytes + * \returns Code size, in bytes + */ + size_t size() const { + return m_code.size() * sizeof(uint32_t); + } + + /** + * \brief Begin instruction iterator + * + * Points to the first instruction in the instruction + * block. The header, if any, will be skipped over. + * \returns Instruction iterator + */ + SpirvInstructionIterator begin() { + return SpirvInstructionIterator( + m_code.data(), 0, m_code.size()); + } + + /** + * \brief End instruction iterator + * + * Points to the end of the instruction block. + * \returns Instruction iterator + */ + SpirvInstructionIterator end() { + return SpirvInstructionIterator(nullptr, 0, 0); + } + + /** + * \brief Allocates a new ID + * + * Returns a new valid ID and increments the + * maximum ID count stored in the header. + * \returns The new SPIR-V ID + */ + uint32_t allocId(); + + /** + * \brief Merges two code buffers + * + * This is useful to generate declarations or + * the SPIR-V header at the same time as the + * code when doing so in advance is impossible. + * \param [in] other Code buffer to append + */ + void append(const SpirvCodeBuffer& other); + + /** + * \brief Appends an 32-bit word to the buffer + * \param [in] word The word to append + */ + void putWord(uint32_t word); + + /** + * \brief Appends an instruction word to the buffer + * + * Adds a single word containing both the word count + * and the op code number for a single instruction. + * \param [in] opCode Operand code + * \param [in] wordCount Number of words + */ + void putIns(spv::Op opCode, uint16_t wordCount); + + /** + * \brief Appends a 32-bit integer to the buffer + * \param [in] value The number to add + */ + void putInt32(uint32_t word); + + /** + * \brief Appends a 64-bit integer to the buffer + * + * A 64-bit integer will take up two 32-bit words. + * \param [in] value 64-bit value to add + */ + void putInt64(uint64_t value); + + /** + * \brief Appends a 32-bit float to the buffer + * \param [in] value The number to add + */ + void putFloat32(float value); + + /** + * \brief Appends a 64-bit float to the buffer + * \param [in] value The number to add + */ + void putFloat64(double value); + + /** + * \brief Appends a literal string to the buffer + * \param [in] str String to append to the buffer + */ + void putStr(const char* str); + + /** + * \brief Adds the header to the buffer + * + * \param [in] version SPIR-V version + * \param [in] boundIds Number of bound IDs + */ + void putHeader(uint32_t version, uint32_t boundIds); + + /** + * \brief Erases given number of dwords + * + * Removes data from the code buffer, starting + * at the current insertion offset. + * \param [in] size Number of words to remove + */ + void erase(size_t size); + + /** + * \brief Computes length of a literal string + * + * \param [in] str The string to check + * \returns Number of words consumed by a string + */ + uint32_t strLen(const char* str); + + /** + * \brief Stores the SPIR-V module to a stream + * + * The ability to save modules to a file + * exists mostly for debugging purposes. + * \param [in] stream Output stream + */ + void store(std::ostream& stream) const; + + /** + * \brief Retrieves current insertion pointer + * + * Sometimes it may be necessay to insert code into the + * middle of the stream rather than appending it. This + * retrieves the current function pointer. Note that the + * pointer will become invalid if any code is inserted + * before the current pointer location. + * \returns Current instruction pointr + */ + size_t getInsertionPtr() const { + return m_ptr; + } + + /** + * \brief Sets insertion pointer to a specific value + * + * Sets the insertion pointer to a value that was + * previously retrieved by \ref getInsertionPtr. + * \returns Current instruction pointr + */ + void beginInsertion(size_t ptr) { + m_ptr = ptr; + } + + /** + * \brief Sets insertion pointer to the end + * + * After this call, new instructions will be + * appended to the stream. In other words, + * this will restore default behaviour. + */ + void endInsertion() { + m_ptr = m_code.size(); + } + + private: + + std::vector<uint32_t> m_code; + size_t m_ptr = 0; + + }; + +}
\ No newline at end of file diff --git a/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_compression.cpp b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_compression.cpp new file mode 100644 index 00000000..6c3f6875 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_compression.cpp @@ -0,0 +1,110 @@ +#include "spirv_compression.h" + +namespace dxvk { + + SpirvCompressedBuffer::SpirvCompressedBuffer() + : m_size(0) { + + } + + + SpirvCompressedBuffer::SpirvCompressedBuffer( + const SpirvCodeBuffer& code) + : m_size(code.dwords()) { + const uint32_t* data = code.data(); + + // The compression works by eliminating leading null bytes + // from DWORDs, exploiting that SPIR-V IDs are consecutive + // integers that usually fall into the 16-bit range. For + // each DWORD, a two-bit integer is stored which indicates + // the number of bytes it takes in the compressed buffer. + // This way, it can achieve a compression ratio of ~50%. + m_mask.reserve((m_size + NumMaskWords - 1) / NumMaskWords); + m_code.reserve((m_size + 1) / 2); + + uint64_t dstWord = 0; + uint32_t dstShift = 0; + + for (uint32_t i = 0; i < m_size; i += NumMaskWords) { + uint64_t byteCounts = 0; + + for (uint32_t w = 0; w < NumMaskWords && i + w < m_size; w++) { + uint64_t word = data[i + w]; + uint64_t bytes = 0; + + if (word < (1 << 8)) bytes = 0; + else if (word < (1 << 16)) bytes = 1; + else if (word < (1 << 24)) bytes = 2; + else bytes = 3; + + byteCounts |= bytes << (2 * w); + + uint32_t bits = 8 * bytes + 8; + uint32_t rem = bit::pack(dstWord, dstShift, word, bits); + + if (unlikely(rem != 0)) { + m_code.push_back(dstWord); + + dstWord = 0; + dstShift = 0; + + bit::pack(dstWord, dstShift, word >> (bits - rem), rem); + } + } + + m_mask.push_back(byteCounts); + } + + if (dstShift) + m_code.push_back(dstWord); + + m_mask.shrink_to_fit(); + m_code.shrink_to_fit(); + } + + + SpirvCompressedBuffer::~SpirvCompressedBuffer() { + + } + + + SpirvCodeBuffer SpirvCompressedBuffer::decompress() const { + SpirvCodeBuffer code(m_size); + uint32_t* data = code.data(); + + if (m_size == 0) + return code; + + uint32_t maskIdx = 0; + uint32_t codeIdx = 0; + + uint64_t srcWord = m_code[codeIdx++]; + uint32_t srcShift = 0; + + for (uint32_t i = 0; i < m_size; i += NumMaskWords) { + uint64_t srcMask = m_mask[maskIdx++]; + + for (uint32_t w = 0; w < NumMaskWords && i + w < m_size; w++) { + uint32_t bits = 8 * ((srcMask & 3) + 1); + + uint64_t word = 0; + uint32_t rem = bit::unpack(word, srcWord, srcShift, bits); + + if (unlikely(rem != 0)) { + srcWord = m_code[codeIdx++]; + srcShift = 0; + + uint64_t tmp = 0; + bit::unpack(tmp, srcWord, srcShift, rem); + word |= tmp << (bits - rem); + } + + data[i + w] = word; + srcMask >>= 2; + } + } + + return code; + } + +}
\ No newline at end of file diff --git a/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_compression.h b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_compression.h new file mode 100644 index 00000000..7a1276c8 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_compression.h @@ -0,0 +1,36 @@ +#pragma once + +#include <vector> + +#include "spirv_code_buffer.h" + +namespace dxvk { + + /** + * \brief Compressed SPIR-V code buffer + * + * Implements a fast in-memory compression + * to keep memory footprint low. + */ + class SpirvCompressedBuffer { + constexpr static uint32_t NumMaskWords = 32; + public: + + SpirvCompressedBuffer(); + + SpirvCompressedBuffer( + const SpirvCodeBuffer& code); + + ~SpirvCompressedBuffer(); + + SpirvCodeBuffer decompress() const; + + private: + + uint32_t m_size; + std::vector<uint64_t> m_mask; + std::vector<uint64_t> m_code; + + }; + +}
\ No newline at end of file diff --git a/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_include.h b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_include.h new file mode 100644 index 00000000..fca94181 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_include.h @@ -0,0 +1,12 @@ +#pragma once + +#include "../util/log/log.h" +#include "../util/log/log_debug.h" + +#include "../util/util_error.h" +#include "../util/util_flags.h" +#include "../util/util_likely.h" +#include "../util/util_string.h" + +#include "../util/rc/util_rc.h" +#include "../util/rc/util_rc_ptr.h" diff --git a/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_instruction.h b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_instruction.h new file mode 100644 index 00000000..061d5ab7 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_instruction.h @@ -0,0 +1,155 @@ +#pragma once + +#include <spirv/spirv.hpp> +#include <spirv/GLSL.std.450.hpp> + +#include "spirv_include.h" + +namespace dxvk { + + /** + * \brief SPIR-V instruction + * + * Helps parsing a single instruction, providing + * access to the op code, instruction length and + * instruction arguments. + */ + class SpirvInstruction { + + public: + + SpirvInstruction() { } + SpirvInstruction(uint32_t* code, uint32_t offset, uint32_t length) + : m_code(code), m_offset(offset), m_length(length) { } + + /** + * \brief SPIR-V Op code + * \returns The op code + */ + spv::Op opCode() const { + return static_cast<spv::Op>( + this->arg(0) & spv::OpCodeMask); + } + + /** + * \brief Instruction length + * \returns Number of DWORDs + */ + uint32_t length() const { + return this->arg(0) >> spv::WordCountShift; + } + + /** + * \brief Instruction offset + * \returns Offset in DWORDs + */ + uint32_t offset() const { + return m_offset; + } + + /** + * \brief Argument value + * + * Retrieves an argument DWORD. Note that some instructions + * take 64-bit arguments which require more than one DWORD. + * Arguments start at index 1. Calling this method with an + * argument ID of 0 will return the opcode token. + * \param [in] idx Argument index, starting at 1 + * \returns The argument value + */ + uint32_t arg(uint32_t idx) const { + const uint32_t index = m_offset + idx; + return index < m_length ? m_code[index] : 0; + } + + /** + * \brief Argument string + * + * Retrieves a pointer to a UTF-8-encoded string. + * \param [in] idx Argument index, starting at 1 + * \returns Pointer to the literal string + */ + const char* chr(uint32_t idx) const { + const uint32_t index = m_offset + idx; + return index < m_length ? reinterpret_cast<const char*>(&m_code[index]) : nullptr; + } + + /** + * \brief Changes the value of an argument + * + * \param [in] idx Argument index, starting at 1 + * \param [in] word New argument word + */ + void setArg(uint32_t idx, uint32_t word) const { + if (m_offset + idx < m_length) + m_code[m_offset + idx] = word; + } + + private: + + uint32_t* m_code = nullptr; + uint32_t m_offset = 0; + uint32_t m_length = 0; + + }; + + + /** + * \brief SPIR-V instruction iterator + * + * Convenient iterator that can be used + * to process raw SPIR-V shader code. + */ + class SpirvInstructionIterator { + + public: + + SpirvInstructionIterator() { } + SpirvInstructionIterator(uint32_t* code, uint32_t offset, uint32_t length) + : m_code (length != 0 ? code : nullptr), + m_offset(length != 0 ? offset : 0), + m_length(length) { + if ((length >= 5) && (m_code[0] == spv::MagicNumber)) + this->advance(5); + } + + SpirvInstructionIterator& operator ++ () { + this->advance(SpirvInstruction(m_code, m_offset, m_length).length()); + return *this; + } + + SpirvInstruction operator * () const { + return SpirvInstruction(m_code, m_offset, m_length); + } + + bool operator == (const SpirvInstructionIterator& other) const { + return this->m_code == other.m_code + && this->m_offset == other.m_offset + && this->m_length == other.m_length; + } + + bool operator != (const SpirvInstructionIterator& other) const { + return this->m_code != other.m_code + || this->m_offset != other.m_offset + || this->m_length != other.m_length; + } + + private: + + uint32_t* m_code = nullptr; + uint32_t m_offset = 0; + uint32_t m_length = 0; + + void advance(uint32_t n) { + if (m_offset + n < m_length) { + m_offset += n; + } else { + m_code = nullptr; + m_offset = 0; + m_length = 0; + } + } + + }; + +}
\ No newline at end of file diff --git a/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_module.cpp b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_module.cpp new file mode 100644 index 00000000..7811bae9 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_module.cpp @@ -0,0 +1,3741 @@ +#include <cstring> + +#include "spirv_module.h" + +namespace dxvk { + + SpirvModule::SpirvModule(uint32_t version) + : m_version(version) { + this->instImportGlsl450(); + } + + + SpirvModule::~SpirvModule() { + + } + + + SpirvCodeBuffer SpirvModule::compile() const { + SpirvCodeBuffer result; + result.putHeader(m_version, m_id); + result.append(m_capabilities); + result.append(m_extensions); + result.append(m_instExt); + result.append(m_memoryModel); + result.append(m_entryPoints); + result.append(m_execModeInfo); + result.append(m_debugNames); + result.append(m_annotations); + result.append(m_typeConstDefs); + result.append(m_variables); + result.append(m_code); + return result; + } + + + uint32_t SpirvModule::allocateId() { + return m_id++; + } + + + bool SpirvModule::hasCapability( + spv::Capability capability) { + for (auto ins : m_capabilities) { + if (ins.opCode() == spv::OpCapability && ins.arg(1) == capability) + return true; + } + + return false; + } + + void SpirvModule::enableCapability( + spv::Capability capability) { + // Scan the generated instructions to check + // whether we already enabled the capability. + if (!hasCapability(capability)) { + m_capabilities.putIns (spv::OpCapability, 2); + m_capabilities.putWord(capability); + } + } + + + void SpirvModule::enableExtension( + const char* extensionName) { + m_extensions.putIns (spv::OpExtension, 1 + m_extensions.strLen(extensionName)); + m_extensions.putStr (extensionName); + } + + + void SpirvModule::addEntryPoint( + uint32_t entryPointId, + spv::ExecutionModel executionModel, + const char* name, + uint32_t interfaceCount, + const uint32_t* interfaceIds) { + m_entryPoints.putIns (spv::OpEntryPoint, 3 + m_entryPoints.strLen(name) + interfaceCount); + m_entryPoints.putWord (executionModel); + m_entryPoints.putWord (entryPointId); + m_entryPoints.putStr (name); + + for (uint32_t i = 0; i < interfaceCount; i++) + m_entryPoints.putWord(interfaceIds[i]); + } + + + void SpirvModule::setMemoryModel( + spv::AddressingModel addressModel, + spv::MemoryModel memoryModel) { + m_memoryModel.putIns (spv::OpMemoryModel, 3); + m_memoryModel.putWord (addressModel); + m_memoryModel.putWord (memoryModel); + } + + + void SpirvModule::setExecutionMode( + uint32_t entryPointId, + spv::ExecutionMode executionMode) { + m_execModeInfo.putIns (spv::OpExecutionMode, 3); + m_execModeInfo.putWord(entryPointId); + m_execModeInfo.putWord(executionMode); + } + + + void SpirvModule::setExecutionMode( + uint32_t entryPointId, + spv::ExecutionMode executionMode, + uint32_t argCount, + const uint32_t* args) { + m_execModeInfo.putIns (spv::OpExecutionMode, 3 + argCount); + m_execModeInfo.putWord(entryPointId); + m_execModeInfo.putWord(executionMode); + + for (uint32_t i = 0; i < argCount; i++) + m_execModeInfo.putWord(args[i]); + } + + + void SpirvModule::setInvocations( + uint32_t entryPointId, + uint32_t invocations) { + m_execModeInfo.putIns (spv::OpExecutionMode, 4); + m_execModeInfo.putWord (entryPointId); + m_execModeInfo.putWord (spv::ExecutionModeInvocations); + m_execModeInfo.putInt32(invocations); + } + + + void SpirvModule::setLocalSize( + uint32_t entryPointId, + uint32_t x, + uint32_t y, + uint32_t z) { + m_execModeInfo.putIns (spv::OpExecutionMode, 6); + m_execModeInfo.putWord (entryPointId); + m_execModeInfo.putWord (spv::ExecutionModeLocalSize); + m_execModeInfo.putInt32(x); + m_execModeInfo.putInt32(y); + m_execModeInfo.putInt32(z); + } + + + void SpirvModule::setOutputVertices( + uint32_t entryPointId, + uint32_t vertexCount) { + m_execModeInfo.putIns (spv::OpExecutionMode, 4); + m_execModeInfo.putWord(entryPointId); + m_execModeInfo.putWord(spv::ExecutionModeOutputVertices); + m_execModeInfo.putWord(vertexCount); + } + + + uint32_t SpirvModule::addDebugString( + const char* string) { + uint32_t resultId = this->allocateId(); + + m_debugNames.putIns (spv::OpString, + 2 + m_debugNames.strLen(string)); + m_debugNames.putWord(resultId); + m_debugNames.putStr (string); + return resultId; + } + + + void SpirvModule::setDebugSource( + spv::SourceLanguage language, + uint32_t version, + uint32_t file, + const char* source) { + uint32_t strLen = source != nullptr + ? m_debugNames.strLen(source) : 0; + + m_debugNames.putIns (spv::OpSource, 4 + strLen); + m_debugNames.putWord(language); + m_debugNames.putWord(version); + m_debugNames.putWord(file); + + if (source != nullptr) + m_debugNames.putStr(source); + } + + void SpirvModule::setDebugName( + uint32_t expressionId, + const char* debugName) { + m_debugNames.putIns (spv::OpName, 2 + m_debugNames.strLen(debugName)); + m_debugNames.putWord(expressionId); + m_debugNames.putStr (debugName); + } + + + void SpirvModule::setDebugMemberName( + uint32_t structId, + uint32_t memberId, + const char* debugName) { + m_debugNames.putIns (spv::OpMemberName, 3 + m_debugNames.strLen(debugName)); + m_debugNames.putWord(structId); + m_debugNames.putWord(memberId); + m_debugNames.putStr (debugName); + } + + + uint32_t SpirvModule::constBool( + bool v) { + return this->defConst(v + ? spv::OpConstantTrue + : spv::OpConstantFalse, + this->defBoolType(), + 0, nullptr); + } + + + uint32_t SpirvModule::consti32( + int32_t v) { + std::array<uint32_t, 1> data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defIntType(32, 1), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::consti64( + int64_t v) { + std::array<uint32_t, 2> data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defIntType(64, 1), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::constu32( + uint32_t v) { + std::array<uint32_t, 1> data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defIntType(32, 0), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::constu64( + uint64_t v) { + std::array<uint32_t, 2> data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defIntType(64, 0), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::constf32( + float v) { + std::array<uint32_t, 1> data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defFloatType(32), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::constf64( + double v) { + std::array<uint32_t, 2> data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defFloatType(64), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::constvec4i32( + int32_t x, + int32_t y, + int32_t z, + int32_t w) { + std::array<uint32_t, 4> args = {{ + this->consti32(x), this->consti32(y), + this->consti32(z), this->consti32(w), + }}; + + uint32_t scalarTypeId = this->defIntType(32, 1); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constvec4b32( + bool x, + bool y, + bool z, + bool w) { + std::array<uint32_t, 4> args = {{ + this->constBool(x), this->constBool(y), + this->constBool(z), this->constBool(w), + }}; + + uint32_t scalarTypeId = this->defBoolType(); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constvec4u32( + uint32_t x, + uint32_t y, + uint32_t z, + uint32_t w) { + std::array<uint32_t, 4> args = {{ + this->constu32(x), this->constu32(y), + this->constu32(z), this->constu32(w), + }}; + + uint32_t scalarTypeId = this->defIntType(32, 0); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constvec2f32( + float x, + float y) { + std::array<uint32_t, 2> args = {{ + this->constf32(x), this->constf32(y), + }}; + + uint32_t scalarTypeId = this->defFloatType(32); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 2); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constvec3f32( + float x, + float y, + float z) { + std::array<uint32_t, 3> args = {{ + this->constf32(x), this->constf32(y), + this->constf32(z), + }}; + + uint32_t scalarTypeId = this->defFloatType(32); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 3); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constvec4f32( + float x, + float y, + float z, + float w) { + std::array<uint32_t, 4> args = {{ + this->constf32(x), this->constf32(y), + this->constf32(z), this->constf32(w), + }}; + + uint32_t scalarTypeId = this->defFloatType(32); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constfReplicant( + float replicant, + uint32_t count) { + uint32_t value = this->constf32(replicant); + + std::array<uint32_t, 4> args = { value, value, value, value }; + + // Can't make a scalar composite. + if (count == 1) + return args[0]; + + uint32_t scalarTypeId = this->defFloatType(32); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, count); + + return this->constComposite(vectorTypeId, count, args.data()); + } + + + uint32_t SpirvModule::constbReplicant( + bool replicant, + uint32_t count) { + uint32_t value = this->constBool(replicant); + + std::array<uint32_t, 4> args = { value, value, value, value }; + + // Can't make a scalar composite. + if (count == 1) + return args[0]; + + uint32_t scalarTypeId = this->defBoolType(); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, count); + + return this->constComposite(vectorTypeId, count, args.data()); + } + + + uint32_t SpirvModule::constiReplicant( + int32_t replicant, + uint32_t count) { + uint32_t value = this->consti32(replicant); + + std::array<uint32_t, 4> args = { value, value, value, value }; + + // Can't make a scalar composite. + if (count == 1) + return args[0]; + + uint32_t scalarTypeId = this->defIntType(32, 1); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, count); + + return this->constComposite(vectorTypeId, count, args.data()); + } + + + uint32_t SpirvModule::constuReplicant( + int32_t replicant, + uint32_t count) { + uint32_t value = this->constu32(replicant); + + std::array<uint32_t, 4> args = { value, value, value, value }; + + // Can't make a scalar composite. + if (count == 1) + return args[0]; + + uint32_t scalarTypeId = this->defIntType(32, 0); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, count); + + return this->constComposite(vectorTypeId, count, args.data()); + } + + + uint32_t SpirvModule::constComposite( + uint32_t typeId, + uint32_t constCount, + const uint32_t* constIds) { + return this->defConst( + spv::OpConstantComposite, + typeId, constCount, constIds); + } + + + uint32_t SpirvModule::constUndef( + uint32_t typeId) { + return this->defConst(spv::OpUndef, + typeId, 0, nullptr); + } + + + uint32_t SpirvModule::lateConst32( + uint32_t typeId) { + uint32_t resultId = this->allocateId(); + m_lateConsts.insert(resultId); + + m_typeConstDefs.putIns (spv::OpConstant, 4); + m_typeConstDefs.putWord(typeId); + m_typeConstDefs.putWord(resultId); + m_typeConstDefs.putWord(0); + return resultId; + } + + + void SpirvModule::setLateConst( + uint32_t constId, + const uint32_t* argIds) { + for (auto ins : m_typeConstDefs) { + if (ins.opCode() != spv::OpConstant + && ins.opCode() != spv::OpConstantComposite) + continue; + + if (ins.arg(2) != constId) + continue; + + for (uint32_t i = 3; i < ins.length(); i++) + ins.setArg(i, argIds[i - 3]); + + return; + } + } + + + uint32_t SpirvModule::specConstBool( + bool v) { + uint32_t typeId = this->defBoolType(); + uint32_t resultId = this->allocateId(); + + const spv::Op op = v + ? spv::OpSpecConstantTrue + : spv::OpSpecConstantFalse; + + m_typeConstDefs.putIns (op, 3); + m_typeConstDefs.putWord (typeId); + m_typeConstDefs.putWord (resultId); + return resultId; + } + + + uint32_t SpirvModule::specConst32( + uint32_t typeId, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_typeConstDefs.putIns (spv::OpSpecConstant, 4); + m_typeConstDefs.putWord (typeId); + m_typeConstDefs.putWord (resultId); + m_typeConstDefs.putWord (value); + return resultId; + } + + + void SpirvModule::decorate( + uint32_t object, + spv::Decoration decoration) { + m_annotations.putIns (spv::OpDecorate, 3); + m_annotations.putWord (object); + m_annotations.putWord (decoration); + } + + + void SpirvModule::decorateArrayStride( + uint32_t object, + uint32_t stride) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationArrayStride); + m_annotations.putInt32(stride); + } + + + void SpirvModule::decorateBinding( + uint32_t object, + uint32_t binding) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationBinding); + m_annotations.putInt32(binding); + } + + + void SpirvModule::decorateBlock(uint32_t object) { + m_annotations.putIns (spv::OpDecorate, 3); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationBlock); + } + + + void SpirvModule::decorateBuiltIn( + uint32_t object, + spv::BuiltIn builtIn) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationBuiltIn); + m_annotations.putWord (builtIn); + } + + + void SpirvModule::decorateComponent( + uint32_t object, + uint32_t location) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationComponent); + m_annotations.putInt32(location); + } + + + void SpirvModule::decorateDescriptorSet( + uint32_t object, + uint32_t set) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationDescriptorSet); + m_annotations.putInt32(set); + } + + + void SpirvModule::decorateIndex( + uint32_t object, + uint32_t index) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationIndex); + m_annotations.putInt32(index); + } + + + void SpirvModule::decorateLocation( + uint32_t object, + uint32_t location) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationLocation); + m_annotations.putInt32(location); + } + + + void SpirvModule::decorateSpecId( + uint32_t object, + uint32_t specId) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationSpecId); + m_annotations.putInt32(specId); + } + + + void SpirvModule::decorateXfb( + uint32_t object, + uint32_t streamId, + uint32_t bufferId, + uint32_t offset, + uint32_t stride) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationStream); + m_annotations.putInt32(streamId); + + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationXfbBuffer); + m_annotations.putInt32(bufferId); + + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationXfbStride); + m_annotations.putInt32(stride); + + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationOffset); + m_annotations.putInt32(offset); + } + + + void SpirvModule::memberDecorateBuiltIn( + uint32_t structId, + uint32_t memberId, + spv::BuiltIn builtIn) { + m_annotations.putIns (spv::OpMemberDecorate, 5); + m_annotations.putWord (structId); + m_annotations.putWord (memberId); + m_annotations.putWord (spv::DecorationBuiltIn); + m_annotations.putWord (builtIn); + } + + + void SpirvModule::memberDecorate( + uint32_t structId, + uint32_t memberId, + spv::Decoration decoration) { + m_annotations.putIns (spv::OpMemberDecorate, 4); + m_annotations.putWord (structId); + m_annotations.putWord (memberId); + m_annotations.putWord (decoration); + } + + + void SpirvModule::memberDecorateMatrixStride( + uint32_t structId, + uint32_t memberId, + uint32_t stride) { + m_annotations.putIns (spv::OpMemberDecorate, 5); + m_annotations.putWord (structId); + m_annotations.putWord (memberId); + m_annotations.putWord (spv::DecorationMatrixStride); + m_annotations.putWord (stride); + } + + + void SpirvModule::memberDecorateOffset( + uint32_t structId, + uint32_t memberId, + uint32_t offset) { + m_annotations.putIns (spv::OpMemberDecorate, 5); + m_annotations.putWord (structId); + m_annotations.putWord (memberId); + m_annotations.putWord (spv::DecorationOffset); + m_annotations.putWord (offset); + } + + + uint32_t SpirvModule::defVoidType() { + return this->defType(spv::OpTypeVoid, 0, nullptr); + } + + + uint32_t SpirvModule::defBoolType() { + return this->defType(spv::OpTypeBool, 0, nullptr); + } + + + uint32_t SpirvModule::defIntType( + uint32_t width, + uint32_t isSigned) { + std::array<uint32_t, 2> args = {{ width, isSigned }}; + return this->defType(spv::OpTypeInt, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defFloatType( + uint32_t width) { + std::array<uint32_t, 1> args = {{ width }}; + return this->defType(spv::OpTypeFloat, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defVectorType( + uint32_t elementType, + uint32_t elementCount) { + std::array<uint32_t, 2> args = + {{ elementType, elementCount }}; + + return this->defType(spv::OpTypeVector, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defMatrixType( + uint32_t columnType, + uint32_t columnCount) { + std::array<uint32_t, 2> args = + {{ columnType, columnCount }}; + + return this->defType(spv::OpTypeMatrix, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defArrayType( + uint32_t typeId, + uint32_t length) { + std::array<uint32_t, 2> args = {{ typeId, length }}; + + return this->defType(spv::OpTypeArray, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defArrayTypeUnique( + uint32_t typeId, + uint32_t length) { + uint32_t resultId = this->allocateId(); + + m_typeConstDefs.putIns (spv::OpTypeArray, 4); + m_typeConstDefs.putWord(resultId); + m_typeConstDefs.putWord(typeId); + m_typeConstDefs.putWord(length); + return resultId; + } + + + uint32_t SpirvModule::defRuntimeArrayType( + uint32_t typeId) { + std::array<uint32_t, 1> args = { typeId }; + + return this->defType(spv::OpTypeRuntimeArray, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defRuntimeArrayTypeUnique( + uint32_t typeId) { + uint32_t resultId = this->allocateId(); + + m_typeConstDefs.putIns (spv::OpTypeRuntimeArray, 3); + m_typeConstDefs.putWord(resultId); + m_typeConstDefs.putWord(typeId); + return resultId; + } + + + uint32_t SpirvModule::defFunctionType( + uint32_t returnType, + uint32_t argCount, + const uint32_t* argTypes) { + std::vector<uint32_t> args; + args.push_back(returnType); + + for (uint32_t i = 0; i < argCount; i++) + args.push_back(argTypes[i]); + + return this->defType(spv::OpTypeFunction, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defStructType( + uint32_t memberCount, + const uint32_t* memberTypes) { + return this->defType(spv::OpTypeStruct, + memberCount, memberTypes); + } + + + uint32_t SpirvModule::defStructTypeUnique( + uint32_t memberCount, + const uint32_t* memberTypes) { + uint32_t resultId = this->allocateId(); + + m_typeConstDefs.putIns (spv::OpTypeStruct, 2 + memberCount); + m_typeConstDefs.putWord(resultId); + + for (uint32_t i = 0; i < memberCount; i++) + m_typeConstDefs.putWord(memberTypes[i]); + return resultId; + } + + + uint32_t SpirvModule::defPointerType( + uint32_t variableType, + spv::StorageClass storageClass) { + std::array<uint32_t, 2> args = {{ + static_cast<uint32_t>(storageClass), + variableType, + }}; + + return this->defType(spv::OpTypePointer, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defSamplerType() { + return this->defType(spv::OpTypeSampler, 0, nullptr); + } + + + uint32_t SpirvModule::defImageType( + uint32_t sampledType, + spv::Dim dimensionality, + uint32_t depth, + uint32_t arrayed, + uint32_t multisample, + uint32_t sampled, + spv::ImageFormat format) { + std::array<uint32_t, 7> args = {{ + sampledType, + static_cast<uint32_t>(dimensionality), + depth, arrayed, + multisample, + sampled, + static_cast<uint32_t>(format) + }}; + + return this->defType(spv::OpTypeImage, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defSampledImageType( + uint32_t imageType) { + return this->defType(spv::OpTypeSampledImage, 1, &imageType); + } + + + uint32_t SpirvModule::newVar( + uint32_t pointerType, + spv::StorageClass storageClass) { + uint32_t resultId = this->allocateId(); + + auto& code = storageClass != spv::StorageClassFunction + ? m_variables : m_code; + + code.putIns (spv::OpVariable, 4); + code.putWord (pointerType); + code.putWord (resultId); + code.putWord (storageClass); + return resultId; + } + + + uint32_t SpirvModule::newVarInit( + uint32_t pointerType, + spv::StorageClass storageClass, + uint32_t initialValue) { + uint32_t resultId = this->allocateId(); + + auto& code = storageClass != spv::StorageClassFunction + ? m_variables : m_code; + + code.putIns (spv::OpVariable, 5); + code.putWord (pointerType); + code.putWord (resultId); + code.putWord (storageClass); + code.putWord (initialValue); + return resultId; + } + + + void SpirvModule::functionBegin( + uint32_t returnType, + uint32_t functionId, + uint32_t functionType, + spv::FunctionControlMask functionControl) { + m_code.putIns (spv::OpFunction, 5); + m_code.putWord(returnType); + m_code.putWord(functionId); + m_code.putWord(functionControl); + m_code.putWord(functionType); + } + + + uint32_t SpirvModule::functionParameter( + uint32_t parameterType) { + uint32_t parameterId = this->allocateId(); + + m_code.putIns (spv::OpFunctionParameter, 3); + m_code.putWord(parameterType); + m_code.putWord(parameterId); + return parameterId; + } + + + void SpirvModule::functionEnd() { + m_code.putIns (spv::OpFunctionEnd, 1); + } + + + uint32_t SpirvModule::opAccessChain( + uint32_t resultType, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAccessChain, 4 + indexCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(composite); + + for (uint32_t i = 0; i < indexCount; i++) + m_code.putInt32(indexArray[i]); + return resultId; + } + + + uint32_t SpirvModule::opArrayLength( + uint32_t resultType, + uint32_t structure, + uint32_t memberId) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpArrayLength, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(structure); + m_code.putWord(memberId); + return resultId; + } + + + uint32_t SpirvModule::opAny( + uint32_t resultType, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAny, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector); + return resultId; + } + + + uint32_t SpirvModule::opAll( + uint32_t resultType, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAll, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector); + return resultId; + } + + + uint32_t SpirvModule::opAtomicLoad( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicLoad, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + return resultId; + } + + + void SpirvModule::opAtomicStore( + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + m_code.putIns (spv::OpAtomicStore, 5); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + } + + + uint32_t SpirvModule::opAtomicExchange( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicExchange, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicCompareExchange( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t equal, + uint32_t unequal, + uint32_t value, + uint32_t comparator) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicCompareExchange, 9); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(equal); + m_code.putWord(unequal); + m_code.putWord(value); + m_code.putWord(comparator); + return resultId; + } + + + uint32_t SpirvModule::opAtomicIIncrement( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicIIncrement, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + return resultId; + } + + + uint32_t SpirvModule::opAtomicIDecrement( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicIDecrement, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + return resultId; + } + + + uint32_t SpirvModule::opAtomicIAdd( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicIAdd, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicISub( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicISub, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicSMin( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicSMin, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicSMax( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicSMax, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicUMin( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicUMin, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicUMax( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicUMax, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicAnd( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicAnd, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicOr( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicOr, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicXor( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicXor, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opBitcast( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitcast, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opBitCount( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitCount, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opBitReverse( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitReverse, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFindILsb( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FindILsb); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFindUMsb( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FindUMsb); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFindSMsb( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FindSMsb); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opBitFieldInsert( + uint32_t resultType, + uint32_t base, + uint32_t insert, + uint32_t offset, + uint32_t count) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitFieldInsert, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(insert); + m_code.putWord(offset); + m_code.putWord(count); + return resultId; + } + + + uint32_t SpirvModule::opBitFieldSExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitFieldSExtract, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(offset); + m_code.putWord(count); + return resultId; + } + + + uint32_t SpirvModule::opBitFieldUExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitFieldUExtract, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(offset); + m_code.putWord(count); + return resultId; + } + + + uint32_t SpirvModule::opBitwiseAnd( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitwiseAnd, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opBitwiseOr( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitwiseOr, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opBitwiseXor( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitwiseXor, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opNot( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpNot, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opShiftLeftLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpShiftLeftLogical, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(shift); + return resultId; + } + + + uint32_t SpirvModule::opShiftRightArithmetic( + uint32_t resultType, + uint32_t base, + uint32_t shift) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpShiftRightArithmetic, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(shift); + return resultId; + } + + + uint32_t SpirvModule::opShiftRightLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpShiftRightLogical, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(shift); + return resultId; + } + + + uint32_t SpirvModule::opConvertFtoS( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpConvertFToS, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opConvertFtoU( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpConvertFToU, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opConvertStoF( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpConvertSToF, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opConvertUtoF( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpConvertUToF, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opCompositeConstruct( + uint32_t resultType, + uint32_t valueCount, + const uint32_t* valueArray) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpCompositeConstruct, 3 + valueCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + + for (uint32_t i = 0; i < valueCount; i++) + m_code.putWord(valueArray[i]); + return resultId; + } + + + uint32_t SpirvModule::opCompositeExtract( + uint32_t resultType, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpCompositeExtract, 4 + indexCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(composite); + + for (uint32_t i = 0; i < indexCount; i++) + m_code.putInt32(indexArray[i]); + return resultId; + } + + + uint32_t SpirvModule::opCompositeInsert( + uint32_t resultType, + uint32_t object, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpCompositeInsert, 5 + indexCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(object); + m_code.putWord(composite); + + for (uint32_t i = 0; i < indexCount; i++) + m_code.putInt32(indexArray[i]); + return resultId; + } + + + uint32_t SpirvModule::opDpdx( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdx, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDpdy( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdy, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDpdxCoarse( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdxCoarse, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDpdyCoarse( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdyCoarse, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDpdxFine( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdxFine, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDpdyFine( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdyFine, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opVectorExtractDynamic( + uint32_t resultType, + uint32_t vector, + uint32_t index) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpVectorExtractDynamic, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector); + m_code.putWord(index); + return resultId; + } + + + uint32_t SpirvModule::opVectorShuffle( + uint32_t resultType, + uint32_t vectorLeft, + uint32_t vectorRight, + uint32_t indexCount, + const uint32_t* indexArray) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpVectorShuffle, 5 + indexCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vectorLeft); + m_code.putWord(vectorRight); + + for (uint32_t i = 0; i < indexCount; i++) + m_code.putInt32(indexArray[i]); + return resultId; + } + + + uint32_t SpirvModule::opSNegate( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSNegate, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFNegate( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFNegate, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opSAbs( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450SAbs); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFAbs( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FAbs); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFSign( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FSign); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFMix( + uint32_t resultType, + uint32_t x, + uint32_t y, + uint32_t a) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 8); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FMix); + m_code.putWord(x); + m_code.putWord(y); + m_code.putWord(a); + return resultId; + } + + + uint32_t SpirvModule::opCross( + uint32_t resultType, + uint32_t x, + uint32_t y) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Cross); + m_code.putWord(x); + m_code.putWord(y); + return resultId; + } + + + uint32_t SpirvModule::opIAdd( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpIAdd, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opISub( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpISub, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFAdd( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFAdd, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFSub( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFSub, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opSDiv( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSDiv, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opUDiv( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpUDiv, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opSRem( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSRem, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opUMod( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpUMod, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFDiv( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFDiv, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opIMul( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpIMul, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFMul( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFMul, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opVectorTimesScalar( + uint32_t resultType, + uint32_t vector, + uint32_t scalar) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpVectorTimesScalar, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector); + m_code.putWord(scalar); + return resultId; + } + + + uint32_t SpirvModule::opMatrixTimesMatrix( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpMatrixTimesMatrix, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opMatrixTimesVector( + uint32_t resultType, + uint32_t matrix, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpMatrixTimesVector, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(matrix); + m_code.putWord(vector); + return resultId; + } + + + uint32_t SpirvModule::opVectorTimesMatrix( + uint32_t resultType, + uint32_t vector, + uint32_t matrix) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpVectorTimesMatrix, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector); + m_code.putWord(matrix); + return resultId; + } + + + uint32_t SpirvModule::opTranspose( + uint32_t resultType, + uint32_t matrix) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpTranspose, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(matrix); + return resultId; + } + + + uint32_t SpirvModule::opInverse( + uint32_t resultType, + uint32_t matrix) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450MatrixInverse); + m_code.putWord(matrix); + return resultId; + } + + + uint32_t SpirvModule::opFFma( + uint32_t resultType, + uint32_t a, + uint32_t b, + uint32_t c) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 8); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Fma); + m_code.putWord(a); + m_code.putWord(b); + m_code.putWord(c); + return resultId; + } + + + uint32_t SpirvModule::opFMax( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FMax); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFMin( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FMin); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opNMax( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450NMax); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opNMin( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450NMin); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opSMax( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450SMax); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opSMin( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450SMin); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opUMax( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450UMax); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opUMin( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450UMin); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFClamp( + uint32_t resultType, + uint32_t x, + uint32_t minVal, + uint32_t maxVal) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 8); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FClamp); + m_code.putWord(x); + m_code.putWord(minVal); + m_code.putWord(maxVal); + return resultId; + } + + + uint32_t SpirvModule::opNClamp( + uint32_t resultType, + uint32_t x, + uint32_t minVal, + uint32_t maxVal) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 8); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450NClamp); + m_code.putWord(x); + m_code.putWord(minVal); + m_code.putWord(maxVal); + return resultId; + } + + + uint32_t SpirvModule::opIEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpIEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opINotEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpINotEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opSLessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSLessThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opSLessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSLessThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opSGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSGreaterThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opSGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSGreaterThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opULessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpULessThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opULessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpULessThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opUGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpUGreaterThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opUGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpUGreaterThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdNotEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdNotEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdLessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdLessThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdLessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdLessThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdGreaterThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdGreaterThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opLogicalEqual( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLogicalEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opLogicalNotEqual( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLogicalNotEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opLogicalAnd( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLogicalAnd, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opLogicalOr( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLogicalOr, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opLogicalNot( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLogicalNot, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDot( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDot, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opSin( + uint32_t resultType, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Sin); + m_code.putWord(vector); + return resultId; + } + + + uint32_t SpirvModule::opCos( + uint32_t resultType, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Cos); + m_code.putWord(vector); + return resultId; + } + + + uint32_t SpirvModule::opSqrt( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Sqrt); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opInverseSqrt( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450InverseSqrt); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opNormalize( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Normalize); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opReflect( + uint32_t resultType, + uint32_t incident, + uint32_t normal) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Reflect); + m_code.putWord(incident); + m_code.putWord(normal); + return resultId; + } + + + uint32_t SpirvModule::opLength( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Length); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opExp2( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Exp2); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opExp( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Exp); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opLog2( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Log2); + m_code.putWord(operand); + return resultId; + } + + uint32_t SpirvModule::opPow( + uint32_t resultType, + uint32_t base, + uint32_t exponent) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Pow); + m_code.putWord(base); + m_code.putWord(exponent); + return resultId; + } + + uint32_t SpirvModule::opFract( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Fract); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opCeil( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Ceil); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFloor( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Floor); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opRound( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Round); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opRoundEven( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450RoundEven); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opTrunc( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Trunc); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFConvert( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFConvert, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opPackHalf2x16( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450PackHalf2x16); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opUnpackHalf2x16( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450UnpackHalf2x16); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opSelect( + uint32_t resultType, + uint32_t condition, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSelect, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(condition); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opIsNan( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpIsNan, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opIsInf( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpIsInf, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFunctionCall( + uint32_t resultType, + uint32_t functionId, + uint32_t argCount, + const uint32_t* argIds) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFunctionCall, 4 + argCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(functionId); + + for (uint32_t i = 0; i < argCount; i++) + m_code.putWord(argIds[i]); + return resultId; + } + + + void SpirvModule::opLabel(uint32_t labelId) { + m_code.putIns (spv::OpLabel, 2); + m_code.putWord(labelId); + } + + + uint32_t SpirvModule::opLoad( + uint32_t typeId, + uint32_t pointerId) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLoad, 4); + m_code.putWord(typeId); + m_code.putWord(resultId); + m_code.putWord(pointerId); + return resultId; + } + + + void SpirvModule::opStore( + uint32_t pointerId, + uint32_t valueId) { + m_code.putIns (spv::OpStore, 3); + m_code.putWord(pointerId); + m_code.putWord(valueId); + } + + + uint32_t SpirvModule::opInterpolateAtCentroid( + uint32_t resultType, + uint32_t interpolant) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450InterpolateAtCentroid); + m_code.putWord(interpolant); + return resultId; + } + + + uint32_t SpirvModule::opInterpolateAtSample( + uint32_t resultType, + uint32_t interpolant, + uint32_t sample) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450InterpolateAtSample); + m_code.putWord(interpolant); + m_code.putWord(sample); + return resultId; + } + + + uint32_t SpirvModule::opInterpolateAtOffset( + uint32_t resultType, + uint32_t interpolant, + uint32_t offset) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450InterpolateAtOffset); + m_code.putWord(interpolant); + m_code.putWord(offset); + return resultId; + } + + + uint32_t SpirvModule::opImage( + uint32_t resultType, + uint32_t sampledImage) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImage, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + return resultId; + } + + + uint32_t SpirvModule::opImageRead( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageRead, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + void SpirvModule::opImageWrite( + uint32_t image, + uint32_t coordinates, + uint32_t texel, + const SpirvImageOperands& operands) { + m_code.putIns (spv::OpImageWrite, + 4 + getImageOperandWordCount(operands)); + m_code.putWord(image); + m_code.putWord(coordinates); + m_code.putWord(texel); + + putImageOperands(operands); + } + + + uint32_t SpirvModule::opSampledImage( + uint32_t resultType, + uint32_t image, + uint32_t sampler) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSampledImage, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + m_code.putWord(sampler); + return resultId; + } + + + uint32_t SpirvModule::opImageTexelPointer( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + uint32_t sample) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageTexelPointer, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + m_code.putWord(coordinates); + m_code.putWord(sample); + return resultId; + } + + + uint32_t SpirvModule::opImageQuerySizeLod( + uint32_t resultType, + uint32_t image, + uint32_t lod) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageQuerySizeLod, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + m_code.putWord(lod); + return resultId; + } + + + uint32_t SpirvModule::opImageQuerySize( + uint32_t resultType, + uint32_t image) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageQuerySize, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + return resultId; + } + + + uint32_t SpirvModule::opImageQueryLevels( + uint32_t resultType, + uint32_t image) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageQueryLevels, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + return resultId; + } + + + uint32_t SpirvModule::opImageQueryLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageQueryLod, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + return resultId; + } + + + uint32_t SpirvModule::opImageQuerySamples( + uint32_t resultType, + uint32_t image) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageQuerySamples, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + return resultId; + } + + + uint32_t SpirvModule::opImageFetch( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageFetch, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageGather( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t component, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageGather, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(component); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageDrefGather( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageDrefGather, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(reference); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleImplicitLod, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleExplicitLod, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleProjImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleProjImplicitLod, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleProjExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleProjExplicitLod, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleDrefImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleDrefImplicitLod, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(reference); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleDrefExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleDrefExplicitLod, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(reference); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleProjDrefImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleProjDrefImplicitLod, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(reference); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleProjDrefExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleProjDrefExplicitLod, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(reference); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opGroupNonUniformBallot( + uint32_t resultType, + uint32_t execution, + uint32_t predicate) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpGroupNonUniformBallot, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(execution); + m_code.putWord(predicate); + return resultId; + } + + + uint32_t SpirvModule::opGroupNonUniformBallotBitCount( + uint32_t resultType, + uint32_t execution, + uint32_t operation, + uint32_t ballot) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpGroupNonUniformBallotBitCount, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(execution); + m_code.putWord(operation); + m_code.putWord(ballot); + return resultId; + } + + + uint32_t SpirvModule::opGroupNonUniformElect( + uint32_t resultType, + uint32_t execution) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpGroupNonUniformElect, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(execution); + return resultId; + } + + + uint32_t SpirvModule::opGroupNonUniformBroadcastFirst( + uint32_t resultType, + uint32_t execution, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpGroupNonUniformBroadcastFirst, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(execution); + m_code.putWord(value); + return resultId; + } + + + void SpirvModule::opControlBarrier( + uint32_t execution, + uint32_t memory, + uint32_t semantics) { + m_code.putIns (spv::OpControlBarrier, 4); + m_code.putWord(execution); + m_code.putWord(memory); + m_code.putWord(semantics); + } + + + void SpirvModule::opMemoryBarrier( + uint32_t memory, + uint32_t semantics) { + m_code.putIns (spv::OpMemoryBarrier, 3); + m_code.putWord(memory); + m_code.putWord(semantics); + } + + + void SpirvModule::opLoopMerge( + uint32_t mergeBlock, + uint32_t continueTarget, + uint32_t loopControl) { + m_code.putIns (spv::OpLoopMerge, 4); + m_code.putWord(mergeBlock); + m_code.putWord(continueTarget); + m_code.putWord(loopControl); + } + + + void SpirvModule::opSelectionMerge( + uint32_t mergeBlock, + uint32_t selectionControl) { + m_code.putIns (spv::OpSelectionMerge, 3); + m_code.putWord(mergeBlock); + m_code.putWord(selectionControl); + } + + + void SpirvModule::opBranch( + uint32_t label) { + m_code.putIns (spv::OpBranch, 2); + m_code.putWord(label); + } + + + void SpirvModule::opBranchConditional( + uint32_t condition, + uint32_t trueLabel, + uint32_t falseLabel) { + m_code.putIns (spv::OpBranchConditional, 4); + m_code.putWord(condition); + m_code.putWord(trueLabel); + m_code.putWord(falseLabel); + } + + + void SpirvModule::opSwitch( + uint32_t selector, + uint32_t jumpDefault, + uint32_t caseCount, + const SpirvSwitchCaseLabel* caseLabels) { + m_code.putIns (spv::OpSwitch, 3 + 2 * caseCount); + m_code.putWord(selector); + m_code.putWord(jumpDefault); + + for (uint32_t i = 0; i < caseCount; i++) { + m_code.putWord(caseLabels[i].literal); + m_code.putWord(caseLabels[i].labelId); + } + } + + + uint32_t SpirvModule::opPhi( + uint32_t resultType, + uint32_t sourceCount, + const SpirvPhiLabel* sourceLabels) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpPhi, 3 + 2 * sourceCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + + for (uint32_t i = 0; i < sourceCount; i++) { + m_code.putWord(sourceLabels[i].varId); + m_code.putWord(sourceLabels[i].labelId); + } + + return resultId; + } + + + void SpirvModule::opReturn() { + m_code.putIns (spv::OpReturn, 1); + } + + + void SpirvModule::opKill() { + m_code.putIns (spv::OpKill, 1); + } + + + void SpirvModule::opDemoteToHelperInvocation() { + m_code.putIns (spv::OpDemoteToHelperInvocationEXT, 1); + } + + + void SpirvModule::opEmitVertex( + uint32_t streamId) { + if (streamId == 0) { + m_code.putIns (spv::OpEmitVertex, 1); + } else { + m_code.putIns (spv::OpEmitStreamVertex, 2); + m_code.putWord(streamId); + } + } + + + void SpirvModule::opEndPrimitive( + uint32_t streamId) { + if (streamId == 0) { + m_code.putIns (spv::OpEndPrimitive, 1); + } else { + m_code.putIns (spv::OpEndStreamPrimitive, 2); + m_code.putWord(streamId); + } + } + + + uint32_t SpirvModule::defType( + spv::Op op, + uint32_t argCount, + const uint32_t* argIds) { + // Since the type info is stored in the code buffer, + // we can use the code buffer to look up type IDs as + // well. Result IDs are always stored as argument 1. + for (auto ins : m_typeConstDefs) { + bool match = ins.opCode() == op + && ins.length() == 2 + argCount; + + for (uint32_t i = 0; i < argCount && match; i++) + match &= ins.arg(2 + i) == argIds[i]; + + if (match) + return ins.arg(1); + } + + // Type not yet declared, create a new one. + uint32_t resultId = this->allocateId(); + m_typeConstDefs.putIns (op, 2 + argCount); + m_typeConstDefs.putWord(resultId); + + for (uint32_t i = 0; i < argCount; i++) + m_typeConstDefs.putWord(argIds[i]); + return resultId; + } + + + uint32_t SpirvModule::defConst( + spv::Op op, + uint32_t typeId, + uint32_t argCount, + const uint32_t* argIds) { + // Avoid declaring constants multiple times + for (auto ins : m_typeConstDefs) { + bool match = ins.opCode() == op + && ins.length() == 3 + argCount + && ins.arg(1) == typeId; + + for (uint32_t i = 0; i < argCount && match; i++) + match &= ins.arg(3 + i) == argIds[i]; + + if (!match) + continue; + + uint32_t id = ins.arg(2); + + if (m_lateConsts.find(id) == m_lateConsts.end()) + return id; + } + + // Constant not yet declared, make a new one + uint32_t resultId = this->allocateId(); + m_typeConstDefs.putIns (op, 3 + argCount); + m_typeConstDefs.putWord(typeId); + m_typeConstDefs.putWord(resultId); + + for (uint32_t i = 0; i < argCount; i++) + m_typeConstDefs.putWord(argIds[i]); + return resultId; + } + + + void SpirvModule::instImportGlsl450() { + m_instExtGlsl450 = this->allocateId(); + const char* name = "GLSL.std.450"; + + m_instExt.putIns (spv::OpExtInstImport, 2 + m_instExt.strLen(name)); + m_instExt.putWord(m_instExtGlsl450); + m_instExt.putStr (name); + } + + + uint32_t SpirvModule::getImageOperandWordCount(const SpirvImageOperands& op) const { + // Each flag may add one or more operands + const uint32_t result + = ((op.flags & spv::ImageOperandsBiasMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsLodMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsConstOffsetMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsGradMask) ? 2 : 0) + + ((op.flags & spv::ImageOperandsOffsetMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsConstOffsetsMask)? 1 : 0) + + ((op.flags & spv::ImageOperandsSampleMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsMinLodMask) ? 1 : 0); + + // Add a DWORD for the operand mask if it is non-zero + return result != 0 ? result + 1 : 0; + } + + + void SpirvModule::putImageOperands(const SpirvImageOperands& op) { + if (op.flags != 0) { + m_code.putWord(op.flags); + + if (op.flags & spv::ImageOperandsBiasMask) + m_code.putWord(op.sLodBias); + + if (op.flags & spv::ImageOperandsLodMask) + m_code.putWord(op.sLod); + + if (op.flags & spv::ImageOperandsConstOffsetMask) + m_code.putWord(op.sConstOffset); + + if (op.flags & spv::ImageOperandsGradMask) { + m_code.putWord(op.sGradX); + m_code.putWord(op.sGradY); + } + + if (op.flags & spv::ImageOperandsOffsetMask) + m_code.putWord(op.gOffset); + + if (op.flags & spv::ImageOperandsConstOffsetsMask) + m_code.putWord(op.gConstOffsets); + + if (op.flags & spv::ImageOperandsSampleMask) + m_code.putWord(op.sSampleId); + + if (op.flags & spv::ImageOperandsMinLodMask) + m_code.putWord(op.sMinLod); + } + } + +}
\ No newline at end of file diff --git a/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_module.h b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_module.h new file mode 100644 index 00000000..7ce5b8f1 --- /dev/null +++ b/src/libs/dxvk-native-1.9.2a/src/spirv/spirv_module.h @@ -0,0 +1,1280 @@ +#pragma once + +#include <unordered_set> + +#include "spirv_code_buffer.h" + +namespace dxvk { + + struct SpirvPhiLabel { + uint32_t varId = 0; + uint32_t labelId = 0; + }; + + struct SpirvSwitchCaseLabel { + uint32_t literal = 0; + uint32_t labelId = 0; + }; + + struct SpirvImageOperands { + uint32_t flags = 0; + uint32_t sLodBias = 0; + uint32_t sLod = 0; + uint32_t sConstOffset = 0; + uint32_t sGradX = 0; + uint32_t sGradY = 0; + uint32_t gOffset = 0; + uint32_t gConstOffsets = 0; + uint32_t sSampleId = 0; + uint32_t sMinLod = 0; + }; + + constexpr uint32_t spvVersion(uint32_t major, uint32_t minor) { + return (major << 16) | (minor << 8); + } + + /** + * \brief SPIR-V module + * + * This class generates a code buffer containing a full + * SPIR-V shader module. Ensures that the module layout + * is valid, as defined in the SPIR-V 1.0 specification, + * section 2.4 "Logical Layout of a Module". + */ + class SpirvModule { + + public: + + explicit SpirvModule(uint32_t version); + + ~SpirvModule(); + + SpirvCodeBuffer compile() const; + + size_t getInsertionPtr() { + return m_code.getInsertionPtr(); + } + + void beginInsertion(size_t ptr) { + m_code.beginInsertion(ptr); + } + + void endInsertion() { + m_code.endInsertion(); + } + + uint32_t allocateId(); + + bool hasCapability( + spv::Capability capability); + + void enableCapability( + spv::Capability capability); + + void enableExtension( + const char* extensionName); + + void addEntryPoint( + uint32_t entryPointId, + spv::ExecutionModel executionModel, + const char* name, + uint32_t interfaceCount, + const uint32_t* interfaceIds); + + void setMemoryModel( + spv::AddressingModel addressModel, + spv::MemoryModel memoryModel); + + void setExecutionMode( + uint32_t entryPointId, + spv::ExecutionMode executionMode); + + void setExecutionMode( + uint32_t entryPointId, + spv::ExecutionMode executionMode, + uint32_t argCount, + const uint32_t* args); + + void setInvocations( + uint32_t entryPointId, + uint32_t invocations); + + void setLocalSize( + uint32_t entryPointId, + uint32_t x, + uint32_t y, + uint32_t z); + + void setOutputVertices( + uint32_t entryPointId, + uint32_t vertexCount); + + uint32_t addDebugString( + const char* string); + + void setDebugSource( + spv::SourceLanguage language, + uint32_t version, + uint32_t file, + const char* source); + + void setDebugName( + uint32_t expressionId, + const char* debugName); + + void setDebugMemberName( + uint32_t structId, + uint32_t memberId, + const char* debugName); + + uint32_t constBool( + bool v); + + uint32_t consti32( + int32_t v); + + uint32_t consti64( + int64_t v); + + uint32_t constu32( + uint32_t v); + + uint32_t constu64( + uint64_t v); + + uint32_t constf32( + float v); + + uint32_t constf64( + double v); + + uint32_t constvec4i32( + int32_t x, + int32_t y, + int32_t z, + int32_t w); + + uint32_t constvec4b32( + bool x, + bool y, + bool z, + bool w); + + uint32_t constvec4u32( + uint32_t x, + uint32_t y, + uint32_t z, + uint32_t w); + + uint32_t constvec2f32( + float x, + float y); + + uint32_t constvec3f32( + float x, + float y, + float z); + + uint32_t constvec4f32( + float x, + float y, + float z, + float w); + + uint32_t constfReplicant( + float replicant, + uint32_t count); + + uint32_t constbReplicant( + bool replicant, + uint32_t count); + + uint32_t constiReplicant( + int32_t replicant, + uint32_t count); + + uint32_t constuReplicant( + int32_t replicant, + uint32_t count); + + uint32_t constComposite( + uint32_t typeId, + uint32_t constCount, + const uint32_t* constIds); + + uint32_t constUndef( + uint32_t typeId); + + uint32_t lateConst32( + uint32_t typeId); + + void setLateConst( + uint32_t constId, + const uint32_t* argIds); + + uint32_t specConstBool( + bool v); + + uint32_t specConst32( + uint32_t typeId, + uint32_t value); + + void decorate( + uint32_t object, + spv::Decoration decoration); + + void decorateArrayStride( + uint32_t object, + uint32_t stride); + + void decorateBinding( + uint32_t object, + uint32_t binding); + + void decorateBlock( + uint32_t object); + + void decorateBuiltIn( + uint32_t object, + spv::BuiltIn builtIn); + + void decorateComponent( + uint32_t object, + uint32_t location); + + void decorateDescriptorSet( + uint32_t object, + uint32_t set); + + void decorateIndex( + uint32_t object, + uint32_t index); + + void decorateLocation( + uint32_t object, + uint32_t location); + + void decorateSpecId( + uint32_t object, + uint32_t specId); + + void decorateXfb( + uint32_t object, + uint32_t streamId, + uint32_t bufferId, + uint32_t offset, + uint32_t stride); + + void memberDecorateBuiltIn( + uint32_t structId, + uint32_t memberId, + spv::BuiltIn builtIn); + + void memberDecorate( + uint32_t structId, + uint32_t memberId, + spv::Decoration decoration); + + void memberDecorateMatrixStride( + uint32_t structId, + uint32_t memberId, + uint32_t stride); + + void memberDecorateOffset( + uint32_t structId, + uint32_t memberId, + uint32_t offset); + + uint32_t defVoidType(); + + uint32_t defBoolType(); + + uint32_t defIntType( + uint32_t width, + uint32_t isSigned); + + uint32_t defFloatType( + uint32_t width); + + uint32_t defVectorType( + uint32_t elementType, + uint32_t elementCount); + + uint32_t defMatrixType( + uint32_t columnType, + uint32_t columnCount); + + uint32_t defArrayType( + uint32_t typeId, + uint32_t length); + + uint32_t defArrayTypeUnique( + uint32_t typeId, + uint32_t length); + + uint32_t defRuntimeArrayType( + uint32_t typeId); + + uint32_t defRuntimeArrayTypeUnique( + uint32_t typeId); + + uint32_t defFunctionType( + uint32_t returnType, + uint32_t argCount, + const uint32_t* argTypes); + + uint32_t defStructType( + uint32_t memberCount, + const uint32_t* memberTypes); + + uint32_t defStructTypeUnique( + uint32_t memberCount, + const uint32_t* memberTypes); + + uint32_t defPointerType( + uint32_t variableType, + spv::StorageClass storageClass); + + uint32_t defSamplerType(); + + uint32_t defImageType( + uint32_t sampledType, + spv::Dim dimensionality, + uint32_t depth, + uint32_t arrayed, + uint32_t multisample, + uint32_t sampled, + spv::ImageFormat format); + + uint32_t defSampledImageType( + uint32_t imageType); + + uint32_t newVar( + uint32_t pointerType, + spv::StorageClass storageClass); + + uint32_t newVarInit( + uint32_t pointerType, + spv::StorageClass storageClass, + uint32_t initialValue); + + void functionBegin( + uint32_t returnType, + uint32_t functionId, + uint32_t functionType, + spv::FunctionControlMask functionControl); + + uint32_t functionParameter( + uint32_t parameterType); + + void functionEnd(); + + uint32_t opAccessChain( + uint32_t resultType, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray); + + uint32_t opArrayLength( + uint32_t resultType, + uint32_t structure, + uint32_t memberId); + + uint32_t opAny( + uint32_t resultType, + uint32_t vector); + + uint32_t opAll( + uint32_t resultType, + uint32_t vector); + + uint32_t opAtomicLoad( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics); + + void opAtomicStore( + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicExchange( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicCompareExchange( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t equal, + uint32_t unequal, + uint32_t value, + uint32_t comparator); + + uint32_t opAtomicIIncrement( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics); + + uint32_t opAtomicIDecrement( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics); + + uint32_t opAtomicIAdd( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicISub( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicSMin( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicSMax( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicUMin( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicUMax( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicAnd( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicOr( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicXor( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opBitcast( + uint32_t resultType, + uint32_t operand); + + uint32_t opBitCount( + uint32_t resultType, + uint32_t operand); + + uint32_t opBitReverse( + uint32_t resultType, + uint32_t operand); + + uint32_t opFindILsb( + uint32_t resultType, + uint32_t operand); + + uint32_t opFindUMsb( + uint32_t resultType, + uint32_t operand); + + uint32_t opFindSMsb( + uint32_t resultType, + uint32_t operand); + + uint32_t opBitFieldInsert( + uint32_t resultType, + uint32_t base, + uint32_t insert, + uint32_t offset, + uint32_t count); + + uint32_t opBitFieldSExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count); + + uint32_t opBitFieldUExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count); + + uint32_t opBitwiseAnd( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opBitwiseOr( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opBitwiseXor( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opNot( + uint32_t resultType, + uint32_t operand); + + uint32_t opShiftLeftLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift); + + uint32_t opShiftRightArithmetic( + uint32_t resultType, + uint32_t base, + uint32_t shift); + + uint32_t opShiftRightLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift); + + uint32_t opConvertFtoS( + uint32_t resultType, + uint32_t operand); + + uint32_t opConvertFtoU( + uint32_t resultType, + uint32_t operand); + + uint32_t opConvertStoF( + uint32_t resultType, + uint32_t operand); + + uint32_t opConvertUtoF( + uint32_t resultType, + uint32_t operand); + + uint32_t opCompositeConstruct( + uint32_t resultType, + uint32_t valueCount, + const uint32_t* valueArray); + + uint32_t opCompositeExtract( + uint32_t resultType, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray); + + uint32_t opCompositeInsert( + uint32_t resultType, + uint32_t object, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray); + + uint32_t opDpdx( + uint32_t resultType, + uint32_t operand); + + uint32_t opDpdy( + uint32_t resultType, + uint32_t operand); + + uint32_t opDpdxCoarse( + uint32_t resultType, + uint32_t operand); + + uint32_t opDpdyCoarse( + uint32_t resultType, + uint32_t operand); + + uint32_t opDpdxFine( + uint32_t resultType, + uint32_t operand); + + uint32_t opDpdyFine( + uint32_t resultType, + uint32_t operand); + + uint32_t opVectorExtractDynamic( + uint32_t resultType, + uint32_t vector, + uint32_t index); + + uint32_t opVectorShuffle( + uint32_t resultType, + uint32_t vectorLeft, + uint32_t vectorRight, + uint32_t indexCount, + const uint32_t* indexArray); + + uint32_t opSNegate( + uint32_t resultType, + uint32_t operand); + + uint32_t opFNegate( + uint32_t resultType, + uint32_t operand); + + uint32_t opSAbs( + uint32_t resultType, + uint32_t operand); + + uint32_t opFAbs( + uint32_t resultType, + uint32_t operand); + + uint32_t opFSign( + uint32_t resultType, + uint32_t operand); + + uint32_t opFMix( + uint32_t resultType, + uint32_t x, + uint32_t y, + uint32_t a); + + uint32_t opCross( + uint32_t resultType, + uint32_t x, + uint32_t y); + + uint32_t opIAdd( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opISub( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFAdd( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFSub( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opSDiv( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opUDiv( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opSRem( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opUMod( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFDiv( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opIMul( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFMul( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opVectorTimesScalar( + uint32_t resultType, + uint32_t vector, + uint32_t scalar); + + uint32_t opMatrixTimesMatrix( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opMatrixTimesVector( + uint32_t resultType, + uint32_t matrix, + uint32_t vector); + + uint32_t opVectorTimesMatrix( + uint32_t resultType, + uint32_t vector, + uint32_t matrix); + + uint32_t opTranspose( + uint32_t resultType, + uint32_t matrix); + + uint32_t opInverse( + uint32_t resultType, + uint32_t matrix); + + uint32_t opFFma( + uint32_t resultType, + uint32_t a, + uint32_t b, + uint32_t c); + + uint32_t opFMax( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFMin( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opNMax( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opNMin( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opSMax( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opSMin( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opUMax( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opUMin( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFClamp( + uint32_t resultType, + uint32_t x, + uint32_t minVal, + uint32_t maxVal); + + uint32_t opNClamp( + uint32_t resultType, + uint32_t x, + uint32_t minVal, + uint32_t maxVal); + + uint32_t opIEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opINotEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opSLessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opSLessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opSGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opSGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opULessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opULessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opUGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opUGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdNotEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdLessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdLessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opLogicalEqual( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opLogicalNotEqual( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opLogicalAnd( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opLogicalOr( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opLogicalNot( + uint32_t resultType, + uint32_t operand); + + uint32_t opDot( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opSin( + uint32_t resultType, + uint32_t vector); + + uint32_t opCos( + uint32_t resultType, + uint32_t vector); + + uint32_t opSqrt( + uint32_t resultType, + uint32_t operand); + + uint32_t opInverseSqrt( + uint32_t resultType, + uint32_t operand); + + uint32_t opNormalize( + uint32_t resultType, + uint32_t operand); + + uint32_t opReflect( + uint32_t resultType, + uint32_t incident, + uint32_t normal); + + uint32_t opLength( + uint32_t resultType, + uint32_t operand); + + uint32_t opExp2( + uint32_t resultType, + uint32_t operand); + + uint32_t opExp( + uint32_t resultType, + uint32_t operand); + + uint32_t opLog2( + uint32_t resultType, + uint32_t operand); + + uint32_t opPow( + uint32_t resultType, + uint32_t base, + uint32_t exponent); + + uint32_t opFract( + uint32_t resultType, + uint32_t operand); + + uint32_t opCeil( + uint32_t resultType, + uint32_t operand); + + uint32_t opFloor( + uint32_t resultType, + uint32_t operand); + + uint32_t opRound( + uint32_t resultType, + uint32_t operand); + + uint32_t opRoundEven( + uint32_t resultType, + uint32_t operand); + + uint32_t opTrunc( + uint32_t resultType, + uint32_t operand); + + uint32_t opFConvert( + uint32_t resultType, + uint32_t operand); + + uint32_t opPackHalf2x16( + uint32_t resultType, + uint32_t operand); + + uint32_t opUnpackHalf2x16( + uint32_t resultType, + uint32_t operand); + + uint32_t opSelect( + uint32_t resultType, + uint32_t condition, + uint32_t operand1, + uint32_t operand2); + + uint32_t opIsNan( + uint32_t resultType, + uint32_t operand); + + uint32_t opIsInf( + uint32_t resultType, + uint32_t operand); + + uint32_t opFunctionCall( + uint32_t resultType, + uint32_t functionId, + uint32_t argCount, + const uint32_t* argIds); + + void opLabel( + uint32_t labelId); + + uint32_t opLoad( + uint32_t typeId, + uint32_t pointerId); + + void opStore( + uint32_t pointerId, + uint32_t valueId); + + uint32_t opInterpolateAtCentroid( + uint32_t resultType, + uint32_t interpolant); + + uint32_t opInterpolateAtSample( + uint32_t resultType, + uint32_t interpolant, + uint32_t sample); + + uint32_t opInterpolateAtOffset( + uint32_t resultType, + uint32_t interpolant, + uint32_t offset); + + uint32_t opImage( + uint32_t resultType, + uint32_t sampledImage); + + uint32_t opImageRead( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + const SpirvImageOperands& operands); + + void opImageWrite( + uint32_t image, + uint32_t coordinates, + uint32_t texel, + const SpirvImageOperands& operands); + + uint32_t opImageTexelPointer( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + uint32_t sample); + + uint32_t opSampledImage( + uint32_t resultType, + uint32_t image, + uint32_t sampler); + + uint32_t opImageQuerySizeLod( + uint32_t resultType, + uint32_t image, + uint32_t lod); + + uint32_t opImageQuerySize( + uint32_t resultType, + uint32_t image); + + uint32_t opImageQueryLevels( + uint32_t resultType, + uint32_t image); + + uint32_t opImageQueryLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates); + + uint32_t opImageQuerySamples( + uint32_t resultType, + uint32_t image); + + uint32_t opImageFetch( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + const SpirvImageOperands& operands); + + uint32_t opImageGather( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t component, + const SpirvImageOperands& operands); + + uint32_t opImageDrefGather( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands); + + uint32_t opImageSampleImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands); + + uint32_t opImageSampleExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands); + + uint32_t opImageSampleProjImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands); + + uint32_t opImageSampleProjExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands); + + uint32_t opImageSampleDrefImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands); + + uint32_t opImageSampleDrefExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands); + + uint32_t opImageSampleProjDrefImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands); + + uint32_t opImageSampleProjDrefExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands); + + uint32_t opGroupNonUniformBallot( + uint32_t resultType, + uint32_t execution, + uint32_t predicate); + + uint32_t opGroupNonUniformBallotBitCount( + uint32_t resultType, + uint32_t execution, + uint32_t operation, + uint32_t ballot); + + uint32_t opGroupNonUniformElect( + uint32_t resultType, + uint32_t execution); + + uint32_t opGroupNonUniformBroadcastFirst( + uint32_t resultType, + uint32_t execution, + uint32_t value); + + void opControlBarrier( + uint32_t execution, + uint32_t memory, + uint32_t semantics); + + void opMemoryBarrier( + uint32_t memory, + uint32_t semantics); + + void opLoopMerge( + uint32_t mergeBlock, + uint32_t continueTarget, + uint32_t loopControl); + + void opSelectionMerge( + uint32_t mergeBlock, + uint32_t selectionControl); + + void opBranch( + uint32_t label); + + void opBranchConditional( + uint32_t condition, + uint32_t trueLabel, + uint32_t falseLabel); + + void opSwitch( + uint32_t selector, + uint32_t jumpDefault, + uint32_t caseCount, + const SpirvSwitchCaseLabel* caseLabels); + + uint32_t opPhi( + uint32_t resultType, + uint32_t sourceCount, + const SpirvPhiLabel* sourceLabels); + + void opReturn(); + + void opKill(); + + void opDemoteToHelperInvocation(); + + void opEmitVertex( + uint32_t streamId); + + void opEndPrimitive( + uint32_t streamId); + + private: + + uint32_t m_version; + uint32_t m_id = 1; + uint32_t m_instExtGlsl450 = 0; + + SpirvCodeBuffer m_capabilities; + SpirvCodeBuffer m_extensions; + SpirvCodeBuffer m_instExt; + SpirvCodeBuffer m_memoryModel; + SpirvCodeBuffer m_entryPoints; + SpirvCodeBuffer m_execModeInfo; + SpirvCodeBuffer m_debugNames; + SpirvCodeBuffer m_annotations; + SpirvCodeBuffer m_typeConstDefs; + SpirvCodeBuffer m_variables; + SpirvCodeBuffer m_code; + + std::unordered_set<uint32_t> m_lateConsts; + + uint32_t defType( + spv::Op op, + uint32_t argCount, + const uint32_t* argIds); + + uint32_t defConst( + spv::Op op, + uint32_t typeId, + uint32_t argCount, + const uint32_t* argIds); + + void instImportGlsl450(); + + uint32_t getImageOperandWordCount( + const SpirvImageOperands& op) const; + + void putImageOperands( + const SpirvImageOperands& op); + + }; + +}
\ No newline at end of file |