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.
This commit is contained in:
baldurk committed 2019-06-03 14:16:43 +01:00
1 parent c3d5924f0d
commit d4e7a0633c
6 files changed
+610 -649

No files matched your search

@@ -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;
}
@@ -25,3 +25,138 @@
#pragma once
#include <stdint.h>
#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<uint32_t> &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<uint32_t>::iterator it() { return words->begin() + offset; }
std::vector<uint32_t>::const_iterator it() const { return words->cbegin() + offset; }
size_t offset = 0;
std::vector<uint32_t> *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<uint32_t> &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<uint32_t> &dest) const { dest.insert(dest.end(), begin(), end()); }
void insertInto(std::vector<uint32_t> &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<uint32_t>::const_iterator begin() const { return iter.it(); }
std::vector<uint32_t>::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<uint32_t> words;
};
}; // namespace rdcspv
DECLARE_STRINGISE_TYPE(rdcspv::Id);
+124 -192
View File
@@ -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<uint32_t> 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<uint32_t> &spirvWords) : spirv(spirvWords)
@@ -172,9 +131,9 @@ SPIRVEditor::SPIRVEditor(std::vector<uint32_t> &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<uint32_t> &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<uint32_t> 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<uint32_t> 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<uint32_t> members)
rdcspv::Id SPIRVEditor::DeclareStructType(std::vector<uint32_t> 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<SPIRVId> args;
std::vector<rdcspv::Id> 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<SPIRVId> args;
std::vector<rdcspv::Id> 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<StructType, SPIRVId> &SPIRVEditor::GetTable<StructType>() \
{ \
return variable; \
} \
template <> \
const std::map<StructType, SPIRVId> &SPIRVEditor::GetTable<StructType>() const \
{ \
return variable; \
#define TYPETABLE(StructType, variable) \
template <> \
std::map<StructType, rdcspv::Id> &SPIRVEditor::GetTable<StructType>() \
{ \
return variable; \
} \
template <> \
const std::map<StructType, rdcspv::Id> &SPIRVEditor::GetTable<StructType>() const \
{ \
return variable; \
}
TYPETABLE(SPIRVScalar, scalarTypes);
@@ -989,7 +921,7 @@ static void RemoveSection(std::vector<uint32_t> &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());
+85 -210
View File
@@ -29,151 +29,24 @@
#include <set>
#include <string>
#include <vector>
#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<uint32_t> &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<uint32_t>::iterator it() { return words->begin() + offset; }
std::vector<uint32_t>::const_iterator it() const { return words->cbegin() + offset; }
size_t offset = 0;
std::vector<uint32_t> *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<uint32_t> &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<uint32_t>::const_iterator begin() const { return iter.it(); }
std::vector<uint32_t>::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<uint32_t> 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<SPIRVId> &args) : returnId(ret), argumentIds(args) {}
SPIRVId returnId;
std::vector<SPIRVId> argumentIds;
SPIRVFunction(rdcspv::Id ret, const std::vector<rdcspv::Id> &args)
: returnId(ret), argumentIds(args)
{
}
rdcspv::Id returnId;
std::vector<rdcspv::Id> 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 <typename SPIRVType>
using SPIRVTypeId = std::pair<SPIRVType, SPIRVId>;
using SPIRVTypeId = std::pair<SPIRVType, rdcspv::Id>;
template <typename SPIRVType>
using SPIRVTypeIds = std::vector<SPIRVTypeId<SPIRVType>>;
@@ -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<uint32_t> 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<uint32_t> 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 <typename SPIRVType>
SPIRVId DeclareType(const SPIRVType &t)
rdcspv::Id DeclareType(const SPIRVType &t)
{
std::map<SPIRVType, SPIRVId> &table = GetTable<SPIRVType>();
std::map<SPIRVType, rdcspv::Id> &table = GetTable<SPIRVType>();
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<SPIRVType, SPIRVId>(t, id));
table.insert(it, std::pair<SPIRVType, rdcspv::Id>(t, id));
return id;
}
template <typename SPIRVType>
SPIRVId GetType(const SPIRVType &t)
rdcspv::Id GetType(const SPIRVType &t)
{
std::map<SPIRVType, SPIRVId> &table = GetTable<SPIRVType>();
std::map<SPIRVType, rdcspv::Id> &table = GetTable<SPIRVType>();
auto it = table.find(t);
if(it != table.end())
return it->second;
return SPIRVId();
return rdcspv::Id();
}
template <typename SPIRVType>
SPIRVTypeIds<SPIRVType> GetTypes()
{
std::map<SPIRVType, SPIRVId> &table = GetTable<SPIRVType>();
std::map<SPIRVType, rdcspv::Id> &table = GetTable<SPIRVType>();
SPIRVTypeIds<SPIRVType> ret;
@@ -567,33 +442,33 @@ public:
}
template <typename SPIRVType>
const std::map<SPIRVType, SPIRVId> &GetTypeInfo() const
const std::map<SPIRVType, rdcspv::Id> &GetTypeInfo() const
{
return GetTable<SPIRVType>();
}
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<SPIRVId> &GetStructTypes() const { return structTypes; }
SPIRVId DeclareStructType(std::vector<uint32_t> members);
const std::set<rdcspv::Id> &GetStructTypes() const { return structTypes; }
rdcspv::Id DeclareStructType(std::vector<uint32_t> members);
// helper for AddConstant
template <typename T>
SPIRVId AddConstantImmediate(T t)
rdcspv::Id AddConstantImmediate(T t)
{
SPIRVId typeId = DeclareType(scalar<T>());
rdcspv::Id typeId = DeclareType(scalar<T>());
std::vector<uint32_t> 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<SPIRVEntry> &GetEntries() { return entries; }
const std::vector<SPIRVVariable> &GetVariables() { return variables; }
const std::vector<SPIRVId> &GetFunctions() { return functions; }
SPIRVId GetIDType(SPIRVId id) { return idTypes[id]; }
const std::vector<rdcspv::Id> &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<SPIRVDecoration> decorations;
std::map<SPIRVId, SPIRVBinding> bindings;
std::map<rdcspv::Id, SPIRVBinding> bindings;
std::vector<size_t> idOffsets;
std::vector<SPIRVId> idTypes;
std::vector<rdcspv::Id> idTypes;
std::vector<SPIRVEntry> entries;
std::vector<SPIRVVariable> variables;
std::vector<SPIRVId> functions;
std::vector<rdcspv::Id> functions;
std::set<std::string> extensions;
std::set<spv::Capability> capabilities;
std::map<std::string, SPIRVId> extSets;
std::map<std::string, rdcspv::Id> extSets;
std::map<SPIRVScalar, SPIRVId> scalarTypes;
std::map<SPIRVVector, SPIRVId> vectorTypes;
std::map<SPIRVMatrix, SPIRVId> matrixTypes;
std::map<SPIRVPointer, SPIRVId> pointerTypes;
std::map<SPIRVImage, SPIRVId> imageTypes;
std::map<SPIRVSampler, SPIRVId> samplerTypes;
std::map<SPIRVSampledImage, SPIRVId> sampledImageTypes;
std::map<SPIRVFunction, SPIRVId> functionTypes;
std::map<SPIRVScalar, rdcspv::Id> scalarTypes;
std::map<SPIRVVector, rdcspv::Id> vectorTypes;
std::map<SPIRVMatrix, rdcspv::Id> matrixTypes;
std::map<SPIRVPointer, rdcspv::Id> pointerTypes;
std::map<SPIRVImage, rdcspv::Id> imageTypes;
std::map<SPIRVSampler, rdcspv::Id> samplerTypes;
std::map<SPIRVSampledImage, rdcspv::Id> sampledImageTypes;
std::map<SPIRVFunction, rdcspv::Id> functionTypes;
std::set<SPIRVId> structTypes;
std::set<rdcspv::Id> structTypes;
template <typename SPIRVType>
std::map<SPIRVType, SPIRVId> &GetTable();
std::map<SPIRVType, rdcspv::Id> &GetTable();
template <typename SPIRVType>
const std::map<SPIRVType, SPIRVId> &GetTable() const;
const std::map<SPIRVType, rdcspv::Id> &GetTable() const;
std::vector<uint32_t> &spirv;
};
@@ -44,11 +44,11 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
const bool useBufferAddress = (addr != 0);
SPIRVId uint32ID = editor.DeclareType(scalar<uint32_t>());
SPIRVId int32ID = editor.DeclareType(scalar<int32_t>());
SPIRVId uint64ID, int64ID;
SPIRVId uint32StructID;
SPIRVId funcParamType;
rdcspv::Id uint32ID = editor.DeclareType(scalar<uint32_t>());
rdcspv::Id int32ID = editor.DeclareType(scalar<int32_t>());
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<uint64_t>());
int64ID = editor.DeclareType(scalar<int64_t>());
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<SPIRVId, SPIRVId> varLookup;
std::map<rdcspv::Id, rdcspv::Id> 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<uint64_t>(it->second.offset);
rdcspv::Id id = varLookup[var.id] = editor.AddConstantImmediate<uint64_t>(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>(uint32_t(index));
rdcspv::Id id = varLookup[var.id] = editor.AddConstantImmediate<uint32_t>(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<uint32_t>(0U);
SPIRVId usedValue = editor.AddConstantImmediate<uint32_t>(0xFFFFFFFFU);
SPIRVId scope = editor.AddConstantImmediate<uint32_t>(spv::ScopeInvocation);
SPIRVId semantics = editor.AddConstantImmediate<uint32_t>(0U);
SPIRVId uint32shift = editor.AddConstantImmediate<uint32_t>(2U);
rdcspv::Id rtarrayOffset = editor.AddConstantImmediate<uint32_t>(0U);
rdcspv::Id usedValue = editor.AddConstantImmediate<uint32_t>(0xFFFFFFFFU);
rdcspv::Id scope = editor.AddConstantImmediate<uint32_t>(spv::ScopeInvocation);
rdcspv::Id semantics = editor.AddConstantImmediate<uint32_t>(0U);
rdcspv::Id uint32shift = editor.AddConstantImmediate<uint32_t>(2U);
std::map<SPIRVId, SPIRVScalar> intTypeLookup;
std::map<rdcspv::Id, SPIRVScalar> intTypeLookup;
for(auto scalarType : editor.GetTypeInfo<SPIRVScalar>())
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<SPIRVFunction> funcTypes = editor.GetTypes<SPIRVFunction>();
// functions that have been patched with annotation & extra function parameters if needed
std::set<SPIRVId> patchedFunctions;
std::set<rdcspv::Id> patchedFunctions;
// functions we need to patch, with the indices of which parameters have bindings coming along
// with
std::map<SPIRVId, std::vector<size_t>> functionPatchQueue;
std::map<rdcspv::Id, std::vector<size_t>> 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<size_t> 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<SPIRVId> patchedParamIDs;
std::vector<rdcspv::Id> 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
}
+155 -180
View File
@@ -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<inputOutputIDs> ins;
ins.resize(numInputs);
std::vector<inputOutputIDs> outs;
outs.resize(numOutputs);
std::set<SPIRVId> inputs;
std::set<SPIRVId> outputs;
std::set<rdcspv::Id> inputs;
std::set<rdcspv::Id> outputs;
std::map<SPIRVId, SPIRVId> typeReplacements;
std::map<rdcspv::Id, rdcspv::Id> 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<SPIRVId> entries;
std::set<rdcspv::Id> 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<uint32_t>(numVerts);
SPIRVId numInstConstID = editor.AddConstantImmediate<uint32_t>(draw->numInstances);
SPIRVId numViewsConstID = editor.AddConstantImmediate<uint32_t>(numViews);
rdcspv::Id outBufferVarID = 0;
rdcspv::Id numVertsConstID = editor.AddConstantImmediate<uint32_t>(numVerts);
rdcspv::Id numInstConstID = editor.AddConstantImmediate<uint32_t>(draw->numInstances);
rdcspv::Id numViewsConstID = editor.AddConstantImmediate<uint32_t>(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<uint32_t>(), 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<uint32_t>(), 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<uint32_t>());
rdcspv::Id uint32ID = editor.DeclareType(scalar<uint32_t>());
// add the wrapper function
{
std::vector<SPIRVOperation> ops;
std::vector<rdcspv::Operation> ops;
SPIRVId voidType = editor.DeclareType(scalar<void>());
SPIRVId funcType = editor.DeclareType(SPIRVFunction(voidType, {}));
rdcspv::Id voidType = editor.DeclareType(scalar<void>());
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<bool>()), inBounds,
viewID, numViewsConstID}));
ops.push_back(rdcspv::Operation(spv::OpULessThan, {editor.DeclareType(scalar<bool>()),
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<uint32_t>(draw->vertexOffset)}));
ops.push_back(rdcspv::Operation(
spv::OpIAdd, {uint32ID, vertexIndexID, vtxID,
editor.AddConstantImmediate<uint32_t>(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<uint32_t>(draw->instanceOffset)}));
ops.push_back(rdcspv::Operation(
spv::OpIAdd, {uint32ID, instIndexID, instID,
editor.AddConstantImmediate<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<double>()), comps[c],
glsl450, GLSLstd450PackDouble2x32, packed,
}));
ops.push_back(rdcspv::Operation(
spv::OpExtInst, {
editor.DeclareType(scalar<double>()), 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<uint32_t>(0);
rdcspv::Id zero = editor.AddConstantImmediate<uint32_t>(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);
}