mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-09 22:01:36 +00:00
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:
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);
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user