summaryrefslogtreecommitdiffstats
path: root/src/libs/dxvk-native-1.9.2a/src/spirv
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/spirv/meson.build9
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/spirv/spirv_code_buffer.cpp154
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/spirv/spirv_code_buffer.h223
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/spirv/spirv_compression.cpp110
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/spirv/spirv_compression.h36
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/spirv/spirv_include.h12
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/spirv/spirv_instruction.h155
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/spirv/spirv_module.cpp3741
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/spirv/spirv_module.h1280
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