From d4e7a0633c016ca69425cd0f27bd85ceac1dadf0 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 30 May 2019 11:55:08 +0100 Subject: [PATCH] Move SPIRVId/SPIRVIterator/SPIRVOperation to common header * We also add an rdcspv namespace, which we'll be generating our own enums etc to replace the spirv.hpp spv namespace. --- .../driver/shaders/spirv/spirv_common.cpp | 41 +++ renderdoc/driver/shaders/spirv/spirv_common.h | 135 +++++++ .../driver/shaders/spirv/spirv_editor.cpp | 316 +++++++---------- renderdoc/driver/shaders/spirv/spirv_editor.h | 295 +++++---------- .../driver/vulkan/vk_bindless_feedback.cpp | 137 +++---- renderdoc/driver/vulkan/vk_postvs.cpp | 335 ++++++++---------- 6 files changed, 610 insertions(+), 649 deletions(-) diff --git a/renderdoc/driver/shaders/spirv/spirv_common.cpp b/renderdoc/driver/shaders/spirv/spirv_common.cpp index 613973c83..382eb3b64 100644 --- a/renderdoc/driver/shaders/spirv/spirv_common.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_common.cpp @@ -24,3 +24,44 @@ #include "spirv_common.h" #include "common/common.h" + +template <> +rdcstr DoStringise(const rdcspv::Id &el) +{ + return StringFormat::Fmt("%u", el.id); +} + +void rdcspv::Iter::nopRemove(size_t idx, size_t count) +{ + RDCASSERT(idx >= 1); + size_t oldSize = size(); + + if(count == 0) + count = oldSize - idx; + + // reduce the size of this op + word(0) = rdcspv::Operation::MakeHeader(opcode(), oldSize - count); + + if(idx + count < oldSize) + { + // move any words on the end into the middle, then nop them + for(size_t i = 0; i < count; i++) + { + word(idx + i) = word(idx + count + i); + word(oldSize - i - 1) = OpNopWord; + } + } + else + { + for(size_t i = 0; i < count; i++) + { + word(idx + i) = OpNopWord; + } + } +} + +void rdcspv::Iter::nopRemove() +{ + for(size_t i = 0, sz = size(); i < sz; i++) + word(i) = OpNopWord; +} \ No newline at end of file diff --git a/renderdoc/driver/shaders/spirv/spirv_common.h b/renderdoc/driver/shaders/spirv/spirv_common.h index 5fec680ec..9e1fc17c4 100644 --- a/renderdoc/driver/shaders/spirv/spirv_common.h +++ b/renderdoc/driver/shaders/spirv/spirv_common.h @@ -25,3 +25,138 @@ #pragma once #include +#include "3rdparty/glslang/SPIRV/spirv.hpp" + +namespace rdcspv +{ +// length of 1 word in the top 16-bits, OpNop = 0 in the lower 16-bits +static constexpr uint32_t OpNopWord = 0x00010000U; + +struct Id +{ + constexpr inline Id() : id(0) {} + constexpr inline Id(uint32_t i) : id(i) {} + inline operator uint32_t() const { return id; } + constexpr inline bool operator==(const Id o) const { return id == o.id; } + constexpr inline bool operator!=(const Id o) const { return id != o.id; } + constexpr inline bool operator<(const Id o) const { return id < o.id; } + constexpr inline bool operator==(const uint32_t o) const { return id == o; } + constexpr inline bool operator!=(const uint32_t o) const { return id != o; } + constexpr inline bool operator<(const uint32_t o) const { return id < o; } + uint32_t id; +}; + +class Operation; + +class Iter +{ +public: + // constructors + Iter() = default; + Iter(std::vector &w, size_t o) : words(&w), offset(o) {} + // increment to the next op + Iter operator++(int) + { + Iter ret = *this; + operator++(); + return ret; + } + Iter operator++() + { + do + { + offset += cur() >> spv::WordCountShift; + // silently skip nops + } while(*this && opcode() == spv::OpNop); + + return *this; + } + bool operator==(const Iter &it) const = delete; + bool operator!=(const Iter &it) const = delete; + bool operator<(const Iter &it) const { return words == it.words && offset < it.offset; } + // utility functions + explicit operator bool() const { return words != NULL && offset < words->size(); } + uint32_t &operator*() { return cur(); } + const uint32_t &operator*() const { return cur(); } + spv::Op opcode() { return spv::Op(cur() & spv::OpCodeMask); } + uint32_t &word(size_t idx) { return words->at(offset + idx); } + const uint32_t &word(size_t idx) const { return words->at(offset + idx); } + size_t offs() const { return offset; } + size_t size() const { return cur() >> spv::WordCountShift; } + // replace part of this operation with NOPs and update the length. Cannot completely erase the + // operation, or expand it + void nopRemove(size_t idx, size_t count = 0); + // completely remove the operation and replace with NOPs + void nopRemove(); + +private: + friend class Operation; + inline uint32_t &cur() { return words->at(offset); } + inline const uint32_t &cur() const { return words->at(offset); } + std::vector::iterator it() { return words->begin() + offset; } + std::vector::const_iterator it() const { return words->cbegin() + offset; } + size_t offset = 0; + std::vector *words = NULL; +}; + +class Operation +{ +public: + // constructor of a synthetic operation, from an operation & subsequent words, calculates the + // length then constructs the first word with opcode + length. + Operation(spv::Op op, const std::vector &data) + { + words.push_back(MakeHeader(op, data.size() + 1)); + words.insert(words.begin() + 1, data.begin(), data.end()); + + iter = Iter(words, 0); + } + + Operation(const Operation &op) + { + words = op.words; + + iter = Iter(words, 0); + } + + static Operation copy(Iter it) + { + Operation ret(it); + + ret.words.insert(ret.words.begin(), it.it(), it.it() + it.size()); + ret.iter = Iter(ret.words, 0); + + return ret; + } + + // constructor that takes existing words from elsewhere and just references it. + // Since this is iterator based, normal iteration invalidation rules apply, if you modify earlier + // in the SPIR-V this operation will become invalid. + Operation(Iter it) : iter(it) {} + uint32_t &operator[](size_t idx) { return iter.word(idx); } + const uint32_t &operator[](size_t idx) const { return iter.word(idx); } + size_t size() const { return iter.size(); } + // insert the words for this op into the destination vector + void appendTo(std::vector &dest) const { dest.insert(dest.end(), begin(), end()); } + void insertInto(std::vector &dest, size_t offset) const + { + dest.insert(dest.begin() + offset, begin(), end()); + } + inline static uint32_t MakeHeader(spv::Op op, size_t WordCount) + { + return (uint32_t(op) & spv::OpCodeMask) | (uint16_t(WordCount) << spv::WordCountShift); + } + +private: + std::vector::const_iterator begin() const { return iter.it(); } + std::vector::const_iterator end() const { return iter.it() + size(); } + // everything is based around this iterator, which may point into our local storage or to external + // storage. + Iter iter; + + // may not be used, if we refer to an external iterator + std::vector words; +}; +}; // namespace rdcspv + +DECLARE_STRINGISE_TYPE(rdcspv::Id); diff --git a/renderdoc/driver/shaders/spirv/spirv_editor.cpp b/renderdoc/driver/shaders/spirv/spirv_editor.cpp index 92d635bc9..f39431e5c 100644 --- a/renderdoc/driver/shaders/spirv/spirv_editor.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_editor.cpp @@ -32,48 +32,7 @@ static const uint32_t FirstRealWord = 5; -template <> -rdcstr DoStringise(const SPIRVId &el) -{ - return StringFormat::Fmt("%u", el.id); -} - -void SPIRVOperation::nopRemove(size_t idx, size_t count) -{ - RDCASSERT(idx >= 1); - size_t oldSize = size(); - - if(count == 0) - count = oldSize - idx; - - // reduce the size of this op - *iter = MakeHeader(iter.opcode(), oldSize - count); - - if(idx + count < oldSize) - { - // move any words on the end into the middle, then nop them - for(size_t i = 0; i < count; i++) - { - iter.word(idx + i) = iter.word(idx + count + i); - iter.word(oldSize - i - 1) = SPV_NOP; - } - } - else - { - for(size_t i = 0; i < count; i++) - { - iter.word(idx + i) = SPV_NOP; - } - } -} - -void SPIRVOperation::nopRemove() -{ - for(size_t i = 0, sz = size(); i < sz; i++) - iter.word(i) = SPV_NOP; -} - -SPIRVScalar::SPIRVScalar(SPIRVIterator it) +SPIRVScalar::SPIRVScalar(rdcspv::Iter it) { type = it.opcode(); @@ -88,47 +47,47 @@ SPIRVScalar::SPIRVScalar(SPIRVIterator it) signedness = false; } -SPIRVOperation SPIRVVector::decl(SPIRVEditor &editor) const +rdcspv::Operation SPIRVVector::decl(SPIRVEditor &editor) const { - return SPIRVOperation(spv::OpTypeVector, {0U, editor.DeclareType(scalar), count}); + return rdcspv::Operation(spv::OpTypeVector, {0U, editor.DeclareType(scalar), count}); } -SPIRVOperation SPIRVMatrix::decl(SPIRVEditor &editor) const +rdcspv::Operation SPIRVMatrix::decl(SPIRVEditor &editor) const { - return SPIRVOperation(spv::OpTypeMatrix, {0U, editor.DeclareType(vector), count}); + return rdcspv::Operation(spv::OpTypeMatrix, {0U, editor.DeclareType(vector), count}); } -SPIRVOperation SPIRVPointer::decl(SPIRVEditor &editor) const +rdcspv::Operation SPIRVPointer::decl(SPIRVEditor &editor) const { - return SPIRVOperation(spv::OpTypePointer, {0U, (uint32_t)storage, baseId}); + return rdcspv::Operation(spv::OpTypePointer, {0U, (uint32_t)storage, baseId}); } -SPIRVOperation SPIRVImage::decl(SPIRVEditor &editor) const +rdcspv::Operation SPIRVImage::decl(SPIRVEditor &editor) const { - return SPIRVOperation(spv::OpTypeImage, {0U, editor.DeclareType(retType), (uint32_t)dim, depth, - arrayed, ms, sampled, (uint32_t)format}); + return rdcspv::Operation(spv::OpTypeImage, {0U, editor.DeclareType(retType), (uint32_t)dim, depth, + arrayed, ms, sampled, (uint32_t)format}); } -SPIRVOperation SPIRVSampler::decl(SPIRVEditor &editor) const +rdcspv::Operation SPIRVSampler::decl(SPIRVEditor &editor) const { - return SPIRVOperation(spv::OpTypeSampler, {0U}); + return rdcspv::Operation(spv::OpTypeSampler, {0U}); } -SPIRVOperation SPIRVSampledImage::decl(SPIRVEditor &editor) const +rdcspv::Operation SPIRVSampledImage::decl(SPIRVEditor &editor) const { - return SPIRVOperation(spv::OpTypeSampledImage, {0U, baseId}); + return rdcspv::Operation(spv::OpTypeSampledImage, {0U, baseId}); } -SPIRVOperation SPIRVFunction::decl(SPIRVEditor &editor) const +rdcspv::Operation SPIRVFunction::decl(SPIRVEditor &editor) const { std::vector words; words.push_back(0U); words.push_back(returnId); - for(SPIRVId id : argumentIds) + for(rdcspv::Id id : argumentIds) words.push_back(id); - return SPIRVOperation(spv::OpTypeFunction, words); + return rdcspv::Operation(spv::OpTypeFunction, words); } SPIRVEditor::SPIRVEditor(std::vector &spirvWords) : spirv(spirvWords) @@ -172,9 +131,9 @@ SPIRVEditor::SPIRVEditor(std::vector &spirvWords) : spirv(spirvWords) #define START_SECTION(section) \ if(sections[section].startOffset == 0) \ - sections[section].startOffset = it.offset; + sections[section].startOffset = it.offs(); - for(SPIRVIterator it(spirv, FirstRealWord); it; it++) + for(rdcspv::Iter it(spirv, FirstRealWord); it; it++) { spv::Op opcode = it.opcode(); @@ -256,7 +215,7 @@ SPIRVEditor::SPIRVEditor(std::vector &spirvWords) : spirv(spirvWords) { if(sections[s].startOffset == sections[s].endOffset) { - spirv.insert(spirv.begin() + sections[s].startOffset, SPV_NOP); + spirv.insert(spirv.begin() + sections[s].startOffset, rdcspv::OpNopWord); sections[s].endOffset++; for(uint32_t t = s + 1; t < SPIRVSection::Count; t++) @@ -293,7 +252,7 @@ void SPIRVEditor::StripNops() { for(size_t i = FirstRealWord; i < spirv.size();) { - while(spirv[i] == SPV_NOP) + while(spirv[i] == rdcspv::OpNopWord) { spirv.erase(spirv.begin() + i); addWords(i, -1); @@ -311,7 +270,7 @@ void SPIRVEditor::StripNops() } } -SPIRVId SPIRVEditor::MakeId() +rdcspv::Id SPIRVEditor::MakeId() { uint32_t ret = spirv[3]; spirv[3]++; @@ -328,9 +287,9 @@ void SPIRVEditor::SetName(uint32_t id, const char *name) uintName.insert(uintName.begin(), id); - SPIRVOperation op(spv::OpName, uintName); + rdcspv::Operation op(spv::OpName, uintName); - SPIRVIterator it; + rdcspv::Iter it; // OpName must be before OpModuleProcessed. for(it = Begin(SPIRVSection::Debug); it < End(SPIRVSection::Debug); ++it) @@ -339,18 +298,17 @@ void SPIRVEditor::SetName(uint32_t id, const char *name) break; } - spirv.insert(spirv.begin() + it.offs(), op.begin(), op.end()); - RegisterOp(SPIRVIterator(spirv, it.offs())); + op.insertInto(spirv, it.offs()); + RegisterOp(rdcspv::Iter(spirv, it.offs())); addWords(it.offs(), op.size()); } -void SPIRVEditor::AddDecoration(const SPIRVOperation &op) +void SPIRVEditor::AddDecoration(const rdcspv::Operation &op) { - size_t offs = sections[SPIRVSection::Annotations].endOffset; - - spirv.insert(spirv.begin() + offs, op.begin(), op.end()); - RegisterOp(SPIRVIterator(spirv, offs)); - addWords(offs, op.size()); + size_t offset = sections[SPIRVSection::Annotations].endOffset; + op.insertInto(spirv, offset); + RegisterOp(rdcspv::Iter(spirv, offset)); + addWords(offset, op.size()); } void SPIRVEditor::AddCapability(spv::Capability cap) @@ -360,9 +318,9 @@ void SPIRVEditor::AddCapability(spv::Capability cap) return; // insert the operation at the very start - SPIRVOperation op(spv::OpCapability, {(uint32_t)cap}); - spirv.insert(spirv.begin() + FirstRealWord, op.begin(), op.end()); - RegisterOp(SPIRVIterator(spirv, FirstRealWord)); + rdcspv::Operation op(spv::OpCapability, {(uint32_t)cap}); + op.insertInto(spirv, FirstRealWord); + RegisterOp(rdcspv::Iter(spirv, FirstRealWord)); addWords(FirstRealWord, op.size()); } @@ -373,7 +331,7 @@ void SPIRVEditor::AddExtension(const std::string &extension) return; // start at the beginning - SPIRVIterator it(spirv, FirstRealWord); + rdcspv::Iter it(spirv, FirstRealWord); // skip past any capabilities while(it.opcode() == spv::OpCapability) @@ -384,13 +342,13 @@ void SPIRVEditor::AddExtension(const std::string &extension) std::vector uintName((sz / 4) + 1); memcpy(&uintName[0], extension.c_str(), sz); - SPIRVOperation op(spv::OpExtension, uintName); - spirv.insert(spirv.begin() + it.offset, op.begin(), op.end()); + rdcspv::Operation op(spv::OpExtension, uintName); + op.insertInto(spirv, it.offs()); RegisterOp(it); - addWords(it.offset, op.size()); + addWords(it.offs(), op.size()); } -void SPIRVEditor::AddExecutionMode(SPIRVId entry, spv::ExecutionMode mode, +void SPIRVEditor::AddExecutionMode(rdcspv::Id entry, spv::ExecutionMode mode, std::vector params) { size_t offset = sections[SPIRVSection::ExecutionMode].endOffset; @@ -398,21 +356,21 @@ void SPIRVEditor::AddExecutionMode(SPIRVId entry, spv::ExecutionMode mode, params.insert(params.begin(), (uint32_t)mode); params.insert(params.begin(), (uint32_t)entry); - SPIRVOperation op(spv::OpExecutionMode, params); - spirv.insert(spirv.begin() + offset, op.begin(), op.end()); - RegisterOp(SPIRVIterator(spirv, offset)); + rdcspv::Operation op(spv::OpExecutionMode, params); + op.insertInto(spirv, offset); + RegisterOp(rdcspv::Iter(spirv, offset)); addWords(offset, op.size()); } -SPIRVId SPIRVEditor::ImportExtInst(const char *setname) +rdcspv::Id SPIRVEditor::ImportExtInst(const char *setname) { - SPIRVId ret = extSets[setname]; + rdcspv::Id ret = extSets[setname]; if(ret) return ret; // start at the beginning - SPIRVIterator it(spirv, FirstRealWord); + rdcspv::Iter it(spirv, FirstRealWord); // skip past any capabilities and extensions while(it.opcode() == spv::OpCapability || it.opcode() == spv::OpExtension) @@ -427,76 +385,76 @@ SPIRVId SPIRVEditor::ImportExtInst(const char *setname) uintName.insert(uintName.begin(), ret); - SPIRVOperation op(spv::OpExtInstImport, uintName); - spirv.insert(spirv.begin() + it.offset, op.begin(), op.end()); + rdcspv::Operation op(spv::OpExtInstImport, uintName); + op.insertInto(spirv, it.offs()); RegisterOp(it); - addWords(it.offset, op.size()); + addWords(it.offs(), op.size()); extSets[setname] = ret; return ret; } -SPIRVId SPIRVEditor::AddType(const SPIRVOperation &op) +rdcspv::Id SPIRVEditor::AddType(const rdcspv::Operation &op) { size_t offset = sections[SPIRVSection::Types].endOffset; - SPIRVId id = op[1]; + rdcspv::Id id = op[1]; idOffsets[id] = offset; - spirv.insert(spirv.begin() + offset, op.begin(), op.end()); - RegisterOp(SPIRVIterator(spirv, offset)); + op.insertInto(spirv, offset); + RegisterOp(rdcspv::Iter(spirv, offset)); addWords(offset, op.size()); return id; } -SPIRVId SPIRVEditor::AddVariable(const SPIRVOperation &op) +rdcspv::Id SPIRVEditor::AddVariable(const rdcspv::Operation &op) { size_t offset = sections[SPIRVSection::Variables].endOffset; - SPIRVId id = op[2]; + rdcspv::Id id = op[2]; idOffsets[id] = offset; - spirv.insert(spirv.begin() + offset, op.begin(), op.end()); - RegisterOp(SPIRVIterator(spirv, offset)); + op.insertInto(spirv, offset); + RegisterOp(rdcspv::Iter(spirv, offset)); addWords(offset, op.size()); return id; } -SPIRVId SPIRVEditor::AddConstant(const SPIRVOperation &op) +rdcspv::Id SPIRVEditor::AddConstant(const rdcspv::Operation &op) { size_t offset = sections[SPIRVSection::Constants].endOffset; - SPIRVId id = op[2]; + rdcspv::Id id = op[2]; idOffsets[id] = offset; - spirv.insert(spirv.begin() + offset, op.begin(), op.end()); - RegisterOp(SPIRVIterator(spirv, offset)); + op.insertInto(spirv, offset); + RegisterOp(rdcspv::Iter(spirv, offset)); addWords(offset, op.size()); return id; } -void SPIRVEditor::AddFunction(const SPIRVOperation *ops, size_t count) +void SPIRVEditor::AddFunction(const rdcspv::Operation *ops, size_t count) { idOffsets[ops[0][2]] = spirv.size(); for(size_t i = 0; i < count; i++) - spirv.insert(spirv.end(), ops[i].begin(), ops[i].end()); + ops[i].appendTo(spirv); - RegisterOp(SPIRVIterator(spirv, idOffsets[ops[0][2]])); + RegisterOp(rdcspv::Iter(spirv, idOffsets[ops[0][2]])); } -SPIRVIterator SPIRVEditor::GetID(SPIRVId id) +rdcspv::Iter SPIRVEditor::GetID(rdcspv::Id id) { size_t offs = idOffsets[id]; if(offs) - return SPIRVIterator(spirv, offs); + return rdcspv::Iter(spirv, offs); - return SPIRVIterator(); + return rdcspv::Iter(); } -SPIRVIterator SPIRVEditor::GetEntry(SPIRVId id) +rdcspv::Iter SPIRVEditor::GetEntry(rdcspv::Id id) { - SPIRVIterator it(spirv, sections[SPIRVSection::EntryPoints].startOffset); - SPIRVIterator end(spirv, sections[SPIRVSection::EntryPoints].endOffset); + rdcspv::Iter it(spirv, sections[SPIRVSection::EntryPoints].startOffset); + rdcspv::Iter end(spirv, sections[SPIRVSection::EntryPoints].endOffset); while(it && it < end) { @@ -505,56 +463,30 @@ SPIRVIterator SPIRVEditor::GetEntry(SPIRVId id) it++; } - return SPIRVIterator(); + return rdcspv::Iter(); } -SPIRVId SPIRVEditor::DeclareStructType(std::vector members) +rdcspv::Id SPIRVEditor::DeclareStructType(std::vector members) { - SPIRVId typeId = MakeId(); + rdcspv::Id typeId = MakeId(); members.insert(members.begin(), typeId); - AddType(SPIRVOperation(spv::OpTypeStruct, members)); + AddType(rdcspv::Operation(spv::OpTypeStruct, members)); return typeId; } -void SPIRVEditor::AddWord(SPIRVIterator iter, uint32_t word) +void SPIRVEditor::AddOperation(rdcspv::Iter iter, const rdcspv::Operation &op) { if(!iter) return; - // if it's just pointing at a SPIRVOperation, we can just push_back immediately - if(iter.words != &spirv) - { - iter.words->push_back(word); - return; - } - - // add word - spirv.insert(spirv.begin() + iter.offset + iter.size(), word); - - // fix up header - iter.word(0) = SPIRVOperation::MakeHeader(iter.opcode(), iter.size() + 1); - - // update offsets - addWords(iter.offset + iter.size(), 1); -} - -void SPIRVEditor::AddOperation(SPIRVIterator iter, const SPIRVOperation &op) -{ - if(!iter) - return; - - // if it's just pointing at a SPIRVOperation, this is invalid - if(iter.words != &spirv) - return; - // add op - spirv.insert(spirv.begin() + iter.offset, op.begin(), op.end()); + op.insertInto(spirv, iter.offs()); // update offsets - addWords(iter.offset, op.size()); + addWords(iter.offs(), op.size()); } -void SPIRVEditor::RegisterOp(SPIRVIterator it) +void SPIRVEditor::RegisterOp(rdcspv::Iter it) { spv::Op opcode = it.opcode(); @@ -593,14 +525,14 @@ void SPIRVEditor::RegisterOp(SPIRVIterator it) } else if(opcode == spv::OpExtInstImport) { - SPIRVId id = it.word(1); + rdcspv::Id id = it.word(1); const char *name = (const char *)&it.word(2); extSets[name] = id; } else if(opcode == spv::OpFunction) { - SPIRVId id = it.word(2); - idOffsets[id] = it.offset; + rdcspv::Id id = it.word(2); + idOffsets[id] = it.offs(); functions.push_back(id); } @@ -637,18 +569,18 @@ void SPIRVEditor::RegisterOp(SPIRVIterator it) else if(opcode == spv::OpTypeVoid || opcode == spv::OpTypeBool || opcode == spv::OpTypeInt || opcode == spv::OpTypeFloat) { - SPIRVId id = it.word(1); - idOffsets[id] = it.offset; + rdcspv::Id id = it.word(1); + idOffsets[id] = it.offs(); SPIRVScalar scalar(it); scalarTypes[scalar] = id; } else if(opcode == spv::OpTypeVector) { - SPIRVId id = it.word(1); - idOffsets[id] = it.offset; + rdcspv::Id id = it.word(1); + idOffsets[id] = it.offs(); - SPIRVIterator scalarIt = GetID(it.word(2)); + rdcspv::Iter scalarIt = GetID(it.word(2)); if(!scalarIt) { @@ -660,10 +592,10 @@ void SPIRVEditor::RegisterOp(SPIRVIterator it) } else if(opcode == spv::OpTypeMatrix) { - SPIRVId id = it.word(1); - idOffsets[id] = it.offset; + rdcspv::Id id = it.word(1); + idOffsets[id] = it.offs(); - SPIRVIterator vectorIt = GetID(it.word(2)); + rdcspv::Iter vectorIt = GetID(it.word(2)); if(!vectorIt) { @@ -671,17 +603,17 @@ void SPIRVEditor::RegisterOp(SPIRVIterator it) return; } - SPIRVIterator scalarIt = GetID(vectorIt.word(2)); + rdcspv::Iter scalarIt = GetID(vectorIt.word(2)); uint32_t vectorDim = vectorIt.word(3); matrixTypes[SPIRVMatrix(SPIRVVector(scalarIt, vectorDim), it.word(3))] = id; } else if(opcode == spv::OpTypeImage) { - SPIRVId id = it.word(1); - idOffsets[id] = it.offset; + rdcspv::Id id = it.word(1); + idOffsets[id] = it.offs(); - SPIRVIterator scalarIt = GetID(it.word(2)); + rdcspv::Iter scalarIt = GetID(it.word(2)); if(!scalarIt) { @@ -694,40 +626,40 @@ void SPIRVEditor::RegisterOp(SPIRVIterator it) } else if(opcode == spv::OpTypeSampler) { - SPIRVId id = it.word(1); - idOffsets[id] = it.offset; + rdcspv::Id id = it.word(1); + idOffsets[id] = it.offs(); samplerTypes[SPIRVSampler()] = id; } else if(opcode == spv::OpTypeSampledImage) { - SPIRVId id = it.word(1); - idOffsets[id] = it.offset; + rdcspv::Id id = it.word(1); + idOffsets[id] = it.offs(); - SPIRVId base = it.word(2); + rdcspv::Id base = it.word(2); sampledImageTypes[SPIRVSampledImage(base)] = id; } else if(opcode == spv::OpTypePointer) { - SPIRVId id = it.word(1); - idOffsets[id] = it.offset; + rdcspv::Id id = it.word(1); + idOffsets[id] = it.offs(); pointerTypes[SPIRVPointer(it.word(3), (spv::StorageClass)it.word(2))] = id; } else if(opcode == spv::OpTypeStruct) { - SPIRVId id = it.word(1); - idOffsets[id] = it.offset; + rdcspv::Id id = it.word(1); + idOffsets[id] = it.offs(); structTypes.insert(id); } else if(opcode == spv::OpTypeFunction) { - SPIRVId id = it.word(1); - idOffsets[id] = it.offset; + rdcspv::Id id = it.word(1); + idOffsets[id] = it.offs(); - std::vector args; + std::vector args; for(size_t i = 3; i < it.size(); i++) args.push_back(it.word(i)); @@ -736,7 +668,7 @@ void SPIRVEditor::RegisterOp(SPIRVIterator it) } } -void SPIRVEditor::UnregisterOp(SPIRVIterator it) +void SPIRVEditor::UnregisterOp(rdcspv::Iter it) { spv::Op opcode = it.opcode(); @@ -748,7 +680,7 @@ void SPIRVEditor::UnregisterOp(SPIRVIterator it) idTypes[it.word(2)] = 0; } - SPIRVId id; + rdcspv::Id id; if(opcode == spv::OpEntryPoint) { @@ -831,7 +763,7 @@ void SPIRVEditor::UnregisterOp(SPIRVIterator it) { id = it.word(1); - SPIRVIterator scalarIt = GetID(it.word(2)); + rdcspv::Iter scalarIt = GetID(it.word(2)); if(!scalarIt) { @@ -845,7 +777,7 @@ void SPIRVEditor::UnregisterOp(SPIRVIterator it) { id = it.word(1); - SPIRVIterator vectorIt = GetID(it.word(2)); + rdcspv::Iter vectorIt = GetID(it.word(2)); if(!vectorIt) { @@ -853,7 +785,7 @@ void SPIRVEditor::UnregisterOp(SPIRVIterator it) return; } - SPIRVIterator scalarIt = GetID(vectorIt.word(2)); + rdcspv::Iter scalarIt = GetID(vectorIt.word(2)); uint32_t vectorDim = vectorIt.word(3); matrixTypes.erase(SPIRVMatrix(SPIRVVector(scalarIt, vectorDim), it.word(3))); @@ -862,7 +794,7 @@ void SPIRVEditor::UnregisterOp(SPIRVIterator it) { id = it.word(1); - SPIRVIterator scalarIt = GetID(it.word(2)); + rdcspv::Iter scalarIt = GetID(it.word(2)); if(!scalarIt) { @@ -883,7 +815,7 @@ void SPIRVEditor::UnregisterOp(SPIRVIterator it) { id = it.word(1); - SPIRVId base = it.word(2); + rdcspv::Id base = it.word(2); sampledImageTypes.erase(SPIRVSampledImage(base)); } @@ -903,7 +835,7 @@ void SPIRVEditor::UnregisterOp(SPIRVIterator it) { id = it.word(1); - std::vector args; + std::vector args; for(size_t i = 3; i < it.size(); i++) args.push_back(it.word(i)); @@ -956,16 +888,16 @@ void SPIRVEditor::addWords(size_t offs, int32_t num) o += num; } -#define TYPETABLE(StructType, variable) \ - template <> \ - std::map &SPIRVEditor::GetTable() \ - { \ - return variable; \ - } \ - template <> \ - const std::map &SPIRVEditor::GetTable() const \ - { \ - return variable; \ +#define TYPETABLE(StructType, variable) \ + template <> \ + std::map &SPIRVEditor::GetTable() \ + { \ + return variable; \ + } \ + template <> \ + const std::map &SPIRVEditor::GetTable() const \ + { \ + return variable; \ } TYPETABLE(SPIRVScalar, scalarTypes); @@ -989,7 +921,7 @@ static void RemoveSection(std::vector &spirv, size_t offsets[SPIRVSect { SPIRVEditor ed(spirv); - for(SPIRVIterator it = ed.Begin(section), end = ed.End(section); it < end; it++) + for(rdcspv::Iter it = ed.Begin(section), end = ed.End(section); it < end; it++) ed.Remove(it); size_t oldLength = offsets[section][1] - offsets[section][0]; @@ -1020,7 +952,7 @@ static void CheckSPIRV(SPIRVEditor &ed, size_t offsets[SPIRVSection::Count][2]) // should only be one entry point REQUIRE(ed.GetEntries().size() == 1); - SPIRVId entryId = ed.GetEntries()[0].id; + rdcspv::Id entryId = ed.GetEntries()[0].id; // check that the iterator places us precisely at the start of the functions section CHECK(ed.GetID(entryId).offs() == ed.Begin(SPIRVSection::Functions).offs()); diff --git a/renderdoc/driver/shaders/spirv/spirv_editor.h b/renderdoc/driver/shaders/spirv/spirv_editor.h index 50fdbad81..d4845b2c4 100644 --- a/renderdoc/driver/shaders/spirv/spirv_editor.h +++ b/renderdoc/driver/shaders/spirv/spirv_editor.h @@ -29,151 +29,24 @@ #include #include #include -#include "3rdparty/glslang/SPIRV/spirv.hpp" #include "api/replay/renderdoc_replay.h" #include "common/common.h" +#include "spirv_common.h" -class SPIRVOperation; class SPIRVEditor; -struct SPIRVId -{ - constexpr inline SPIRVId() : id(0) {} - constexpr inline SPIRVId(uint32_t i) : id(i) {} - inline operator uint32_t() const { return id; } - constexpr inline bool operator==(const SPIRVId o) const { return id == o.id; } - constexpr inline bool operator!=(const SPIRVId o) const { return id != o.id; } - constexpr inline bool operator<(const SPIRVId o) const { return id < o.id; } - constexpr inline bool operator==(const uint32_t o) const { return id == o; } - constexpr inline bool operator!=(const uint32_t o) const { return id != o; } - constexpr inline bool operator<(const uint32_t o) const { return id < o; } - uint32_t id; -}; - -DECLARE_STRINGISE_TYPE(SPIRVId); - -// length of 1 word in the top 16-bits, OpNop = 0 in the lower 16-bits -#define SPV_NOP (0x00010000) - -class SPIRVIterator -{ -public: - // constructors - SPIRVIterator() = default; - SPIRVIterator(std::vector &w, size_t o) : words(&w), offset(o) {} - // increment to the next op - SPIRVIterator operator++(int) - { - SPIRVIterator ret = *this; - operator++(); - return ret; - } - SPIRVIterator operator++() - { - do - { - offset += cur() >> spv::WordCountShift; - // silently skip nops - } while(*this && opcode() == spv::OpNop); - - return *this; - } - bool operator==(const SPIRVIterator &it) const = delete; - bool operator!=(const SPIRVIterator &it) const = delete; - bool operator<(const SPIRVIterator &it) const { return words == it.words && offset < it.offset; } - // utility functions - explicit operator bool() const { return words != NULL && offset < words->size(); } - uint32_t &operator*() { return cur(); } - const uint32_t &operator*() const { return cur(); } - spv::Op opcode() { return spv::Op(cur() & spv::OpCodeMask); } - uint32_t &word(size_t idx) { return words->at(offset + idx); } - const uint32_t &word(size_t idx) const { return words->at(offset + idx); } - size_t offs() const { return offset; } - size_t size() const { return cur() >> spv::WordCountShift; } -private: - inline uint32_t &cur() { return words->at(offset); } - inline const uint32_t &cur() const { return words->at(offset); } - // we add some friend classes to poke directly into words when it wants to edit - friend class SPIRVOperation; - friend class SPIRVEditor; - std::vector::iterator it() { return words->begin() + offset; } - std::vector::const_iterator it() const { return words->cbegin() + offset; } - size_t offset = 0; - std::vector *words = NULL; -}; - -class SPIRVOperation -{ -public: - // constructor of a synthetic operation, from an operation & subsequent words, calculates the - // length then constructs the first word with opcode + length. - SPIRVOperation(spv::Op op, const std::vector &data) - { - words.push_back(MakeHeader(op, data.size() + 1)); - words.insert(words.begin() + 1, data.begin(), data.end()); - - iter = SPIRVIterator(words, 0); - } - - SPIRVOperation(const SPIRVOperation &op) - { - words = op.words; - - iter = SPIRVIterator(words, 0); - } - - static SPIRVOperation copy(SPIRVIterator it) - { - SPIRVOperation ret(it); - - ret.words.insert(ret.words.begin(), it.it(), it.it() + it.size()); - ret.iter = SPIRVIterator(ret.words, 0); - - return ret; - } - - // constructor that takes existing words from elsewhere and just references it. - // Since this is iterator based, normal iteration invalidation rules apply, if you modify earlier - // in the SPIR-V this operation will become invalid. - SPIRVOperation(SPIRVIterator it) : iter(it) {} - uint32_t &operator[](size_t idx) { return iter.word(idx); } - const uint32_t &operator[](size_t idx) const { return iter.word(idx); } - size_t size() const { return iter.size(); } - // replace part of this operation with NOPs and update the length. Cannot completely erase the - // operation - void nopRemove(size_t idx, size_t count = 0); - -private: - friend class SPIRVEditor; - - std::vector::const_iterator begin() const { return iter.it(); } - std::vector::const_iterator end() const { return iter.it() + size(); } - inline static uint32_t MakeHeader(spv::Op op, size_t WordCount) - { - return (uint32_t(op) & spv::OpCodeMask) | (uint16_t(WordCount) << spv::WordCountShift); - } - void nopRemove(); - - // everything is based around this iterator, which may point into our local storage or to external - // storage. - SPIRVIterator iter; - - // may not be used, if we refer to an external iterator - std::vector words; -}; - struct SPIRVEntry { - SPIRVId id; + rdcspv::Id id; std::string name; }; struct SPIRVVariable { - SPIRVId id; - SPIRVId type; + rdcspv::Id id; + rdcspv::Id type; spv::StorageClass storageClass; - SPIRVId init; + rdcspv::Id init; bool operator<(const SPIRVVariable &o) const { @@ -195,7 +68,7 @@ struct SPIRVVariable struct SPIRVDecoration { - SPIRVId id; + rdcspv::Id id; spv::Decoration dec = spv::DecorationMax; uint32_t parameters[4] = {}; @@ -242,7 +115,7 @@ struct SPIRVScalar { SPIRVScalar() : type(spv::OpMax), width(0), signedness(false) {} constexpr SPIRVScalar(spv::Op t, uint32_t w, bool s) : type(t), width(w), signedness(s) {} - SPIRVScalar(SPIRVIterator op); + SPIRVScalar(rdcspv::Iter op); spv::Op type; uint32_t width; @@ -263,18 +136,18 @@ struct SPIRVScalar return type == o.type && width == o.width && signedness == o.signedness; } - SPIRVOperation decl(SPIRVEditor &editor) const + rdcspv::Operation decl(SPIRVEditor &editor) const { if(type == spv::OpTypeVoid) - return SPIRVOperation(type, {0}); + return rdcspv::Operation(type, {0}); else if(type == spv::OpTypeBool) - return SPIRVOperation(type, {0}); + return rdcspv::Operation(type, {0}); else if(type == spv::OpTypeFloat) - return SPIRVOperation(type, {0, width}); + return rdcspv::Operation(type, {0, width}); else if(type == spv::OpTypeInt) - return SPIRVOperation(type, {0, width, signedness ? 1U : 0U}); + return rdcspv::Operation(type, {0, width, signedness ? 1U : 0U}); else - return SPIRVOperation(spv::OpNop, {0}); + return rdcspv::Operation(spv::OpNop, {0}); } }; @@ -317,7 +190,7 @@ struct SPIRVVector bool operator!=(const SPIRVVector &o) const { return !operator==(o); } bool operator==(const SPIRVVector &o) const { return scalar == o.scalar && count == o.count; } - SPIRVOperation decl(SPIRVEditor &editor) const; + rdcspv::Operation decl(SPIRVEditor &editor) const; }; struct SPIRVMatrix @@ -335,13 +208,13 @@ struct SPIRVMatrix bool operator!=(const SPIRVMatrix &o) const { return !operator==(o); } bool operator==(const SPIRVMatrix &o) const { return vector == o.vector && count == o.count; } - SPIRVOperation decl(SPIRVEditor &editor) const; + rdcspv::Operation decl(SPIRVEditor &editor) const; }; struct SPIRVPointer { - SPIRVPointer(SPIRVId b, spv::StorageClass s) : baseId(b), storage(s) {} - SPIRVId baseId; + SPIRVPointer(rdcspv::Id b, spv::StorageClass s) : baseId(b), storage(s) {} + rdcspv::Id baseId; spv::StorageClass storage; bool operator<(const SPIRVPointer &o) const @@ -356,7 +229,7 @@ struct SPIRVPointer { return baseId == o.baseId && storage == o.storage; } - SPIRVOperation decl(SPIRVEditor &editor) const; + rdcspv::Operation decl(SPIRVEditor &editor) const; }; struct SPIRVImage @@ -397,7 +270,7 @@ struct SPIRVImage return retType == o.retType && dim == o.dim && depth == o.depth && arrayed == o.arrayed && ms == o.ms && sampled == o.sampled && format == o.format; } - SPIRVOperation decl(SPIRVEditor &editor) const; + rdcspv::Operation decl(SPIRVEditor &editor) const; }; struct SPIRVSampler @@ -406,25 +279,28 @@ struct SPIRVSampler bool operator<(const SPIRVSampler &o) const { return false; } bool operator!=(const SPIRVSampler &o) const { return false; } bool operator==(const SPIRVSampler &o) const { return true; } - SPIRVOperation decl(SPIRVEditor &editor) const; + rdcspv::Operation decl(SPIRVEditor &editor) const; }; struct SPIRVSampledImage { - SPIRVSampledImage(SPIRVId b) : baseId(b) {} - SPIRVId baseId; + SPIRVSampledImage(rdcspv::Id b) : baseId(b) {} + rdcspv::Id baseId; bool operator<(const SPIRVSampledImage &o) const { return baseId < o.baseId; } bool operator!=(const SPIRVSampledImage &o) const { return !operator==(o); } bool operator==(const SPIRVSampledImage &o) const { return baseId == o.baseId; } - SPIRVOperation decl(SPIRVEditor &editor) const; + rdcspv::Operation decl(SPIRVEditor &editor) const; }; struct SPIRVFunction { - SPIRVFunction(SPIRVId ret, const std::vector &args) : returnId(ret), argumentIds(args) {} - SPIRVId returnId; - std::vector argumentIds; + SPIRVFunction(rdcspv::Id ret, const std::vector &args) + : returnId(ret), argumentIds(args) + { + } + rdcspv::Id returnId; + std::vector argumentIds; bool operator<(const SPIRVFunction &o) const { @@ -438,11 +314,11 @@ struct SPIRVFunction { return returnId == o.returnId && argumentIds == o.argumentIds; } - SPIRVOperation decl(SPIRVEditor &editor) const; + rdcspv::Operation decl(SPIRVEditor &editor) const; }; template -using SPIRVTypeId = std::pair; +using SPIRVTypeId = std::pair; template using SPIRVTypeIds = std::vector>; @@ -478,85 +354,84 @@ public: ~SPIRVEditor() { StripNops(); } void StripNops(); - SPIRVId MakeId(); + rdcspv::Id MakeId(); - void AddWord(SPIRVIterator iter, uint32_t word); - void AddOperation(SPIRVIterator iter, const SPIRVOperation &op); + void AddOperation(rdcspv::Iter iter, const rdcspv::Operation &op); // callbacks to allow us to update our internal structures over changes // called before any modifications are made. Removes the operation from internal structures. - void PreModify(SPIRVIterator iter) { UnregisterOp(iter); } + void PreModify(rdcspv::Iter iter) { UnregisterOp(iter); } // called after any modifications, re-adds the operation to internal structures with its new // properties - void PostModify(SPIRVIterator iter) { RegisterOp(iter); } + void PostModify(rdcspv::Iter iter) { RegisterOp(iter); } // removed an operation and replaces it with nops - void Remove(SPIRVIterator iter) + void Remove(rdcspv::Iter iter) { UnregisterOp(iter); - SPIRVOperation(iter).nopRemove(); + iter.nopRemove(); } void SetName(uint32_t id, const char *name); - void AddDecoration(const SPIRVOperation &op); + void AddDecoration(const rdcspv::Operation &op); void AddCapability(spv::Capability cap); void AddExtension(const std::string &extension); - void AddExecutionMode(SPIRVId entry, spv::ExecutionMode mode, std::vector params = {}); - SPIRVId ImportExtInst(const char *setname); - SPIRVId AddType(const SPIRVOperation &op); - SPIRVId AddVariable(const SPIRVOperation &op); - SPIRVId AddConstant(const SPIRVOperation &op); - void AddFunction(const SPIRVOperation *ops, size_t count); + void AddExecutionMode(rdcspv::Id entry, spv::ExecutionMode mode, std::vector params = {}); + rdcspv::Id ImportExtInst(const char *setname); + rdcspv::Id AddType(const rdcspv::Operation &op); + rdcspv::Id AddVariable(const rdcspv::Operation &op); + rdcspv::Id AddConstant(const rdcspv::Operation &op); + void AddFunction(const rdcspv::Operation *ops, size_t count); - SPIRVIterator GetID(SPIRVId id); + rdcspv::Iter GetID(rdcspv::Id id); // the entry point has 'two' opcodes, the entrypoint declaration and the function. // This returns the first, GetID returns the second. - SPIRVIterator GetEntry(SPIRVId id); - SPIRVIterator Begin(SPIRVSection::Type section) + rdcspv::Iter GetEntry(rdcspv::Id id); + rdcspv::Iter Begin(SPIRVSection::Type section) { - return SPIRVIterator(spirv, sections[section].startOffset); + return rdcspv::Iter(spirv, sections[section].startOffset); } - SPIRVIterator End(SPIRVSection::Type section) + rdcspv::Iter End(SPIRVSection::Type section) { - return SPIRVIterator(spirv, sections[section].endOffset); + return rdcspv::Iter(spirv, sections[section].endOffset); } // fetches the id of this type. If it exists already the old ID will be returned, otherwise it // will be declared and the new ID returned template - SPIRVId DeclareType(const SPIRVType &t) + rdcspv::Id DeclareType(const SPIRVType &t) { - std::map &table = GetTable(); + std::map &table = GetTable(); auto it = table.lower_bound(t); if(it != table.end() && it->first == t) return it->second; - SPIRVOperation decl = t.decl(*this); - SPIRVId id = decl[1] = MakeId(); + rdcspv::Operation decl = t.decl(*this); + rdcspv::Id id = decl[1] = MakeId(); AddType(decl); - table.insert(it, std::pair(t, id)); + table.insert(it, std::pair(t, id)); return id; } template - SPIRVId GetType(const SPIRVType &t) + rdcspv::Id GetType(const SPIRVType &t) { - std::map &table = GetTable(); + std::map &table = GetTable(); auto it = table.find(t); if(it != table.end()) return it->second; - return SPIRVId(); + return rdcspv::Id(); } template SPIRVTypeIds GetTypes() { - std::map &table = GetTable(); + std::map &table = GetTable(); SPIRVTypeIds ret; @@ -567,33 +442,33 @@ public: } template - const std::map &GetTypeInfo() const + const std::map &GetTypeInfo() const { return GetTable(); } - SPIRVBinding GetBinding(SPIRVId id) const + SPIRVBinding GetBinding(rdcspv::Id id) const { auto it = bindings.find(id); if(it == bindings.end()) return SPIRVBinding(); return it->second; } - const std::set &GetStructTypes() const { return structTypes; } - SPIRVId DeclareStructType(std::vector members); + const std::set &GetStructTypes() const { return structTypes; } + rdcspv::Id DeclareStructType(std::vector members); // helper for AddConstant template - SPIRVId AddConstantImmediate(T t) + rdcspv::Id AddConstantImmediate(T t) { - SPIRVId typeId = DeclareType(scalar()); + rdcspv::Id typeId = DeclareType(scalar()); std::vector words = {typeId, MakeId()}; words.insert(words.end(), sizeof(T) / 4, 0U); memcpy(&words[2], &t, sizeof(T)); - return AddConstant(SPIRVOperation(spv::OpConstant, words)); + return AddConstant(rdcspv::Operation(spv::OpConstant, words)); } // simple properties that are public. @@ -609,14 +484,14 @@ public: // accessors to structs/vectors of data const std::vector &GetEntries() { return entries; } const std::vector &GetVariables() { return variables; } - const std::vector &GetFunctions() { return functions; } - SPIRVId GetIDType(SPIRVId id) { return idTypes[id]; } + const std::vector &GetFunctions() { return functions; } + rdcspv::Id GetIDType(rdcspv::Id id) { return idTypes[id]; } private: inline void addWords(size_t offs, size_t num) { addWords(offs, (int32_t)num); } void addWords(size_t offs, int32_t num); - void RegisterOp(SPIRVIterator iter); - void UnregisterOp(SPIRVIterator iter); + void RegisterOp(rdcspv::Iter iter); + void UnregisterOp(rdcspv::Iter iter); struct LogicalSection { @@ -631,35 +506,35 @@ private: std::vector decorations; - std::map bindings; + std::map bindings; std::vector idOffsets; - std::vector idTypes; + std::vector idTypes; std::vector entries; std::vector variables; - std::vector functions; + std::vector functions; std::set extensions; std::set capabilities; - std::map extSets; + std::map extSets; - std::map scalarTypes; - std::map vectorTypes; - std::map matrixTypes; - std::map pointerTypes; - std::map imageTypes; - std::map samplerTypes; - std::map sampledImageTypes; - std::map functionTypes; + std::map scalarTypes; + std::map vectorTypes; + std::map matrixTypes; + std::map pointerTypes; + std::map imageTypes; + std::map samplerTypes; + std::map sampledImageTypes; + std::map functionTypes; - std::set structTypes; + std::set structTypes; template - std::map &GetTable(); + std::map &GetTable(); template - const std::map &GetTable() const; + const std::map &GetTable() const; std::vector &spirv; }; \ No newline at end of file diff --git a/renderdoc/driver/vulkan/vk_bindless_feedback.cpp b/renderdoc/driver/vulkan/vk_bindless_feedback.cpp index b37c853c0..255b84992 100644 --- a/renderdoc/driver/vulkan/vk_bindless_feedback.cpp +++ b/renderdoc/driver/vulkan/vk_bindless_feedback.cpp @@ -44,11 +44,11 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, const bool useBufferAddress = (addr != 0); - SPIRVId uint32ID = editor.DeclareType(scalar()); - SPIRVId int32ID = editor.DeclareType(scalar()); - SPIRVId uint64ID, int64ID; - SPIRVId uint32StructID; - SPIRVId funcParamType; + rdcspv::Id uint32ID = editor.DeclareType(scalar()); + rdcspv::Id int32ID = editor.DeclareType(scalar()); + rdcspv::Id uint64ID, int64ID; + rdcspv::Id uint32StructID; + rdcspv::Id funcParamType; if(useBufferAddress) { @@ -56,21 +56,22 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, uint64ID = editor.DeclareType(scalar()); int64ID = editor.DeclareType(scalar()); - uint32StructID = editor.AddType(SPIRVOperation(spv::OpTypeStruct, {editor.MakeId(), uint32ID})); + uint32StructID = + editor.AddType(rdcspv::Operation(spv::OpTypeStruct, {editor.MakeId(), uint32ID})); // any function parameters we add are uint64 byte offsets funcParamType = uint64ID; } else { - SPIRVId runtimeArrayID = - editor.AddType(SPIRVOperation(spv::OpTypeRuntimeArray, {editor.MakeId(), uint32ID})); + rdcspv::Id runtimeArrayID = + editor.AddType(rdcspv::Operation(spv::OpTypeRuntimeArray, {editor.MakeId(), uint32ID})); - editor.AddDecoration(SPIRVOperation( + editor.AddDecoration(rdcspv::Operation( spv::OpDecorate, {runtimeArrayID, spv::DecorationArrayStride, sizeof(uint32_t)})); uint32StructID = - editor.AddType(SPIRVOperation(spv::OpTypeStruct, {editor.MakeId(), runtimeArrayID})); + editor.AddType(rdcspv::Operation(spv::OpTypeStruct, {editor.MakeId(), runtimeArrayID})); // any function parameters we add are uint32 indices funcParamType = uint32ID; @@ -79,11 +80,11 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, editor.SetName(uint32StructID, "__rd_feedbackStruct"); editor.AddDecoration( - SPIRVOperation(spv::OpMemberDecorate, {uint32StructID, 0, spv::DecorationOffset, 0})); + rdcspv::Operation(spv::OpMemberDecorate, {uint32StructID, 0, spv::DecorationOffset, 0})); // map from variable ID to watch, to variable ID to get offset from (as a SPIR-V constant, // or as either uint64 byte offset for buffer addressing or uint32 ssbo index otherwise) - std::map varLookup; + std::map varLookup; // iterate over all variables. We do this here because in the absence of the buffer address // extension we might declare our own below and patch bindings - so we need to look these up now @@ -105,7 +106,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // store the offset for this variable so we watch for access chains and know where to store to if(useBufferAddress) { - SPIRVId id = varLookup[var.id] = editor.AddConstantImmediate(it->second.offset); + rdcspv::Id id = varLookup[var.id] = editor.AddConstantImmediate(it->second.offset); editor.SetName( id, StringFormat::Fmt("__feedbackOffset_set%u_bind%u", it->first.set, it->first.binding) @@ -116,7 +117,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // check that the offset fits in 32-bit word, convert byte offset to uint32 index uint64_t index = it->second.offset / 4; RDCASSERT(index < 0xFFFFFFFFULL, bind.set, bind.binding, it->second.offset); - SPIRVId id = varLookup[var.id] = editor.AddConstantImmediate(uint32_t(index)); + rdcspv::Id id = varLookup[var.id] = editor.AddConstantImmediate(uint32_t(index)); editor.SetName( id, StringFormat::Fmt("__feedbackIndex_set%u_bind%u", it->first.set, it->first.binding) @@ -125,7 +126,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, } } - SPIRVId bufferAddressConst, ssboVar, uint32ptrtype; + rdcspv::Id bufferAddressConst, ssboVar, uint32ptrtype; if(useBufferAddress) { @@ -133,7 +134,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, editor.AddExtension("SPV_EXT_physical_storage_buffer"); // change the memory model to physical storage buffer 64 - SPIRVOperation op(editor.Begin(SPIRVSection::MemoryModel)); + rdcspv::Operation op(editor.Begin(SPIRVSection::MemoryModel)); op[1] = spv::AddressingModelPhysicalStorageBuffer64EXT; // add capabilities @@ -148,17 +149,18 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, editor.SetName(bufferAddressConst, "__rd_feedbackAddress"); // struct is block decorated - editor.AddDecoration(SPIRVOperation(spv::OpDecorate, {uint32StructID, spv::DecorationBlock})); + editor.AddDecoration(rdcspv::Operation(spv::OpDecorate, {uint32StructID, spv::DecorationBlock})); } else { // the pointers are uniform pointers - SPIRVId bufptrtype = editor.DeclareType(SPIRVPointer(uint32StructID, spv::StorageClassUniform)); + rdcspv::Id bufptrtype = + editor.DeclareType(SPIRVPointer(uint32StructID, spv::StorageClassUniform)); uint32ptrtype = editor.DeclareType(SPIRVPointer(uint32ID, spv::StorageClassUniform)); // patch all bindings up by 1 - for(SPIRVIterator it = editor.Begin(SPIRVSection::Annotations), - end = editor.End(SPIRVSection::Annotations); + for(rdcspv::Iter it = editor.Begin(SPIRVSection::Annotations), + end = editor.End(SPIRVSection::Annotations); it < end; ++it) { // we will use descriptor set 0 for our own purposes if we don't have a buffer address. @@ -178,32 +180,32 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // add our SSBO variable, at set 0 binding 0 ssboVar = editor.MakeId(); editor.AddVariable( - SPIRVOperation(spv::OpVariable, {bufptrtype, ssboVar, spv::StorageClassUniform})); + rdcspv::Operation(spv::OpVariable, {bufptrtype, ssboVar, spv::StorageClassUniform})); editor.AddDecoration( - SPIRVOperation(spv::OpDecorate, {ssboVar, (uint32_t)spv::DecorationDescriptorSet, 0})); + rdcspv::Operation(spv::OpDecorate, {ssboVar, (uint32_t)spv::DecorationDescriptorSet, 0})); editor.AddDecoration( - SPIRVOperation(spv::OpDecorate, {ssboVar, (uint32_t)spv::DecorationBinding, 0})); + rdcspv::Operation(spv::OpDecorate, {ssboVar, (uint32_t)spv::DecorationBinding, 0})); editor.SetName(ssboVar, "__rd_feedbackBuffer"); // struct is bufferblock decorated editor.AddDecoration( - SPIRVOperation(spv::OpDecorate, {uint32StructID, (uint32_t)spv::DecorationBufferBlock})); + rdcspv::Operation(spv::OpDecorate, {uint32StructID, (uint32_t)spv::DecorationBufferBlock})); } - SPIRVId rtarrayOffset = editor.AddConstantImmediate(0U); - SPIRVId usedValue = editor.AddConstantImmediate(0xFFFFFFFFU); - SPIRVId scope = editor.AddConstantImmediate(spv::ScopeInvocation); - SPIRVId semantics = editor.AddConstantImmediate(0U); - SPIRVId uint32shift = editor.AddConstantImmediate(2U); + rdcspv::Id rtarrayOffset = editor.AddConstantImmediate(0U); + rdcspv::Id usedValue = editor.AddConstantImmediate(0xFFFFFFFFU); + rdcspv::Id scope = editor.AddConstantImmediate(spv::ScopeInvocation); + rdcspv::Id semantics = editor.AddConstantImmediate(0U); + rdcspv::Id uint32shift = editor.AddConstantImmediate(2U); - std::map intTypeLookup; + std::map intTypeLookup; for(auto scalarType : editor.GetTypeInfo()) if(scalarType.first.type == spv::OpTypeInt) intTypeLookup[scalarType.second] = scalarType.first; - SPIRVId entryID; + rdcspv::Id entryID; for(const SPIRVEntry &entry : editor.GetEntries()) { if(entry.name == entryName) @@ -216,11 +218,11 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, SPIRVTypeIds funcTypes = editor.GetTypes(); // functions that have been patched with annotation & extra function parameters if needed - std::set patchedFunctions; + std::set patchedFunctions; // functions we need to patch, with the indices of which parameters have bindings coming along // with - std::map> functionPatchQueue; + std::map> functionPatchQueue; // start with the entry point, with no parameters to patch functionPatchQueue[entryID] = {}; @@ -228,7 +230,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // now keep patching functions until we have no more to patch while(!functionPatchQueue.empty()) { - SPIRVId funcId; + rdcspv::Id funcId; std::vector patchArgIndices; { @@ -240,7 +242,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, patchedFunctions.insert(funcId); } - SPIRVIterator it = editor.GetID(funcId); + rdcspv::Iter it = editor.GetID(funcId); RDCASSERT(it.opcode() == spv::OpFunction); @@ -255,7 +257,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, for(size_t i = 0; i < patchArgIndices.size(); i++) patchedFuncType.argumentIds.push_back(funcParamType); - SPIRVId newFuncTypeID = editor.DeclareType(patchedFuncType); + rdcspv::Id newFuncTypeID = editor.DeclareType(patchedFuncType); // re-fetch the iterator as it might have moved with the type declaration it = editor.GetID(funcId); @@ -271,7 +273,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, ++it; // onto the OpFunctionParameters. First allocate IDs for all our new function parameters - std::vector patchedParamIDs; + std::vector patchedParamIDs; for(size_t i = 0; i < patchArgIndices.size(); i++) patchedParamIDs.push_back(editor.MakeId()); @@ -296,7 +298,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, for(size_t i = 0; i < patchedParamIDs.size(); i++) { editor.AddOperation( - it, SPIRVOperation(spv::OpFunctionParameter, {funcParamType, patchedParamIDs[i]})); + it, rdcspv::Operation(spv::OpFunctionParameter, {funcParamType, patchedParamIDs[i]})); ++it; } @@ -310,7 +312,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // if we see an OpCopyObject, just add it to the map pointing to the same value if(it.opcode() == spv::OpCopyObject) { - SPIRVId sourcevar = it.word(3); + rdcspv::Id sourcevar = it.word(3); // is this a var we want to snoop? auto varIt = varLookup.find(sourcevar); @@ -347,11 +349,11 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, for(size_t i = 1; i < it.size(); i++) funccall.insert(funccall.begin() + i - 1, it.word(i)); - SPIRVIterator oldCall = it; + rdcspv::Iter oldCall = it; // add our patched call afterwards it++; - editor.AddOperation(it, SPIRVOperation(spv::OpFunctionCall, funccall)); + editor.AddOperation(it, rdcspv::Operation(spv::OpFunctionCall, funccall)); // remove the old call editor.Remove(oldCall); @@ -366,7 +368,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // if we see an access chain of a variable we're snooping, save out the result if(it.opcode() == spv::OpAccessChain || it.opcode() == spv::OpInBoundsAccessChain) { - SPIRVId sourcevar = it.word(3); + rdcspv::Id sourcevar = it.word(3); // is this a var we want to snoop? auto varIt = varLookup.find(sourcevar); @@ -378,7 +380,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // members. RDCASSERT(it.size() >= 5, it.size()); - SPIRVId index = it.word(4); + rdcspv::Id index = it.word(4); // patch after the access chain it++; @@ -386,9 +388,9 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // upcast the index to uint32 or uint64 depending on which path we're taking uint32_t targetIndexWidth = useBufferAddress ? 64 : 32; { - SPIRVId indexType = editor.GetIDType(index); + rdcspv::Id indexType = editor.GetIDType(index); - if(indexType == SPIRVId()) + if(indexType == rdcspv::Id()) { RDCERR("Unknown type for ID %u, defaulting to uint32_t", index); indexType = uint32ID; @@ -411,10 +413,10 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, { indexTypeData.signedness = false; - SPIRVId unsignedIndex = editor.MakeId(); + rdcspv::Id unsignedIndex = editor.MakeId(); editor.AddOperation( - it, SPIRVOperation(spv::OpBitcast, - {editor.DeclareType(indexTypeData), unsignedIndex, index})); + it, rdcspv::Operation(spv::OpBitcast, + {editor.DeclareType(indexTypeData), unsignedIndex, index})); it++; index = unsignedIndex; @@ -423,18 +425,18 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // if it's not wide enough, uconvert expand it if(indexTypeData.width != targetIndexWidth) { - SPIRVId extendedtype = + rdcspv::Id extendedtype = editor.DeclareType(SPIRVScalar(spv::OpTypeInt, targetIndexWidth, false)); - SPIRVId extendedindex = editor.MakeId(); + rdcspv::Id extendedindex = editor.MakeId(); editor.AddOperation( - it, SPIRVOperation(spv::OpUConvert, {extendedtype, extendedindex, index})); + it, rdcspv::Operation(spv::OpUConvert, {extendedtype, extendedindex, index})); it++; index = extendedindex; } } - SPIRVId bufptr; + rdcspv::Id bufptr; if(useBufferAddress) { @@ -442,30 +444,31 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // get our output slot address by adding an offset to the base pointer // baseaddr = bufferAddressConst + bindingOffset - SPIRVId baseaddr = editor.MakeId(); - editor.AddOperation(it, SPIRVOperation(spv::OpIAdd, {uint64ID, baseaddr, - bufferAddressConst, varIt->second})); + rdcspv::Id baseaddr = editor.MakeId(); + editor.AddOperation( + it, rdcspv::Operation(spv::OpIAdd, + {uint64ID, baseaddr, bufferAddressConst, varIt->second})); it++; // shift the index since this is a byte offset // shiftedindex = index << uint32shift - SPIRVId shiftedindex = editor.MakeId(); - editor.AddOperation(it, SPIRVOperation(spv::OpShiftLeftLogical, - {uint64ID, shiftedindex, index, uint32shift})); + rdcspv::Id shiftedindex = editor.MakeId(); + editor.AddOperation(it, rdcspv::Operation(spv::OpShiftLeftLogical, + {uint64ID, shiftedindex, index, uint32shift})); it++; // add the index on top of that // offsetaddr = baseaddr + shiftedindex - SPIRVId offsetaddr = editor.MakeId(); + rdcspv::Id offsetaddr = editor.MakeId(); editor.AddOperation( - it, SPIRVOperation(spv::OpIAdd, {uint64ID, offsetaddr, baseaddr, shiftedindex})); + it, rdcspv::Operation(spv::OpIAdd, {uint64ID, offsetaddr, baseaddr, shiftedindex})); it++; // make a pointer out of it // uint32_t *bufptr = (uint32_t *)offsetaddr bufptr = editor.MakeId(); editor.AddOperation( - it, SPIRVOperation(spv::OpConvertUToPtr, {uint32ptrtype, bufptr, offsetaddr})); + it, rdcspv::Operation(spv::OpConvertUToPtr, {uint32ptrtype, bufptr, offsetaddr})); it++; } else @@ -474,9 +477,9 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // add the index to this binding's base index // ssboindex = bindingOffset + index - SPIRVId ssboindex = editor.MakeId(); + rdcspv::Id ssboindex = editor.MakeId(); editor.AddOperation( - it, SPIRVOperation(spv::OpIAdd, {uint32ID, ssboindex, index, varIt->second})); + it, rdcspv::Operation(spv::OpIAdd, {uint32ID, ssboindex, index, varIt->second})); it++; // accesschain to get the pointer we'll atomic into. @@ -484,15 +487,15 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // uint32_t *bufptr = (uint32_t *)&buf.rtarray[ssboindex]; bufptr = editor.MakeId(); editor.AddOperation( - it, SPIRVOperation(spv::OpAccessChain, - {uint32ptrtype, bufptr, ssboVar, rtarrayOffset, ssboindex})); + it, rdcspv::Operation(spv::OpAccessChain, + {uint32ptrtype, bufptr, ssboVar, rtarrayOffset, ssboindex})); it++; } // atomically set the uint32 that's pointed to editor.AddOperation( - it, SPIRVOperation(spv::OpAtomicUMax, - {uint32ID, editor.MakeId(), bufptr, scope, semantics, usedValue})); + it, rdcspv::Operation(spv::OpAtomicUMax, {uint32ID, editor.MakeId(), bufptr, scope, + semantics, usedValue})); // no it++ here, it will happen implicitly on loop continue } diff --git a/renderdoc/driver/vulkan/vk_postvs.cpp b/renderdoc/driver/vulkan/vk_postvs.cpp index 461f120a4..513dc3228 100644 --- a/renderdoc/driver/vulkan/vk_postvs.cpp +++ b/renderdoc/driver/vulkan/vk_postvs.cpp @@ -60,8 +60,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV uint32_t numOutputs = (uint32_t)refl.outputSignature.size(); RDCASSERT(numOutputs > 0); - for(SPIRVIterator it = editor.Begin(SPIRVSection::Annotations), - end = editor.End(SPIRVSection::Annotations); + for(rdcspv::Iter it = editor.Begin(SPIRVSection::Annotations), + end = editor.End(SPIRVSection::Annotations); it < end; ++it) { // we will use descriptor set 0 bindings 0..N for our own purposes. @@ -92,41 +92,41 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // if this is a builtin value, what builtin value is expected ShaderBuiltin builtin = ShaderBuiltin::Undefined; // ID of the variable - SPIRVId variableID; + rdcspv::Id variableID; // constant ID for the index of this attribute - SPIRVId constID; + rdcspv::Id constID; // the type ID for this attribute. Must be present already by definition! - SPIRVId basetypeID; + rdcspv::Id basetypeID; // tbuffer type for this input tbufferType tbuffer; // gvec4 type for this input, used as result type when fetching from tbuffer uint32_t vec4ID; // Uniform Pointer ID for this output. Used only for output data, to write to output SSBO - SPIRVId uniformPtrID; + rdcspv::Id uniformPtrID; // Output Pointer ID for this attribute. // For inputs, used to 'write' to the global at the start. // For outputs, used to 'read' from the global at the end. - SPIRVId privatePtrID; + rdcspv::Id privatePtrID; }; std::vector ins; ins.resize(numInputs); std::vector outs; outs.resize(numOutputs); - std::set inputs; - std::set outputs; + std::set inputs; + std::set outputs; - std::map typeReplacements; + std::map typeReplacements; // rewrite any inputs and outputs to be private storage class - for(SPIRVIterator it = editor.Begin(SPIRVSection::TypesVariablesConstants), - end = editor.End(SPIRVSection::TypesVariablesConstants); + for(rdcspv::Iter it = editor.Begin(SPIRVSection::TypesVariablesConstants), + end = editor.End(SPIRVSection::TypesVariablesConstants); it < end; ++it) { // rewrite any input/output variables to private, and build up inputs/outputs list if(it.opcode() == spv::OpTypePointer) { - SPIRVId id; + rdcspv::Id id; if(it.word(2) == spv::StorageClassInput) { @@ -138,9 +138,9 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV id = it.word(1); outputs.insert(id); - SPIRVId baseId = it.word(3); + rdcspv::Id baseId = it.word(3); - SPIRVIterator baseIt = editor.GetID(baseId); + rdcspv::Iter baseIt = editor.GetID(baseId); if(baseIt && baseIt.opcode() == spv::OpTypeStruct) outputs.insert(baseId); } @@ -149,7 +149,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV { SPIRVPointer privPtr(it.word(3), spv::StorageClassPrivate); - SPIRVId origId = editor.GetType(privPtr); + rdcspv::Id origId = editor.GetType(privPtr); if(origId) { @@ -211,7 +211,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV if(replIt != typeReplacements.end()) { // make a copy of the opcode - SPIRVOperation op = SPIRVOperation::copy(it); + rdcspv::Operation op = rdcspv::Operation::copy(it); // remove the old one editor.Remove(it); // add it anew @@ -257,7 +257,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV } } - for(SPIRVIterator it = editor.Begin(SPIRVSection::Functions); it; ++it) + for(rdcspv::Iter it = editor.Begin(SPIRVSection::Functions); it; ++it) { // identify functions with result types we might want to replace if(it.opcode() == spv::OpFunction || it.opcode() == spv::OpFunctionParameter || @@ -278,8 +278,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV } // detect builtin inputs or outputs, and remove builtin decorations - for(SPIRVIterator it = editor.Begin(SPIRVSection::Annotations), - end = editor.End(SPIRVSection::Annotations); + for(rdcspv::Iter it = editor.Begin(SPIRVSection::Annotations), + end = editor.End(SPIRVSection::Annotations); it < end; ++it) { // remove any builtin decorations @@ -296,7 +296,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // remove block decoration from input or output structs if(it.opcode() == spv::OpDecorate && it.word(2) == spv::DecorationBlock) { - SPIRVId id = it.word(1); + rdcspv::Id id = it.word(1); if(outputs.find(id) != outputs.end() || inputs.find(id) != inputs.end()) editor.Remove(it); @@ -316,9 +316,9 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV } } - SPIRVId entryID = 0; + rdcspv::Id entryID = 0; - std::set entries; + std::set entries; for(const SPIRVEntry &entry : editor.GetEntries()) { @@ -330,13 +330,13 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV RDCASSERT(entryID); - for(SPIRVIterator it = editor.Begin(SPIRVSection::Debug), end2 = editor.End(SPIRVSection::Debug); + for(rdcspv::Iter it = editor.Begin(SPIRVSection::Debug), end2 = editor.End(SPIRVSection::Debug); it < end2; ++it) { if(it.opcode() == spv::OpName && (inputs.find(it.word(1)) != inputs.end() || outputs.find(it.word(1)) != outputs.end())) { - SPIRVId id = it.word(1); + rdcspv::Id id = it.word(1); std::string oldName = (const char *)&it.word(2); editor.Remove(it); if(typeReplacements.find(id) == typeReplacements.end()) @@ -476,8 +476,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV tbuffers[tb].imageSampledTypeID = editor.DeclareType(SPIRVSampledImage(tbuffers[tb].imageTypeID)); uint32_t arrayType = editor.MakeId(); - editor.AddType( - SPIRVOperation(spv::OpTypeArray, {arrayType, tbuffers[tb].imageSampledTypeID, arraySize})); + editor.AddType(rdcspv::Operation(spv::OpTypeArray, + {arrayType, tbuffers[tb].imageSampledTypeID, arraySize})); uint32_t arrayPtrType = editor.DeclareType(SPIRVPointer(arrayType, spv::StorageClassUniformConstant)); @@ -486,21 +486,21 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV SPIRVPointer(tbuffers[tb].imageSampledTypeID, spv::StorageClassUniformConstant)); tbuffers[tb].variableID = editor.MakeId(); - editor.AddVariable(SPIRVOperation( + editor.AddVariable(rdcspv::Operation( spv::OpVariable, {arrayPtrType, tbuffers[tb].variableID, spv::StorageClassUniformConstant})); editor.SetName(tbuffers[tb].variableID, name); - editor.AddDecoration(SPIRVOperation( + editor.AddDecoration(rdcspv::Operation( spv::OpDecorate, {tbuffers[tb].variableID, (uint32_t)spv::DecorationDescriptorSet, 0})); - editor.AddDecoration(SPIRVOperation( + editor.AddDecoration(rdcspv::Operation( spv::OpDecorate, {tbuffers[tb].variableID, (uint32_t)spv::DecorationBinding, (uint32_t)tb})); } - SPIRVId uint32Vec4ID = 0; - SPIRVId idxImageTypeID = 0; - SPIRVId idxImagePtr = 0; - SPIRVId idxSampledTypeID = 0; + rdcspv::Id uint32Vec4ID = 0; + rdcspv::Id idxImageTypeID = 0; + rdcspv::Id idxImagePtr = 0; + rdcspv::Id idxSampledTypeID = 0; if(draw->flags & DrawFlags::Indexed) { @@ -514,15 +514,15 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV editor.DeclareType(SPIRVPointer(idxSampledTypeID, spv::StorageClassUniformConstant)); idxImagePtr = editor.MakeId(); - editor.AddVariable(SPIRVOperation( + editor.AddVariable(rdcspv::Operation( spv::OpVariable, {idxImagePtrType, idxImagePtr, spv::StorageClassUniformConstant})); editor.SetName(idxImagePtr, "ibuffer"); + editor.AddDecoration(rdcspv::Operation( + spv::OpDecorate, {idxImagePtr, (uint32_t)spv::DecorationDescriptorSet, 0})); editor.AddDecoration( - SPIRVOperation(spv::OpDecorate, {idxImagePtr, (uint32_t)spv::DecorationDescriptorSet, 0})); - editor.AddDecoration( - SPIRVOperation(spv::OpDecorate, {idxImagePtr, (uint32_t)spv::DecorationBinding, 1})); + rdcspv::Operation(spv::OpDecorate, {idxImagePtr, (uint32_t)spv::DecorationBinding, 1})); } if(numInputs > 0) @@ -530,10 +530,10 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV editor.AddCapability(spv::CapabilitySampledBuffer); } - SPIRVId outBufferVarID = 0; - SPIRVId numVertsConstID = editor.AddConstantImmediate(numVerts); - SPIRVId numInstConstID = editor.AddConstantImmediate(draw->numInstances); - SPIRVId numViewsConstID = editor.AddConstantImmediate(numViews); + rdcspv::Id outBufferVarID = 0; + rdcspv::Id numVertsConstID = editor.AddConstantImmediate(numVerts); + rdcspv::Id numInstConstID = editor.AddConstantImmediate(draw->numInstances); + rdcspv::Id numViewsConstID = editor.AddConstantImmediate(numViews); editor.SetName(numVertsConstID, "numVerts"); editor.SetName(numInstConstID, "numInsts"); @@ -546,25 +546,25 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV words.push_back(outs[o].basetypeID); // struct vertex { ... outputs }; - SPIRVId vertStructID = editor.DeclareStructType(words); + rdcspv::Id vertStructID = editor.DeclareStructType(words); editor.SetName(vertStructID, "vertex_struct"); // vertex vertArray[]; - SPIRVId runtimeArrayID = - editor.AddType(SPIRVOperation(spv::OpTypeRuntimeArray, {editor.MakeId(), vertStructID})); + rdcspv::Id runtimeArrayID = + editor.AddType(rdcspv::Operation(spv::OpTypeRuntimeArray, {editor.MakeId(), vertStructID})); editor.SetName(runtimeArrayID, "vertex_array"); // struct meshOutput { vertex vertArray[]; }; - SPIRVId outputStructID = editor.DeclareStructType({runtimeArrayID}); + rdcspv::Id outputStructID = editor.DeclareStructType({runtimeArrayID}); editor.SetName(outputStructID, "meshOutput"); // meshOutput * - SPIRVId outputStructPtrID = + rdcspv::Id outputStructPtrID = editor.DeclareType(SPIRVPointer(outputStructID, spv::StorageClassUniform)); editor.SetName(outputStructPtrID, "meshOutput_ptr"); // meshOutput *outputData; - outBufferVarID = editor.AddVariable(SPIRVOperation( + outBufferVarID = editor.AddVariable(rdcspv::Operation( spv::OpVariable, {outputStructPtrID, editor.MakeId(), spv::StorageClassUniform})); editor.SetName(outBufferVarID, "outputData"); @@ -590,8 +590,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV memberOffset = AlignUp(memberOffset, 4U * elemSize); // apply decoration to each member in the struct with its offset in the struct - editor.AddDecoration(SPIRVOperation(spv::OpMemberDecorate, - {vertStructID, o, spv::DecorationOffset, memberOffset})); + editor.AddDecoration(rdcspv::Operation( + spv::OpMemberDecorate, {vertStructID, o, spv::DecorationOffset, memberOffset})); memberOffset += elemSize * refl.outputSignature[o].compCount; } @@ -605,40 +605,41 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // the array is the only element in the output struct, so // it's at offset 0 editor.AddDecoration( - SPIRVOperation(spv::OpMemberDecorate, {outputStructID, 0, spv::DecorationOffset, 0})); + rdcspv::Operation(spv::OpMemberDecorate, {outputStructID, 0, spv::DecorationOffset, 0})); // set array stride - editor.AddDecoration( - SPIRVOperation(spv::OpDecorate, {runtimeArrayID, spv::DecorationArrayStride, bufStride})); + editor.AddDecoration(rdcspv::Operation( + spv::OpDecorate, {runtimeArrayID, spv::DecorationArrayStride, bufStride})); // set object type editor.AddDecoration( - SPIRVOperation(spv::OpDecorate, {outputStructID, spv::DecorationBufferBlock})); + rdcspv::Operation(spv::OpDecorate, {outputStructID, spv::DecorationBufferBlock})); // set binding editor.AddDecoration( - SPIRVOperation(spv::OpDecorate, {outBufferVarID, spv::DecorationDescriptorSet, 0})); - editor.AddDecoration(SPIRVOperation(spv::OpDecorate, {outBufferVarID, spv::DecorationBinding, 0})); + rdcspv::Operation(spv::OpDecorate, {outBufferVarID, spv::DecorationDescriptorSet, 0})); + editor.AddDecoration( + rdcspv::Operation(spv::OpDecorate, {outBufferVarID, spv::DecorationBinding, 0})); } - SPIRVId uint32Vec3ID = editor.DeclareType(SPIRVVector(scalar(), 3)); - SPIRVId invocationPtr = editor.DeclareType(SPIRVPointer(uint32Vec3ID, spv::StorageClassInput)); - SPIRVId invocationId = editor.AddVariable( - SPIRVOperation(spv::OpVariable, {invocationPtr, editor.MakeId(), spv::StorageClassInput})); - editor.AddDecoration(SPIRVOperation( + rdcspv::Id uint32Vec3ID = editor.DeclareType(SPIRVVector(scalar(), 3)); + rdcspv::Id invocationPtr = editor.DeclareType(SPIRVPointer(uint32Vec3ID, spv::StorageClassInput)); + rdcspv::Id invocationId = editor.AddVariable( + rdcspv::Operation(spv::OpVariable, {invocationPtr, editor.MakeId(), spv::StorageClassInput})); + editor.AddDecoration(rdcspv::Operation( spv::OpDecorate, {invocationId, spv::DecorationBuiltIn, spv::BuiltInGlobalInvocationId})); editor.SetName(invocationId, "rdoc_invocation"); // make a new entry point that will call the old function, then when it returns extract & write // the outputs. - SPIRVId wrapperEntry = editor.MakeId(); + rdcspv::Id wrapperEntry = editor.MakeId(); // don't set a debug name, as some drivers get confused when this doesn't match the entry point // name :(. // editor.SetName(wrapperEntry, "RenderDoc_MeshFetch_Wrapper_Entrypoint"); // we remove all entry points and just create one of our own. - SPIRVIterator it = editor.Begin(SPIRVSection::EntryPoints); + rdcspv::Iter it = editor.Begin(SPIRVSection::EntryPoints); { // there should already have been at least one entry point @@ -649,21 +650,19 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV editor.PreModify(it); - SPIRVOperation op(it); + it.nopRemove(5); - op.nopRemove(5); - - op[1] = spv::ExecutionModelGLCompute; - op[2] = wrapperEntry; - op[3] = MAKE_FOURCC('r', 'd', 'c', 0); - op[4] = invocationId; + it.word(1) = spv::ExecutionModelGLCompute; + it.word(2) = wrapperEntry; + it.word(3) = MAKE_FOURCC('r', 'd', 'c', 0); + it.word(4) = invocationId; editor.PostModify(it); ++it; } - for(SPIRVIterator end = editor.End(SPIRVSection::EntryPoints); it < end; ++it) + for(rdcspv::Iter end = editor.End(SPIRVSection::EntryPoints); it < end; ++it) editor.Remove(it); // Strip away any execution modes from the original shaders @@ -672,7 +671,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV { if(it.opcode() == spv::OpExecutionMode) { - SPIRVId modeEntryID = SPIRVId(it.word(1)); + rdcspv::Id modeEntryID = rdcspv::Id(it.word(1)); // We only need to be cautious about what we are stripping for the entry // that we are actually translating, the rest aren't used anyways. @@ -688,43 +687,35 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV } } - editor.PreModify(it); - - SPIRVOperation op(it); - - // invalid to have a nop here, but it will be stripped out later - op.nopRemove(1); - op[0] = SPV_NOP; - - editor.PostModify(it); + editor.Remove(it); } } // Add our compute shader execution mode editor.AddExecutionMode(wrapperEntry, spv::ExecutionModeLocalSize, {MeshOutputDispatchWidth, 1, 1}); - SPIRVId uint32ID = editor.DeclareType(scalar()); + rdcspv::Id uint32ID = editor.DeclareType(scalar()); // add the wrapper function { - std::vector ops; + std::vector ops; - SPIRVId voidType = editor.DeclareType(scalar()); - SPIRVId funcType = editor.DeclareType(SPIRVFunction(voidType, {})); + rdcspv::Id voidType = editor.DeclareType(scalar()); + rdcspv::Id funcType = editor.DeclareType(SPIRVFunction(voidType, {})); - ops.push_back(SPIRVOperation(spv::OpFunction, - {voidType, wrapperEntry, spv::FunctionControlMaskNone, funcType})); + ops.push_back(rdcspv::Operation( + spv::OpFunction, {voidType, wrapperEntry, spv::FunctionControlMaskNone, funcType})); - ops.push_back(SPIRVOperation(spv::OpLabel, {editor.MakeId()})); + ops.push_back(rdcspv::Operation(spv::OpLabel, {editor.MakeId()})); { // uint3 invocationVec = gl_GlobalInvocationID; uint32_t invocationVector = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpLoad, {uint32Vec3ID, invocationVector, invocationId})); + ops.push_back(rdcspv::Operation(spv::OpLoad, {uint32Vec3ID, invocationVector, invocationId})); // uint invocation = invocationVec.x uint32_t uintInvocationID = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpCompositeExtract, - {uint32ID, uintInvocationID, invocationVector, 0U})); + ops.push_back(rdcspv::Operation(spv::OpCompositeExtract, + {uint32ID, uintInvocationID, invocationVector, 0U})); // arraySlotID = uintInvocationID; uint32_t arraySlotID = uintInvocationID; @@ -733,38 +724,40 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // uint viewinst = uintInvocationID / numVerts uint32_t viewinstID = editor.MakeId(); - ops.push_back( - SPIRVOperation(spv::OpUDiv, {uint32ID, viewinstID, uintInvocationID, numVertsConstID})); + ops.push_back(rdcspv::Operation(spv::OpUDiv, + {uint32ID, viewinstID, uintInvocationID, numVertsConstID})); editor.SetName(viewinstID, "viewInstance"); uint32_t instID = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpUMod, {uint32ID, instID, viewinstID, numInstConstID})); + ops.push_back(rdcspv::Operation(spv::OpUMod, {uint32ID, instID, viewinstID, numInstConstID})); editor.SetName(instID, "instanceID"); uint32_t viewID = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpUDiv, {uint32ID, viewID, viewinstID, numInstConstID})); + ops.push_back(rdcspv::Operation(spv::OpUDiv, {uint32ID, viewID, viewinstID, numInstConstID})); editor.SetName(viewID, "viewID"); // bool inBounds = viewID < numViews; uint32_t inBounds = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpULessThan, {editor.DeclareType(scalar()), inBounds, - viewID, numViewsConstID})); + ops.push_back(rdcspv::Operation(spv::OpULessThan, {editor.DeclareType(scalar()), + inBounds, viewID, numViewsConstID})); // if(inBounds) goto continueLabel; else goto killLabel; uint32_t killLabel = editor.MakeId(); uint32_t continueLabel = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpSelectionMerge, {killLabel, spv::SelectionControlMaskNone})); - ops.push_back(SPIRVOperation(spv::OpBranchConditional, {inBounds, continueLabel, killLabel})); + ops.push_back( + rdcspv::Operation(spv::OpSelectionMerge, {killLabel, spv::SelectionControlMaskNone})); + ops.push_back(rdcspv::Operation(spv::OpBranchConditional, {inBounds, continueLabel, killLabel})); // continueLabel: - ops.push_back(SPIRVOperation(spv::OpLabel, {continueLabel})); + ops.push_back(rdcspv::Operation(spv::OpLabel, {continueLabel})); // uint vtx = uintInvocationID % numVerts uint32_t vtxID = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpUMod, {uint32ID, vtxID, uintInvocationID, numVertsConstID})); + ops.push_back( + rdcspv::Operation(spv::OpUMod, {uint32ID, vtxID, uintInvocationID, numVertsConstID})); editor.SetName(vtxID, "vertexID"); @@ -776,20 +769,21 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV { // sampledimage idximg = *idximgPtr; uint32_t loaded = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpLoad, {idxSampledTypeID, loaded, idxImagePtr})); + ops.push_back(rdcspv::Operation(spv::OpLoad, {idxSampledTypeID, loaded, idxImagePtr})); // image rawimg = imageFromSampled(idximg); uint32_t rawimg = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpImage, {idxImageTypeID, rawimg, loaded})); + ops.push_back(rdcspv::Operation(spv::OpImage, {idxImageTypeID, rawimg, loaded})); // uvec4 result = texelFetch(rawimg, vtxID); uint32_t result = editor.MakeId(); ops.push_back( - SPIRVOperation(spv::OpImageFetch, {uint32Vec4ID, result, rawimg, vertexIndexID})); + rdcspv::Operation(spv::OpImageFetch, {uint32Vec4ID, result, rawimg, vertexIndexID})); // vertexIndex = result.x; vertexIndexID = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpCompositeExtract, {uint32ID, vertexIndexID, result, 0})); + ops.push_back( + rdcspv::Operation(spv::OpCompositeExtract, {uint32ID, vertexIndexID, result, 0})); } // we use the current value of vertexIndex and use instID, to lookup per-vertex and @@ -804,17 +798,17 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // for non-indexed draws, we manually apply the vertex offset, but here after we used the // 0-based one to calculate the array slot vertexIndexID = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpIAdd, - {uint32ID, vertexIndexID, vtxID, - editor.AddConstantImmediate(draw->vertexOffset)})); + ops.push_back(rdcspv::Operation( + spv::OpIAdd, {uint32ID, vertexIndexID, vtxID, + editor.AddConstantImmediate(draw->vertexOffset)})); } editor.SetName(vertexIndexID, "vertexIndex"); // instIndex = inst + instOffset uint32_t instIndexID = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpIAdd, - {uint32ID, instIndexID, instID, - editor.AddConstantImmediate(draw->instanceOffset)})); + ops.push_back(rdcspv::Operation( + spv::OpIAdd, {uint32ID, instIndexID, instID, + editor.AddConstantImmediate(draw->instanceOffset)})); editor.SetName(instIndexID, "instanceIndex"); uint32_t idxs[64] = {}; @@ -864,14 +858,15 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV { if(refl.inputSignature[i].compType == compType) { - ops.push_back(SPIRVOperation(spv::OpStore, {ins[i].variableID, valueID})); + ops.push_back(rdcspv::Operation(spv::OpStore, {ins[i].variableID, valueID})); } else { uint32_t castedValue = editor.MakeId(); // assume we can just bitcast - ops.push_back(SPIRVOperation(spv::OpBitcast, {ins[i].basetypeID, castedValue, valueID})); - ops.push_back(SPIRVOperation(spv::OpStore, {ins[i].variableID, castedValue})); + ops.push_back( + rdcspv::Operation(spv::OpBitcast, {ins[i].basetypeID, castedValue, valueID})); + ops.push_back(rdcspv::Operation(spv::OpStore, {ins[i].variableID, castedValue})); } } else @@ -894,16 +889,17 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV uint32_t ptrId = editor.MakeId(); // sampledimage *imgPtr = xxx_tbuffers[i]; - ops.push_back(SPIRVOperation(spv::OpAccessChain, {tb.pointerTypeID, ptrId, tb.variableID, - idxs[refl.inputSignature[i].regIndex]})); + ops.push_back(rdcspv::Operation( + spv::OpAccessChain, + {tb.pointerTypeID, ptrId, tb.variableID, idxs[refl.inputSignature[i].regIndex]})); // sampledimage img = *imgPtr; uint32_t loaded = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpLoad, {tb.imageSampledTypeID, loaded, ptrId})); + ops.push_back(rdcspv::Operation(spv::OpLoad, {tb.imageSampledTypeID, loaded, ptrId})); // image rawimg = imageFromSampled(img); uint32_t rawimg = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpImage, {tb.imageTypeID, rawimg, loaded})); + ops.push_back(rdcspv::Operation(spv::OpImage, {tb.imageTypeID, rawimg, loaded})); // vec4 result = texelFetch(rawimg, vtxID or instID); uint32_t idx = vertexLookupID; @@ -932,7 +928,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // otherwise we divide by the divisor idx = editor.MakeId(); divisor = editor.AddConstantImmediate(divisor); - ops.push_back(SPIRVOperation(spv::OpUDiv, {uint32ID, idx, instanceLookupID, divisor})); + ops.push_back( + rdcspv::Operation(spv::OpUDiv, {uint32ID, idx, instanceLookupID, divisor})); } } @@ -940,13 +937,13 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV { // since doubles are packed into two uints, we need to multiply the index by two uint32_t doubled = editor.MakeId(); - ops.push_back(SPIRVOperation( + ops.push_back(rdcspv::Operation( spv::OpIMul, {uint32ID, doubled, idx, editor.AddConstantImmediate(2)})); idx = doubled; } uint32_t result = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpImageFetch, {ins[i].vec4ID, result, rawimg, idx})); + ops.push_back(rdcspv::Operation(spv::OpImageFetch, {ins[i].vec4ID, result, rawimg, idx})); if(refl.inputSignature[i].compType == CompType::Double) { @@ -955,12 +952,12 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // bounds of the buffer uint32_t nextidx = editor.MakeId(); - ops.push_back(SPIRVOperation( + ops.push_back(rdcspv::Operation( spv::OpIAdd, {uint32ID, nextidx, idx, editor.AddConstantImmediate(1)})); uint32_t result2 = editor.MakeId(); ops.push_back( - SPIRVOperation(spv::OpImageFetch, {ins[i].vec4ID, result2, rawimg, nextidx})); + rdcspv::Operation(spv::OpImageFetch, {ins[i].vec4ID, result2, rawimg, nextidx})); uint32_t glsl450 = editor.ImportExtInst("GLSL.std.450"); @@ -973,7 +970,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV uint32_t packed = editor.MakeId(); // uvec2 packed = result.[xy/zw] / result2.[xy/zw]; - ops.push_back(SPIRVOperation( + ops.push_back(rdcspv::Operation( spv::OpVectorShuffle, {uvec2Type, packed, result, result2, c * 2 + 0, c * 2 + 1})); char swizzle[] = "xyzw"; @@ -982,11 +979,11 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // double comp = PackDouble2x32(packed); comps[c] = editor.MakeId(); - ops.push_back( - SPIRVOperation(spv::OpExtInst, { - editor.DeclareType(scalar()), comps[c], - glsl450, GLSLstd450PackDouble2x32, packed, - })); + ops.push_back(rdcspv::Operation( + spv::OpExtInst, { + editor.DeclareType(scalar()), comps[c], glsl450, + GLSLstd450PackDouble2x32, packed, + })); } // if there's only one component it's ready, otherwise construct a vector @@ -1004,7 +1001,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV words.push_back(comps[c]); // baseTypeN value = result.xyz; - ops.push_back(SPIRVOperation(spv::OpCompositeConstruct, words)); + ops.push_back(rdcspv::Operation(spv::OpCompositeConstruct, words)); } } else if(refl.inputSignature[i].compCount == 1) @@ -1015,8 +1012,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV result = editor.MakeId(); // baseType value = result.x; - ops.push_back( - SPIRVOperation(spv::OpCompositeExtract, {ins[i].basetypeID, result, swizzleIn, 0})); + ops.push_back(rdcspv::Operation(spv::OpCompositeExtract, + {ins[i].basetypeID, result, swizzleIn, 0})); } else if(refl.inputSignature[i].compCount != 4) { @@ -1030,7 +1027,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV words.push_back(c); // baseTypeN value = result.xyz; - ops.push_back(SPIRVOperation(spv::OpVectorShuffle, words)); + ops.push_back(rdcspv::Operation(spv::OpVectorShuffle, words)); } // copy the 4 component result directly @@ -1039,7 +1036,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV if(patchData.inputs[i].accessChain.empty()) { // *global = value - ops.push_back(SPIRVOperation(spv::OpStore, {ins[i].variableID, result})); + ops.push_back(rdcspv::Operation(spv::OpStore, {ins[i].variableID, result})); } else { @@ -1055,17 +1052,17 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV words.push_back(idxs[accessIdx]); } - ops.push_back(SPIRVOperation(spv::OpAccessChain, words)); + ops.push_back(rdcspv::Operation(spv::OpAccessChain, words)); - ops.push_back(SPIRVOperation(spv::OpStore, {subElement, result})); + ops.push_back(rdcspv::Operation(spv::OpStore, {subElement, result})); } } } // real_main(); - ops.push_back(SPIRVOperation(spv::OpFunctionCall, {voidType, editor.MakeId(), entryID})); + ops.push_back(rdcspv::Operation(spv::OpFunctionCall, {voidType, editor.MakeId(), entryID})); - SPIRVId zero = editor.AddConstantImmediate(0); + rdcspv::Id zero = editor.AddConstantImmediate(0); for(uint32_t o = 0; o < numOutputs; o++) { @@ -1076,8 +1073,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV { loaded = editor.MakeId(); // type loaded = *globalvar; - ops.push_back( - SPIRVOperation(spv::OpLoad, {outs[o].basetypeID, loaded, patchData.outputs[o].ID})); + ops.push_back(rdcspv::Operation(spv::OpLoad, + {outs[o].basetypeID, loaded, patchData.outputs[o].ID})); } else { @@ -1096,31 +1093,31 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV } // type *readPtr = globalvar.globalsub...; - ops.push_back(SPIRVOperation(spv::OpAccessChain, words)); + ops.push_back(rdcspv::Operation(spv::OpAccessChain, words)); // type loaded = *readPtr; - ops.push_back(SPIRVOperation(spv::OpLoad, {outs[o].basetypeID, loaded, readPtr})); + ops.push_back(rdcspv::Operation(spv::OpLoad, {outs[o].basetypeID, loaded, readPtr})); } // access chain the destination // type *writePtr = outBuffer.verts[arraySlot].outputN uint32_t writePtr = editor.MakeId(); - ops.push_back(SPIRVOperation( + ops.push_back(rdcspv::Operation( spv::OpAccessChain, {outs[o].uniformPtrID, writePtr, outBufferVarID, zero, arraySlotID, outs[o].constID})); // *writePtr = loaded; - ops.push_back(SPIRVOperation(spv::OpStore, {writePtr, loaded})); + ops.push_back(rdcspv::Operation(spv::OpStore, {writePtr, loaded})); } // goto killLabel; - ops.push_back(SPIRVOperation(spv::OpBranch, {killLabel})); + ops.push_back(rdcspv::Operation(spv::OpBranch, {killLabel})); // killLabel: - ops.push_back(SPIRVOperation(spv::OpLabel, {killLabel})); + ops.push_back(rdcspv::Operation(spv::OpLabel, {killLabel})); } - ops.push_back(SPIRVOperation(spv::OpReturn, {})); + ops.push_back(rdcspv::Operation(spv::OpReturn, {})); - ops.push_back(SPIRVOperation(spv::OpFunctionEnd, {})); + ops.push_back(rdcspv::Operation(spv::OpFunctionEnd, {})); editor.AddFunction(ops.data(), ops.size()); } @@ -1147,7 +1144,7 @@ static void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData bool hasXFB = false; - for(SPIRVIterator it = editor.Begin(SPIRVSection::ExecutionMode); + for(rdcspv::Iter it = editor.Begin(SPIRVSection::ExecutionMode); it < editor.End(SPIRVSection::ExecutionMode); ++it) { if(it.opcode() == spv::OpExecutionMode && it.word(1) == entryid && @@ -1160,22 +1157,14 @@ static void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData if(hasXFB) { - for(SPIRVIterator it = editor.Begin(SPIRVSection::Annotations); + for(rdcspv::Iter it = editor.Begin(SPIRVSection::Annotations); it < editor.End(SPIRVSection::Annotations); ++it) { // remove any existing xfb decorations if(it.opcode() == spv::OpDecorate && (it.word(2) == spv::DecorationXfbBuffer || it.word(2) == spv::DecorationXfbStride)) { - editor.PreModify(it); - - SPIRVOperation op(it); - - // invalid to have a nop here, but it will be stripped out later - op.nopRemove(1); - op[0] = SPV_NOP; - - editor.PostModify(it); + editor.Remove(it); } // offset is trickier, need to see if it'll match one we want later @@ -1189,28 +1178,14 @@ static void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData if(it.opcode() == spv::OpMemberDecorate && it.word(1) == outpatch[i].structID && it.word(2) == outpatch[i].accessChain.back()) { - editor.PreModify(it); - - SPIRVOperation op(it); - - op.nopRemove(1); - op[0] = SPV_NOP; - - editor.PostModify(it); + editor.Remove(it); } } else { if(it.opcode() == spv::OpDecorate && it.word(1) == outpatch[i].ID) { - editor.PreModify(it); - - SPIRVOperation op(it); - - op.nopRemove(1); - op[0] = SPV_NOP; - - editor.PostModify(it); + editor.Remove(it); } } } @@ -1246,13 +1221,13 @@ static void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData } else if(outpatch[i].structID && !outpatch[i].accessChain.empty()) { - editor.AddDecoration(SPIRVOperation( + editor.AddDecoration(rdcspv::Operation( spv::OpMemberDecorate, {outpatch[i].structID, outpatch[i].accessChain.back(), spv::DecorationOffset, xfbStride})); } else if(outpatch[i].ID) { - editor.AddDecoration(SPIRVOperation( + editor.AddDecoration(rdcspv::Operation( spv::OpDecorate, {outpatch[i].ID, (uint32_t)spv::DecorationOffset, xfbStride})); } @@ -1271,9 +1246,9 @@ static void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData if(outpatch[i].ID && !outpatch[i].isArraySubsequentElement && vars.find(outpatch[i].ID) == vars.end()) { - editor.AddDecoration( - SPIRVOperation(spv::OpDecorate, {outpatch[i].ID, (uint32_t)spv::DecorationXfbBuffer, 0})); - editor.AddDecoration(SPIRVOperation( + editor.AddDecoration(rdcspv::Operation( + spv::OpDecorate, {outpatch[i].ID, (uint32_t)spv::DecorationXfbBuffer, 0})); + editor.AddDecoration(rdcspv::Operation( spv::OpDecorate, {outpatch[i].ID, (uint32_t)spv::DecorationXfbStride, xfbStride})); vars.insert(outpatch[i].ID); }