mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
notify SPIRVEditor of all adds/removes/changes
* This lets the editor update its internal tracking, so e.g. if a type changes then it unregisters the old type and registers the new type. Then any declarations after that point don't accidentally duplicate due to stale internal data.
This commit is contained in:
@@ -27,12 +27,49 @@
|
||||
#include "common/common.h"
|
||||
#include "serialise/serialiser.h"
|
||||
|
||||
static const uint32_t FirstRealWord = 5;
|
||||
|
||||
template <>
|
||||
std::string 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)
|
||||
{
|
||||
type = it.opcode();
|
||||
@@ -88,7 +125,7 @@ SPIRVOperation SPIRVFunction::decl(SPIRVEditor &editor) const
|
||||
|
||||
SPIRVEditor::SPIRVEditor(std::vector<uint32_t> &spirvWords) : spirv(spirvWords)
|
||||
{
|
||||
if(spirv.size() < 5 || spirv[0] != spv::MagicNumber)
|
||||
if(spirv.size() < FirstRealWord || spirv[0] != spv::MagicNumber)
|
||||
{
|
||||
RDCERR("Empty or invalid SPIR-V module");
|
||||
return;
|
||||
@@ -102,19 +139,12 @@ SPIRVEditor::SPIRVEditor(std::vector<uint32_t> &spirvWords) : spirv(spirvWords)
|
||||
// [4] is reserved
|
||||
RDCASSERT(spirv[4] == 0);
|
||||
|
||||
for(SPIRVIterator it(spirv, 5); it; it++)
|
||||
for(SPIRVIterator it(spirv, FirstRealWord); it; it++)
|
||||
{
|
||||
spv::Op opcode = it.opcode();
|
||||
|
||||
// identify entry points
|
||||
if(opcode == spv::OpEntryPoint)
|
||||
{
|
||||
SPIRVEntry entry;
|
||||
entry.id = it.word(2);
|
||||
entry.name = (const char *)&it.word(3);
|
||||
|
||||
entries.push_back(entry);
|
||||
|
||||
// first entry point marks the start of this section
|
||||
if(entryPointSection.startOffset == 0)
|
||||
entryPointSection.startOffset = it.offset;
|
||||
@@ -153,7 +183,6 @@ SPIRVEditor::SPIRVEditor(std::vector<uint32_t> &spirvWords) : spirv(spirvWords)
|
||||
}
|
||||
}
|
||||
|
||||
// identify functions
|
||||
if(opcode == spv::OpFunction)
|
||||
{
|
||||
// if we don't have the end of the types/variables section, this is it
|
||||
@@ -170,85 +199,15 @@ SPIRVEditor::SPIRVEditor(std::vector<uint32_t> &spirvWords) : spirv(spirvWords)
|
||||
decorationSection.startOffset = decorationSection.endOffset = it.offset;
|
||||
}
|
||||
}
|
||||
|
||||
SPIRVId id = it.word(2);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
functions.push_back(id);
|
||||
}
|
||||
|
||||
// identify declared scalar/vector/matrix types
|
||||
if(opcode == spv::OpTypeVoid || opcode == spv::OpTypeBool || opcode == spv::OpTypeInt ||
|
||||
opcode == spv::OpTypeFloat)
|
||||
{
|
||||
uint32_t id = it.word(1);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
SPIRVScalar scalar(it);
|
||||
scalarTypes[scalar] = id;
|
||||
}
|
||||
|
||||
if(opcode == spv::OpTypeVector)
|
||||
{
|
||||
uint32_t id = it.word(1);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
SPIRVIterator scalarIt = GetID(it.word(2));
|
||||
|
||||
if(!scalarIt)
|
||||
{
|
||||
RDCERR("Vector type declared with unknown scalar component type %u", it.word(2));
|
||||
continue;
|
||||
}
|
||||
|
||||
vectorTypes[SPIRVVector(scalarIt, it.word(3))] = id;
|
||||
}
|
||||
|
||||
if(opcode == spv::OpTypeMatrix)
|
||||
{
|
||||
uint32_t id = it.word(1);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
SPIRVIterator vectorIt = GetID(it.word(2));
|
||||
|
||||
if(!vectorIt)
|
||||
{
|
||||
RDCERR("Matrix type declared with unknown vector component type %u", it.word(2));
|
||||
continue;
|
||||
}
|
||||
|
||||
SPIRVIterator scalarIt = GetID(vectorIt.word(2));
|
||||
uint32_t vectorDim = vectorIt.word(3);
|
||||
|
||||
matrixTypes[SPIRVMatrix(SPIRVVector(scalarIt, vectorDim), it.word(3))] = id;
|
||||
}
|
||||
|
||||
if(opcode == spv::OpTypePointer)
|
||||
{
|
||||
uint32_t id = it.word(1);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
pointerTypes[SPIRVPointer(it.word(3), (spv::StorageClass)it.word(2))] = id;
|
||||
}
|
||||
|
||||
if(opcode == spv::OpTypeFunction)
|
||||
{
|
||||
uint32_t id = it.word(1);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
std::vector<SPIRVId> args;
|
||||
|
||||
for(size_t i = 3; i < it.size(); i++)
|
||||
args.push_back(it.word(i));
|
||||
|
||||
functionTypes[SPIRVFunction(it.word(2), args)] = id;
|
||||
}
|
||||
RegisterOp(it);
|
||||
}
|
||||
}
|
||||
|
||||
void SPIRVEditor::StripNops()
|
||||
{
|
||||
for(size_t i = 5; i < spirv.size();)
|
||||
for(size_t i = FirstRealWord; i < spirv.size();)
|
||||
{
|
||||
while(spirv[i] == SPV_NOP)
|
||||
{
|
||||
@@ -287,12 +246,14 @@ void SPIRVEditor::SetName(uint32_t id, const char *name)
|
||||
SPIRVOperation op(spv::OpName, uintName);
|
||||
|
||||
spirv.insert(spirv.begin() + debugSection.endOffset, op.begin(), op.end());
|
||||
RegisterOp(SPIRVIterator(spirv, debugSection.endOffset));
|
||||
addWords(debugSection.endOffset, op.size());
|
||||
}
|
||||
|
||||
void SPIRVEditor::AddDecoration(const SPIRVOperation &op)
|
||||
{
|
||||
spirv.insert(spirv.begin() + decorationSection.endOffset, op.begin(), op.end());
|
||||
RegisterOp(SPIRVIterator(spirv, decorationSection.endOffset));
|
||||
addWords(decorationSection.endOffset, op.size());
|
||||
}
|
||||
|
||||
@@ -301,6 +262,7 @@ SPIRVId SPIRVEditor::AddType(const SPIRVOperation &op)
|
||||
SPIRVId id = op[1];
|
||||
idOffsets[id] = typeVarSection.endOffset;
|
||||
spirv.insert(spirv.begin() + typeVarSection.endOffset, op.begin(), op.end());
|
||||
RegisterOp(SPIRVIterator(spirv, typeVarSection.endOffset));
|
||||
addWords(typeVarSection.endOffset, op.size());
|
||||
return id;
|
||||
}
|
||||
@@ -310,6 +272,7 @@ SPIRVId SPIRVEditor::AddVariable(const SPIRVOperation &op)
|
||||
SPIRVId id = op[2];
|
||||
idOffsets[id] = typeVarSection.endOffset;
|
||||
spirv.insert(spirv.begin() + typeVarSection.endOffset, op.begin(), op.end());
|
||||
RegisterOp(SPIRVIterator(spirv, typeVarSection.endOffset));
|
||||
addWords(typeVarSection.endOffset, op.size());
|
||||
return id;
|
||||
}
|
||||
@@ -319,6 +282,7 @@ SPIRVId SPIRVEditor::AddConstant(const SPIRVOperation &op)
|
||||
SPIRVId id = op[2];
|
||||
idOffsets[id] = typeVarSection.endOffset;
|
||||
spirv.insert(spirv.begin() + typeVarSection.endOffset, op.begin(), op.end());
|
||||
RegisterOp(SPIRVIterator(spirv, typeVarSection.endOffset));
|
||||
addWords(typeVarSection.endOffset, op.size());
|
||||
return id;
|
||||
}
|
||||
@@ -329,6 +293,8 @@ void SPIRVEditor::AddFunction(const SPIRVOperation *ops, size_t count)
|
||||
|
||||
for(size_t i = 0; i < count; i++)
|
||||
spirv.insert(spirv.end(), ops[i].begin(), ops[i].end());
|
||||
|
||||
RegisterOp(SPIRVIterator(spirv, idOffsets[ops[0][2]]));
|
||||
}
|
||||
|
||||
SPIRVIterator SPIRVEditor::GetID(SPIRVId id)
|
||||
@@ -431,6 +397,250 @@ void SPIRVEditor::AddWord(SPIRVIterator iter, uint32_t word)
|
||||
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());
|
||||
|
||||
// update offsets
|
||||
addWords(iter.offset, op.size());
|
||||
}
|
||||
|
||||
void SPIRVEditor::RegisterOp(SPIRVIterator it)
|
||||
{
|
||||
spv::Op opcode = it.opcode();
|
||||
|
||||
if(opcode == spv::OpEntryPoint)
|
||||
{
|
||||
SPIRVEntry entry;
|
||||
entry.id = it.word(2);
|
||||
entry.name = (const char *)&it.word(3);
|
||||
|
||||
entries.push_back(entry);
|
||||
}
|
||||
else if(opcode == spv::OpFunction)
|
||||
{
|
||||
SPIRVId id = it.word(2);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
functions.push_back(id);
|
||||
}
|
||||
else if(opcode == spv::OpTypeVoid || opcode == spv::OpTypeBool || opcode == spv::OpTypeInt ||
|
||||
opcode == spv::OpTypeFloat)
|
||||
{
|
||||
SPIRVId id = it.word(1);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
SPIRVScalar scalar(it);
|
||||
scalarTypes[scalar] = id;
|
||||
}
|
||||
else if(opcode == spv::OpTypeVector)
|
||||
{
|
||||
SPIRVId id = it.word(1);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
SPIRVIterator scalarIt = GetID(it.word(2));
|
||||
|
||||
if(!scalarIt)
|
||||
{
|
||||
RDCERR("Vector type declared with unknown scalar component type %u", it.word(2));
|
||||
return;
|
||||
}
|
||||
|
||||
vectorTypes[SPIRVVector(scalarIt, it.word(3))] = id;
|
||||
}
|
||||
else if(opcode == spv::OpTypeMatrix)
|
||||
{
|
||||
SPIRVId id = it.word(1);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
SPIRVIterator vectorIt = GetID(it.word(2));
|
||||
|
||||
if(!vectorIt)
|
||||
{
|
||||
RDCERR("Matrix type declared with unknown vector component type %u", it.word(2));
|
||||
return;
|
||||
}
|
||||
|
||||
SPIRVIterator 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;
|
||||
|
||||
SPIRVIterator scalarIt = GetID(it.word(2));
|
||||
|
||||
if(!scalarIt)
|
||||
{
|
||||
RDCERR("Image type declared with unknown scalar component type %u", it.word(2));
|
||||
return;
|
||||
}
|
||||
|
||||
imageTypes[SPIRVImage(scalarIt, (spv::Dim)it.word(3), it.word(4), it.word(5), it.word(6),
|
||||
it.word(7), (spv::ImageFormat)it.word(8))] = id;
|
||||
}
|
||||
else if(opcode == spv::OpTypeSampledImage)
|
||||
{
|
||||
SPIRVId id = it.word(1);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
SPIRVId base = it.word(2);
|
||||
|
||||
sampledImageTypes[SPIRVSampledImage(base)] = id;
|
||||
}
|
||||
else if(opcode == spv::OpTypePointer)
|
||||
{
|
||||
SPIRVId id = it.word(1);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
pointerTypes[SPIRVPointer(it.word(3), (spv::StorageClass)it.word(2))] = id;
|
||||
}
|
||||
else if(opcode == spv::OpTypeStruct)
|
||||
{
|
||||
idOffsets[it.word(1)] = it.offset;
|
||||
}
|
||||
else if(opcode == spv::OpTypeFunction)
|
||||
{
|
||||
SPIRVId id = it.word(1);
|
||||
idOffsets[id] = it.offset;
|
||||
|
||||
std::vector<SPIRVId> args;
|
||||
|
||||
for(size_t i = 3; i < it.size(); i++)
|
||||
args.push_back(it.word(i));
|
||||
|
||||
functionTypes[SPIRVFunction(it.word(2), args)] = id;
|
||||
}
|
||||
}
|
||||
|
||||
void SPIRVEditor::UnregisterOp(SPIRVIterator it)
|
||||
{
|
||||
spv::Op opcode = it.opcode();
|
||||
|
||||
SPIRVId id;
|
||||
|
||||
if(opcode == spv::OpEntryPoint)
|
||||
{
|
||||
for(auto entryIt = entries.begin(); entryIt != entries.end(); ++entryIt)
|
||||
{
|
||||
if(entryIt->id == it.word(2))
|
||||
{
|
||||
entries.erase(entryIt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(opcode == spv::OpFunction)
|
||||
{
|
||||
id = it.word(2);
|
||||
for(auto funcIt = functions.begin(); funcIt != functions.end(); ++funcIt)
|
||||
{
|
||||
if(*funcIt == id)
|
||||
{
|
||||
functions.erase(funcIt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(opcode == spv::OpTypeVoid || opcode == spv::OpTypeBool || opcode == spv::OpTypeInt ||
|
||||
opcode == spv::OpTypeFloat)
|
||||
{
|
||||
id = it.word(1);
|
||||
|
||||
SPIRVScalar scalar(it);
|
||||
scalarTypes.erase(scalar);
|
||||
}
|
||||
else if(opcode == spv::OpTypeVector)
|
||||
{
|
||||
id = it.word(1);
|
||||
|
||||
SPIRVIterator scalarIt = GetID(it.word(2));
|
||||
|
||||
if(!scalarIt)
|
||||
{
|
||||
RDCERR("Vector type declared with unknown scalar component type %u", it.word(2));
|
||||
return;
|
||||
}
|
||||
|
||||
vectorTypes.erase(SPIRVVector(scalarIt, it.word(3)));
|
||||
}
|
||||
else if(opcode == spv::OpTypeMatrix)
|
||||
{
|
||||
id = it.word(1);
|
||||
|
||||
SPIRVIterator vectorIt = GetID(it.word(2));
|
||||
|
||||
if(!vectorIt)
|
||||
{
|
||||
RDCERR("Matrix type declared with unknown vector component type %u", it.word(2));
|
||||
return;
|
||||
}
|
||||
|
||||
SPIRVIterator scalarIt = GetID(vectorIt.word(2));
|
||||
uint32_t vectorDim = vectorIt.word(3);
|
||||
|
||||
matrixTypes.erase(SPIRVMatrix(SPIRVVector(scalarIt, vectorDim), it.word(3)));
|
||||
}
|
||||
else if(opcode == spv::OpTypeImage)
|
||||
{
|
||||
id = it.word(1);
|
||||
|
||||
SPIRVIterator scalarIt = GetID(it.word(2));
|
||||
|
||||
if(!scalarIt)
|
||||
{
|
||||
RDCERR("Image type declared with unknown scalar component type %u", it.word(2));
|
||||
return;
|
||||
}
|
||||
|
||||
imageTypes.erase(SPIRVImage(scalarIt, (spv::Dim)it.word(3), it.word(4), it.word(5), it.word(6),
|
||||
it.word(7), (spv::ImageFormat)it.word(8)));
|
||||
}
|
||||
else if(opcode == spv::OpTypeSampledImage)
|
||||
{
|
||||
id = it.word(1);
|
||||
|
||||
SPIRVId base = it.word(2);
|
||||
|
||||
sampledImageTypes.erase(SPIRVSampledImage(base));
|
||||
}
|
||||
else if(opcode == spv::OpTypePointer)
|
||||
{
|
||||
id = it.word(1);
|
||||
|
||||
pointerTypes.erase(SPIRVPointer(it.word(3), (spv::StorageClass)it.word(2)));
|
||||
}
|
||||
else if(opcode == spv::OpTypeStruct)
|
||||
{
|
||||
id = it.word(1);
|
||||
}
|
||||
else if(opcode == spv::OpTypeFunction)
|
||||
{
|
||||
id = it.word(1);
|
||||
|
||||
std::vector<SPIRVId> args;
|
||||
|
||||
for(size_t i = 3; i < it.size(); i++)
|
||||
args.push_back(it.word(i));
|
||||
|
||||
functionTypes.erase(SPIRVFunction(it.word(2), args));
|
||||
}
|
||||
|
||||
if(id)
|
||||
idOffsets[id] = 0;
|
||||
}
|
||||
|
||||
void SPIRVEditor::addWords(size_t offs, int32_t num)
|
||||
{
|
||||
// look through every section, any that are >= this point, adjust the offsets
|
||||
|
||||
@@ -128,28 +128,9 @@ public:
|
||||
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(); }
|
||||
void nopRemove()
|
||||
{
|
||||
for(size_t i = 0, sz = size(); i < sz; i++)
|
||||
iter.word(i) = SPV_NOP;
|
||||
}
|
||||
void nopRemove(size_t idx, size_t count = 0)
|
||||
{
|
||||
size_t oldSize = size();
|
||||
|
||||
if(count == 0)
|
||||
count = oldSize - idx;
|
||||
|
||||
// reduce the size of this op
|
||||
*iter = MakeHeader(iter.opcode(), oldSize - count);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
@@ -160,6 +141,7 @@ private:
|
||||
{
|
||||
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.
|
||||
@@ -373,7 +355,22 @@ public:
|
||||
|
||||
SPIRVId MakeId();
|
||||
|
||||
void AddWord(SPIRVIterator entry, uint32_t word);
|
||||
void AddWord(SPIRVIterator iter, uint32_t word);
|
||||
void AddOperation(SPIRVIterator iter, const SPIRVOperation &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); }
|
||||
// called after any modifications, re-adds the operation to internal structures with its new
|
||||
// properties
|
||||
void PostModify(SPIRVIterator iter) { RegisterOp(iter); }
|
||||
// removed an operation and replaces it with nops
|
||||
void Remove(SPIRVIterator iter)
|
||||
{
|
||||
UnregisterOp(iter);
|
||||
SPIRVOperation(iter).nopRemove();
|
||||
}
|
||||
|
||||
void SetName(uint32_t id, const char *name);
|
||||
void AddDecoration(const SPIRVOperation &op);
|
||||
@@ -461,6 +458,9 @@ 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);
|
||||
|
||||
struct LogicalSection
|
||||
{
|
||||
size_t startOffset = 0;
|
||||
|
||||
Reference in New Issue
Block a user