Disallow implicit casts to/from SPIR-V Id

* This can lead to bugs, so instead we should be explicit about what is an ID
  and what is a uint
This commit is contained in:
baldurk
2019-06-03 14:16:43 +01:00
parent 587d562fa3
commit 1fd75c50f8
6 changed files with 360 additions and 303 deletions
@@ -28,7 +28,10 @@
template <>
rdcstr DoStringise(const rdcspv::Id &el)
{
return StringFormat::Fmt("%u", el.id);
uint32_t id;
RDCCOMPILE_ASSERT(sizeof(el) == sizeof(id), "SPIR-V Id isn't 32-bit!");
memcpy(&id, &el, sizeof(el));
return StringFormat::Fmt("%u", id);
}
void rdcspv::Iter::nopRemove(size_t idx, size_t count)
@@ -35,14 +35,18 @@ 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; }
// only allow explicit functions to cast to/from uint32_t
constexpr static inline Id fromWord(uint32_t i) { return Id(i); }
inline uint32_t value() const { return id; }
constexpr inline explicit operator bool() const { return id != 0; }
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; }
private:
constexpr inline Id(uint32_t i) : id(i) {}
uint32_t id;
};
+83 -81
View File
@@ -49,23 +49,23 @@ SPIRVScalar::SPIRVScalar(rdcspv::Iter it)
rdcspv::Operation SPIRVVector::decl(SPIRVEditor &editor) const
{
return rdcspv::Operation(spv::OpTypeVector, {0U, editor.DeclareType(scalar), count});
return rdcspv::Operation(spv::OpTypeVector, {0U, editor.DeclareType(scalar).value(), count});
}
rdcspv::Operation SPIRVMatrix::decl(SPIRVEditor &editor) const
{
return rdcspv::Operation(spv::OpTypeMatrix, {0U, editor.DeclareType(vector), count});
return rdcspv::Operation(spv::OpTypeMatrix, {0U, editor.DeclareType(vector).value(), count});
}
rdcspv::Operation SPIRVPointer::decl(SPIRVEditor &editor) const
{
return rdcspv::Operation(spv::OpTypePointer, {0U, (uint32_t)storage, baseId});
return rdcspv::Operation(spv::OpTypePointer, {0U, (uint32_t)storage, baseId.value()});
}
rdcspv::Operation SPIRVImage::decl(SPIRVEditor &editor) const
{
return rdcspv::Operation(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).value(), (uint32_t)dim,
depth, arrayed, ms, sampled, (uint32_t)format});
}
rdcspv::Operation SPIRVSampler::decl(SPIRVEditor &editor) const
@@ -75,7 +75,7 @@ rdcspv::Operation SPIRVSampler::decl(SPIRVEditor &editor) const
rdcspv::Operation SPIRVSampledImage::decl(SPIRVEditor &editor) const
{
return rdcspv::Operation(spv::OpTypeSampledImage, {0U, baseId});
return rdcspv::Operation(spv::OpTypeSampledImage, {0U, baseId.value()});
}
rdcspv::Operation SPIRVFunction::decl(SPIRVEditor &editor) const
@@ -83,9 +83,9 @@ rdcspv::Operation SPIRVFunction::decl(SPIRVEditor &editor) const
std::vector<uint32_t> words;
words.push_back(0U);
words.push_back(returnId);
words.push_back(returnId.value());
for(rdcspv::Id id : argumentIds)
words.push_back(id);
words.push_back(id.value());
return rdcspv::Operation(spv::OpTypeFunction, words);
}
@@ -276,16 +276,16 @@ rdcspv::Id SPIRVEditor::MakeId()
spirv[3]++;
idOffsets.resize(spirv[3]);
idTypes.resize(spirv[3]);
return ret;
return rdcspv::Id::fromWord(ret);
}
void SPIRVEditor::SetName(uint32_t id, const char *name)
void SPIRVEditor::SetName(rdcspv::Id id, const char *name)
{
size_t sz = strlen(name);
std::vector<uint32_t> uintName((sz / 4) + 1);
memcpy(&uintName[0], name, sz);
uintName.insert(uintName.begin(), id);
uintName.insert(uintName.begin(), id.value());
rdcspv::Operation op(spv::OpName, uintName);
@@ -354,7 +354,7 @@ void SPIRVEditor::AddExecutionMode(rdcspv::Id entry, spv::ExecutionMode mode,
size_t offset = sections[SPIRVSection::ExecutionMode].endOffset;
params.insert(params.begin(), (uint32_t)mode);
params.insert(params.begin(), (uint32_t)entry);
params.insert(params.begin(), entry.value());
rdcspv::Operation op(spv::OpExecutionMode, params);
op.insertInto(spirv, offset);
@@ -383,7 +383,7 @@ rdcspv::Id SPIRVEditor::ImportExtInst(const char *setname)
std::vector<uint32_t> uintName((sz / 4) + 1);
memcpy(&uintName[0], setname, sz);
uintName.insert(uintName.begin(), ret);
uintName.insert(uintName.begin(), ret.value());
rdcspv::Operation op(spv::OpExtInstImport, uintName);
op.insertInto(spirv, it.offs());
@@ -399,8 +399,8 @@ rdcspv::Id SPIRVEditor::AddType(const rdcspv::Operation &op)
{
size_t offset = sections[SPIRVSection::Types].endOffset;
rdcspv::Id id = op[1];
idOffsets[id] = offset;
rdcspv::Id id = rdcspv::Id::fromWord(op[1]);
idOffsets[id.value()] = offset;
op.insertInto(spirv, offset);
RegisterOp(rdcspv::Iter(spirv, offset));
addWords(offset, op.size());
@@ -411,8 +411,8 @@ rdcspv::Id SPIRVEditor::AddVariable(const rdcspv::Operation &op)
{
size_t offset = sections[SPIRVSection::Variables].endOffset;
rdcspv::Id id = op[2];
idOffsets[id] = offset;
rdcspv::Id id = rdcspv::Id::fromWord(op[2]);
idOffsets[id.value()] = offset;
op.insertInto(spirv, offset);
RegisterOp(rdcspv::Iter(spirv, offset));
addWords(offset, op.size());
@@ -423,8 +423,8 @@ rdcspv::Id SPIRVEditor::AddConstant(const rdcspv::Operation &op)
{
size_t offset = sections[SPIRVSection::Constants].endOffset;
rdcspv::Id id = op[2];
idOffsets[id] = offset;
rdcspv::Id id = rdcspv::Id::fromWord(op[2]);
idOffsets[id.value()] = offset;
op.insertInto(spirv, offset);
RegisterOp(rdcspv::Iter(spirv, offset));
addWords(offset, op.size());
@@ -443,7 +443,7 @@ void SPIRVEditor::AddFunction(const rdcspv::Operation *ops, size_t count)
rdcspv::Iter SPIRVEditor::GetID(rdcspv::Id id)
{
size_t offs = idOffsets[id];
size_t offs = idOffsets[id.value()];
if(offs)
return rdcspv::Iter(spirv, offs);
@@ -458,7 +458,7 @@ rdcspv::Iter SPIRVEditor::GetEntry(rdcspv::Id id)
while(it && it < end)
{
if(it.word(2) == id)
if(it.word(2) == id.value())
return it;
it++;
}
@@ -466,11 +466,13 @@ rdcspv::Iter SPIRVEditor::GetEntry(rdcspv::Id id)
return rdcspv::Iter();
}
rdcspv::Id SPIRVEditor::DeclareStructType(std::vector<uint32_t> members)
rdcspv::Id SPIRVEditor::DeclareStructType(const std::vector<rdcspv::Id> &members)
{
std::vector<uint32_t> words(members.size());
memcpy(words.data(), members.data(), words.size() * sizeof(uint32_t));
rdcspv::Id typeId = MakeId();
members.insert(members.begin(), typeId);
AddType(rdcspv::Operation(spv::OpTypeStruct, members));
words.insert(words.begin(), typeId.value());
AddType(rdcspv::Operation(spv::OpTypeStruct, words));
return typeId;
}
@@ -497,14 +499,14 @@ void SPIRVEditor::RegisterOp(rdcspv::Iter it)
if(hasResult && hasResultType)
{
RDCASSERT(it.word(2) < idTypes.size());
idTypes[it.word(2)] = it.word(1);
idTypes[it.word(2)] = rdcspv::Id::fromWord(it.word(1));
}
}
if(opcode == spv::OpEntryPoint)
{
SPIRVEntry entry;
entry.id = it.word(2);
entry.id = rdcspv::Id::fromWord(it.word(2));
entry.name = (const char *)&it.word(3);
entries.push_back(entry);
@@ -525,32 +527,32 @@ void SPIRVEditor::RegisterOp(rdcspv::Iter it)
}
else if(opcode == spv::OpExtInstImport)
{
rdcspv::Id id = it.word(1);
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
const char *name = (const char *)&it.word(2);
extSets[name] = id;
}
else if(opcode == spv::OpFunction)
{
rdcspv::Id id = it.word(2);
idOffsets[id] = it.offs();
rdcspv::Id id = rdcspv::Id::fromWord(it.word(2));
idOffsets[id.value()] = it.offs();
functions.push_back(id);
}
else if(opcode == spv::OpVariable)
{
SPIRVVariable var;
var.type = it.word(1);
var.id = it.word(2);
var.type = rdcspv::Id::fromWord(it.word(1));
var.id = rdcspv::Id::fromWord(it.word(2));
var.storageClass = (spv::StorageClass)it.word(3);
if(it.size() > 4)
var.init = it.word(4);
var.init = rdcspv::Id::fromWord(it.word(4));
variables.push_back(var);
}
else if(opcode == spv::OpDecorate)
{
SPIRVDecoration decoration;
decoration.id = it.word(1);
decoration.id = rdcspv::Id::fromWord(it.word(1));
decoration.dec = (spv::Decoration)it.word(2);
RDCASSERTMSG("Too many parameters in decoration", it.size() <= 7, it.size());
@@ -569,18 +571,18 @@ void SPIRVEditor::RegisterOp(rdcspv::Iter it)
else if(opcode == spv::OpTypeVoid || opcode == spv::OpTypeBool || opcode == spv::OpTypeInt ||
opcode == spv::OpTypeFloat)
{
rdcspv::Id id = it.word(1);
idOffsets[id] = it.offs();
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
idOffsets[id.value()] = it.offs();
SPIRVScalar scalar(it);
scalarTypes[scalar] = id;
}
else if(opcode == spv::OpTypeVector)
{
rdcspv::Id id = it.word(1);
idOffsets[id] = it.offs();
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
idOffsets[id.value()] = it.offs();
rdcspv::Iter scalarIt = GetID(it.word(2));
rdcspv::Iter scalarIt = GetID(rdcspv::Id::fromWord(it.word(2)));
if(!scalarIt)
{
@@ -592,10 +594,10 @@ void SPIRVEditor::RegisterOp(rdcspv::Iter it)
}
else if(opcode == spv::OpTypeMatrix)
{
rdcspv::Id id = it.word(1);
idOffsets[id] = it.offs();
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
idOffsets[id.value()] = it.offs();
rdcspv::Iter vectorIt = GetID(it.word(2));
rdcspv::Iter vectorIt = GetID(rdcspv::Id::fromWord(it.word(2)));
if(!vectorIt)
{
@@ -603,17 +605,17 @@ void SPIRVEditor::RegisterOp(rdcspv::Iter it)
return;
}
rdcspv::Iter scalarIt = GetID(vectorIt.word(2));
rdcspv::Iter scalarIt = GetID(rdcspv::Id::fromWord(vectorIt.word(2)));
uint32_t vectorDim = vectorIt.word(3);
matrixTypes[SPIRVMatrix(SPIRVVector(scalarIt, vectorDim), it.word(3))] = id;
}
else if(opcode == spv::OpTypeImage)
{
rdcspv::Id id = it.word(1);
idOffsets[id] = it.offs();
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
idOffsets[id.value()] = it.offs();
rdcspv::Iter scalarIt = GetID(it.word(2));
rdcspv::Iter scalarIt = GetID(rdcspv::Id::fromWord(it.word(2)));
if(!scalarIt)
{
@@ -626,45 +628,45 @@ void SPIRVEditor::RegisterOp(rdcspv::Iter it)
}
else if(opcode == spv::OpTypeSampler)
{
rdcspv::Id id = it.word(1);
idOffsets[id] = it.offs();
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
idOffsets[id.value()] = it.offs();
samplerTypes[SPIRVSampler()] = id;
}
else if(opcode == spv::OpTypeSampledImage)
{
rdcspv::Id id = it.word(1);
idOffsets[id] = it.offs();
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
idOffsets[id.value()] = it.offs();
rdcspv::Id base = it.word(2);
rdcspv::Id base = rdcspv::Id::fromWord(it.word(2));
sampledImageTypes[SPIRVSampledImage(base)] = id;
}
else if(opcode == spv::OpTypePointer)
{
rdcspv::Id id = it.word(1);
idOffsets[id] = it.offs();
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
idOffsets[id.value()] = it.offs();
pointerTypes[SPIRVPointer(it.word(3), (spv::StorageClass)it.word(2))] = id;
pointerTypes[SPIRVPointer(rdcspv::Id::fromWord(it.word(3)), (spv::StorageClass)it.word(2))] = id;
}
else if(opcode == spv::OpTypeStruct)
{
rdcspv::Id id = it.word(1);
idOffsets[id] = it.offs();
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
idOffsets[id.value()] = it.offs();
structTypes.insert(id);
}
else if(opcode == spv::OpTypeFunction)
{
rdcspv::Id id = it.word(1);
idOffsets[id] = it.offs();
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
idOffsets[id.value()] = it.offs();
std::vector<rdcspv::Id> args;
for(size_t i = 3; i < it.size(); i++)
args.push_back(it.word(i));
args.push_back(rdcspv::Id::fromWord(it.word(i)));
functionTypes[SPIRVFunction(it.word(2), args)] = id;
functionTypes[SPIRVFunction(rdcspv::Id::fromWord(it.word(2)), args)] = id;
}
}
@@ -677,7 +679,7 @@ void SPIRVEditor::UnregisterOp(rdcspv::Iter it)
spv::HasResultAndType(opcode, &hasResult, &hasResultType);
if(hasResult && hasResultType)
idTypes[it.word(2)] = 0;
idTypes[it.word(2)] = rdcspv::Id();
}
rdcspv::Id id;
@@ -695,7 +697,7 @@ void SPIRVEditor::UnregisterOp(rdcspv::Iter it)
}
else if(opcode == spv::OpFunction)
{
id = it.word(2);
id = rdcspv::Id::fromWord(it.word(2));
for(auto funcIt = functions.begin(); funcIt != functions.end(); ++funcIt)
{
if(*funcIt == id)
@@ -707,7 +709,7 @@ void SPIRVEditor::UnregisterOp(rdcspv::Iter it)
}
else if(opcode == spv::OpVariable)
{
id = it.word(2);
id = rdcspv::Id::fromWord(it.word(2));
for(auto varIt = variables.begin(); varIt != variables.end(); ++varIt)
{
if(varIt->id == id)
@@ -720,7 +722,7 @@ void SPIRVEditor::UnregisterOp(rdcspv::Iter it)
else if(opcode == spv::OpDecorate)
{
SPIRVDecoration decoration;
decoration.id = it.word(1);
decoration.id = rdcspv::Id::fromWord(it.word(1));
decoration.dec = (spv::Decoration)it.word(2);
RDCASSERTMSG("Too many parameters in decoration", it.size() <= 7, it.size());
@@ -754,16 +756,16 @@ void SPIRVEditor::UnregisterOp(rdcspv::Iter it)
else if(opcode == spv::OpTypeVoid || opcode == spv::OpTypeBool || opcode == spv::OpTypeInt ||
opcode == spv::OpTypeFloat)
{
id = it.word(1);
id = rdcspv::Id::fromWord(it.word(1));
SPIRVScalar scalar(it);
scalarTypes.erase(scalar);
}
else if(opcode == spv::OpTypeVector)
{
id = it.word(1);
id = rdcspv::Id::fromWord(it.word(1));
rdcspv::Iter scalarIt = GetID(it.word(2));
rdcspv::Iter scalarIt = GetID(rdcspv::Id::fromWord(it.word(2)));
if(!scalarIt)
{
@@ -775,9 +777,9 @@ void SPIRVEditor::UnregisterOp(rdcspv::Iter it)
}
else if(opcode == spv::OpTypeMatrix)
{
id = it.word(1);
id = rdcspv::Id::fromWord(it.word(1));
rdcspv::Iter vectorIt = GetID(it.word(2));
rdcspv::Iter vectorIt = GetID(rdcspv::Id::fromWord(it.word(2)));
if(!vectorIt)
{
@@ -785,16 +787,16 @@ void SPIRVEditor::UnregisterOp(rdcspv::Iter it)
return;
}
rdcspv::Iter scalarIt = GetID(vectorIt.word(2));
rdcspv::Iter scalarIt = GetID(rdcspv::Id::fromWord(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);
id = rdcspv::Id::fromWord(it.word(1));
rdcspv::Iter scalarIt = GetID(it.word(2));
rdcspv::Iter scalarIt = GetID(rdcspv::Id::fromWord(it.word(2)));
if(!scalarIt)
{
@@ -807,44 +809,44 @@ void SPIRVEditor::UnregisterOp(rdcspv::Iter it)
}
else if(opcode == spv::OpTypeSampler)
{
id = it.word(1);
id = rdcspv::Id::fromWord(it.word(1));
samplerTypes.erase(SPIRVSampler());
}
else if(opcode == spv::OpTypeSampledImage)
{
id = it.word(1);
id = rdcspv::Id::fromWord(it.word(1));
rdcspv::Id base = it.word(2);
rdcspv::Id base = rdcspv::Id::fromWord(it.word(2));
sampledImageTypes.erase(SPIRVSampledImage(base));
}
else if(opcode == spv::OpTypePointer)
{
id = it.word(1);
id = rdcspv::Id::fromWord(it.word(1));
pointerTypes.erase(SPIRVPointer(it.word(3), (spv::StorageClass)it.word(2)));
pointerTypes.erase(SPIRVPointer(rdcspv::Id::fromWord(it.word(3)), (spv::StorageClass)it.word(2)));
}
else if(opcode == spv::OpTypeStruct)
{
id = it.word(1);
id = rdcspv::Id::fromWord(it.word(1));
structTypes.erase(id);
}
else if(opcode == spv::OpTypeFunction)
{
id = it.word(1);
id = rdcspv::Id::fromWord(it.word(1));
std::vector<rdcspv::Id> args;
for(size_t i = 3; i < it.size(); i++)
args.push_back(it.word(i));
args.push_back(rdcspv::Id::fromWord(it.word(i)));
functionTypes.erase(SPIRVFunction(it.word(2), args));
functionTypes.erase(SPIRVFunction(rdcspv::Id::fromWord(it.word(2)), args));
}
if(id)
idOffsets[id] = 0;
idOffsets[id.value()] = 0;
}
void SPIRVEditor::addWords(size_t offs, int32_t num)
@@ -372,7 +372,7 @@ public:
iter.nopRemove();
}
void SetName(uint32_t id, const char *name);
void SetName(rdcspv::Id id, const char *name);
void AddDecoration(const rdcspv::Operation &op);
void AddCapability(spv::Capability cap);
void AddExtension(const std::string &extension);
@@ -408,7 +408,8 @@ public:
return it->second;
rdcspv::Operation decl = t.decl(*this);
rdcspv::Id id = decl[1] = MakeId();
rdcspv::Id id = MakeId();
decl[1] = id.value();
AddType(decl);
table.insert(it, std::pair<SPIRVType, rdcspv::Id>(t, id));
@@ -455,14 +456,14 @@ public:
return it->second;
}
const std::set<rdcspv::Id> &GetStructTypes() const { return structTypes; }
rdcspv::Id DeclareStructType(std::vector<uint32_t> members);
rdcspv::Id DeclareStructType(const std::vector<rdcspv::Id> &members);
// helper for AddConstant
template <typename T>
rdcspv::Id AddConstantImmediate(T t)
{
rdcspv::Id typeId = DeclareType(scalar<T>());
std::vector<uint32_t> words = {typeId, MakeId()};
std::vector<uint32_t> words = {typeId.value(), MakeId().value()};
words.insert(words.end(), sizeof(T) / 4, 0U);
@@ -485,7 +486,7 @@ public:
const std::vector<SPIRVEntry> &GetEntries() { return entries; }
const std::vector<SPIRVVariable> &GetVariables() { return variables; }
const std::vector<rdcspv::Id> &GetFunctions() { return functions; }
rdcspv::Id GetIDType(rdcspv::Id id) { return idTypes[id]; }
rdcspv::Id GetIDType(rdcspv::Id id) { return idTypes[id.value()]; }
private:
inline void addWords(size_t offs, size_t num) { addWords(offs, (int32_t)num); }
void addWords(size_t offs, int32_t num);
@@ -56,22 +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(rdcspv::Operation(spv::OpTypeStruct, {editor.MakeId(), uint32ID}));
uint32StructID = editor.AddType(
rdcspv::Operation(spv::OpTypeStruct, {editor.MakeId().value(), uint32ID.value()}));
// any function parameters we add are uint64 byte offsets
funcParamType = uint64ID;
}
else
{
rdcspv::Id runtimeArrayID =
editor.AddType(rdcspv::Operation(spv::OpTypeRuntimeArray, {editor.MakeId(), uint32ID}));
rdcspv::Id runtimeArrayID = editor.AddType(
rdcspv::Operation(spv::OpTypeRuntimeArray, {editor.MakeId().value(), uint32ID.value()}));
editor.AddDecoration(rdcspv::Operation(
spv::OpDecorate, {runtimeArrayID, spv::DecorationArrayStride, sizeof(uint32_t)}));
spv::OpDecorate, {runtimeArrayID.value(), spv::DecorationArrayStride, sizeof(uint32_t)}));
uint32StructID =
editor.AddType(rdcspv::Operation(spv::OpTypeStruct, {editor.MakeId(), runtimeArrayID}));
uint32StructID = editor.AddType(
rdcspv::Operation(spv::OpTypeStruct, {editor.MakeId().value(), runtimeArrayID.value()}));
// any function parameters we add are uint32 indices
funcParamType = uint32ID;
@@ -79,8 +79,8 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
editor.SetName(uint32StructID, "__rd_feedbackStruct");
editor.AddDecoration(
rdcspv::Operation(spv::OpMemberDecorate, {uint32StructID, 0, spv::DecorationOffset, 0}));
editor.AddDecoration(rdcspv::Operation(spv::OpMemberDecorate,
{uint32StructID.value(), 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)
@@ -149,7 +149,8 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
editor.SetName(bufferAddressConst, "__rd_feedbackAddress");
// struct is block decorated
editor.AddDecoration(rdcspv::Operation(spv::OpDecorate, {uint32StructID, spv::DecorationBlock}));
editor.AddDecoration(
rdcspv::Operation(spv::OpDecorate, {uint32StructID.value(), spv::DecorationBlock}));
}
else
{
@@ -179,18 +180,18 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
// add our SSBO variable, at set 0 binding 0
ssboVar = editor.MakeId();
editor.AddVariable(
rdcspv::Operation(spv::OpVariable, {bufptrtype, ssboVar, spv::StorageClassUniform}));
editor.AddVariable(rdcspv::Operation(
spv::OpVariable, {bufptrtype.value(), ssboVar.value(), spv::StorageClassUniform}));
editor.AddDecoration(rdcspv::Operation(
spv::OpDecorate, {ssboVar.value(), (uint32_t)spv::DecorationDescriptorSet, 0}));
editor.AddDecoration(
rdcspv::Operation(spv::OpDecorate, {ssboVar, (uint32_t)spv::DecorationDescriptorSet, 0}));
editor.AddDecoration(
rdcspv::Operation(spv::OpDecorate, {ssboVar, (uint32_t)spv::DecorationBinding, 0}));
rdcspv::Operation(spv::OpDecorate, {ssboVar.value(), (uint32_t)spv::DecorationBinding, 0}));
editor.SetName(ssboVar, "__rd_feedbackBuffer");
// struct is bufferblock decorated
editor.AddDecoration(
rdcspv::Operation(spv::OpDecorate, {uint32StructID, (uint32_t)spv::DecorationBufferBlock}));
editor.AddDecoration(rdcspv::Operation(
spv::OpDecorate, {uint32StructID.value(), (uint32_t)spv::DecorationBufferBlock}));
}
rdcspv::Id rtarrayOffset = editor.AddConstantImmediate<uint32_t>(0U);
@@ -263,7 +264,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
it = editor.GetID(funcId);
// change the declared function type
it.word(4) = newFuncTypeID;
it.word(4) = newFuncTypeID.value();
break;
}
@@ -285,7 +286,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
if(watchIndex < patchArgIndices.size() && patchArgIndices[watchIndex] == argIndex)
{
// when we see use of this parameter, patch it using the added parameter
varLookup[it.word(2)] = patchedParamIDs[watchIndex];
varLookup[rdcspv::Id::fromWord(it.word(2))] = patchedParamIDs[watchIndex];
// watch for the next argument
watchIndex++;
}
@@ -297,8 +298,8 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
// we're past the existing function parameters, now declare our new ones
for(size_t i = 0; i < patchedParamIDs.size(); i++)
{
editor.AddOperation(
it, rdcspv::Operation(spv::OpFunctionParameter, {funcParamType, patchedParamIDs[i]}));
editor.AddOperation(it, rdcspv::Operation(spv::OpFunctionParameter,
{funcParamType.value(), patchedParamIDs[i].value()}));
++it;
}
@@ -312,13 +313,13 @@ 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)
{
rdcspv::Id sourcevar = it.word(3);
rdcspv::Id sourcevar = rdcspv::Id::fromWord(it.word(3));
// is this a var we want to snoop?
auto varIt = varLookup.find(sourcevar);
if(varIt != varLookup.end())
{
varLookup[it.word(2)] = varIt->second;
varLookup[rdcspv::Id::fromWord(it.word(2))] = varIt->second;
}
}
@@ -335,10 +336,10 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
// if this param we're snooping then pass our offset - whether it's a constant or a
// function
// argument itself - into the function call
auto varIt = varLookup.find(it.word(i));
auto varIt = varLookup.find(rdcspv::Id::fromWord(it.word(i)));
if(varIt != varLookup.end())
{
funccall.push_back(varIt->second);
funccall.push_back(varIt->second.value());
patchArgs.push_back(i - 4);
}
}
@@ -359,16 +360,17 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
editor.Remove(oldCall);
// if this function isn't marked for patching yet, and isn't patched, queue it
if(functionPatchQueue[it.word(3)].empty() &&
patchedFunctions.find(it.word(3)) == patchedFunctions.end())
functionPatchQueue[it.word(3)] = patchArgs;
rdcspv::Id funcid = rdcspv::Id::fromWord(it.word(3));
if(functionPatchQueue[funcid].empty() &&
patchedFunctions.find(funcid) == patchedFunctions.end())
functionPatchQueue[funcid] = patchArgs;
}
}
// 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)
{
rdcspv::Id sourcevar = it.word(3);
rdcspv::Id sourcevar = rdcspv::Id::fromWord(it.word(3));
// is this a var we want to snoop?
auto varIt = varLookup.find(sourcevar);
@@ -380,7 +382,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
// members.
RDCASSERT(it.size() >= 5, it.size());
rdcspv::Id index = it.word(4);
rdcspv::Id index = rdcspv::Id::fromWord(it.word(4));
// patch after the access chain
it++;
@@ -415,8 +417,8 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
rdcspv::Id unsignedIndex = editor.MakeId();
editor.AddOperation(
it, rdcspv::Operation(spv::OpBitcast,
{editor.DeclareType(indexTypeData), unsignedIndex, index}));
it, rdcspv::Operation(spv::OpBitcast, {editor.DeclareType(indexTypeData).value(),
unsignedIndex.value(), index.value()}));
it++;
index = unsignedIndex;
@@ -429,7 +431,8 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
editor.DeclareType(SPIRVScalar(spv::OpTypeInt, targetIndexWidth, false));
rdcspv::Id extendedindex = editor.MakeId();
editor.AddOperation(
it, rdcspv::Operation(spv::OpUConvert, {extendedtype, extendedindex, index}));
it, rdcspv::Operation(spv::OpUConvert, {extendedtype.value(),
extendedindex.value(), index.value()}));
it++;
index = extendedindex;
@@ -446,29 +449,33 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
// baseaddr = bufferAddressConst + bindingOffset
rdcspv::Id baseaddr = editor.MakeId();
editor.AddOperation(
it, rdcspv::Operation(spv::OpIAdd,
{uint64ID, baseaddr, bufferAddressConst, varIt->second}));
it,
rdcspv::Operation(spv::OpIAdd, {uint64ID.value(), baseaddr.value(),
bufferAddressConst.value(), varIt->second.value()}));
it++;
// shift the index since this is a byte offset
// shiftedindex = index << uint32shift
rdcspv::Id shiftedindex = editor.MakeId();
editor.AddOperation(it, rdcspv::Operation(spv::OpShiftLeftLogical,
{uint64ID, shiftedindex, index, uint32shift}));
{uint64ID.value(), shiftedindex.value(),
index.value(), uint32shift.value()}));
it++;
// add the index on top of that
// offsetaddr = baseaddr + shiftedindex
rdcspv::Id offsetaddr = editor.MakeId();
editor.AddOperation(
it, rdcspv::Operation(spv::OpIAdd, {uint64ID, offsetaddr, baseaddr, shiftedindex}));
it, rdcspv::Operation(spv::OpIAdd, {uint64ID.value(), offsetaddr.value(),
baseaddr.value(), shiftedindex.value()}));
it++;
// make a pointer out of it
// uint32_t *bufptr = (uint32_t *)offsetaddr
bufptr = editor.MakeId();
editor.AddOperation(
it, rdcspv::Operation(spv::OpConvertUToPtr, {uint32ptrtype, bufptr, offsetaddr}));
it, rdcspv::Operation(spv::OpConvertUToPtr,
{uint32ptrtype.value(), bufptr.value(), offsetaddr.value()}));
it++;
}
else
@@ -479,7 +486,8 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
// ssboindex = bindingOffset + index
rdcspv::Id ssboindex = editor.MakeId();
editor.AddOperation(
it, rdcspv::Operation(spv::OpIAdd, {uint32ID, ssboindex, index, varIt->second}));
it, rdcspv::Operation(spv::OpIAdd, {uint32ID.value(), ssboindex.value(),
index.value(), varIt->second.value()}));
it++;
// accesschain to get the pointer we'll atomic into.
@@ -488,14 +496,16 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
bufptr = editor.MakeId();
editor.AddOperation(
it, rdcspv::Operation(spv::OpAccessChain,
{uint32ptrtype, bufptr, ssboVar, rtarrayOffset, ssboindex}));
{uint32ptrtype.value(), bufptr.value(), ssboVar.value(),
rtarrayOffset.value(), ssboindex.value()}));
it++;
}
// atomically set the uint32 that's pointed to
editor.AddOperation(
it, rdcspv::Operation(spv::OpAtomicUMax, {uint32ID, editor.MakeId(), bufptr, scope,
semantics, usedValue}));
it, rdcspv::Operation(spv::OpAtomicUMax,
{uint32ID.value(), editor.MakeId().value(), bufptr.value(),
scope.value(), semantics.value(), usedValue.value()}));
// no it++ here, it will happen implicitly on loop continue
}
+209 -172
View File
@@ -100,7 +100,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
// tbuffer type for this input
tbufferType tbuffer;
// gvec4 type for this input, used as result type when fetching from tbuffer
uint32_t vec4ID;
rdcspv::Id vec4ID;
// Uniform Pointer ID for this output. Used only for output data, to write to output SSBO
rdcspv::Id uniformPtrID;
// Output Pointer ID for this attribute.
@@ -130,15 +130,15 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
if(it.word(2) == spv::StorageClassInput)
{
id = it.word(1);
id = rdcspv::Id::fromWord(it.word(1));
inputs.insert(id);
}
else if(it.word(2) == spv::StorageClassOutput)
{
id = it.word(1);
id = rdcspv::Id::fromWord(it.word(1));
outputs.insert(id);
rdcspv::Id baseId = it.word(3);
rdcspv::Id baseId = rdcspv::Id::fromWord(it.word(3));
rdcspv::Iter baseIt = editor.GetID(baseId);
if(baseIt && baseIt.opcode() == spv::OpTypeStruct)
@@ -147,7 +147,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
if(id)
{
SPIRVPointer privPtr(it.word(3), spv::StorageClassPrivate);
SPIRVPointer privPtr(rdcspv::Id::fromWord(it.word(3)), spv::StorageClassPrivate);
rdcspv::Id origId = editor.GetType(privPtr);
@@ -181,7 +181,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
editor.PreModify(it);
it.word(3) = spv::StorageClassPrivate;
inputs.insert(it.word(2));
inputs.insert(rdcspv::Id::fromWord(it.word(2)));
}
else if(it.word(3) == spv::StorageClassOutput)
{
@@ -189,16 +189,16 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
editor.PreModify(it);
it.word(3) = spv::StorageClassPrivate;
outputs.insert(it.word(2));
outputs.insert(rdcspv::Id::fromWord(it.word(2)));
}
auto replIt = typeReplacements.find(it.word(1));
auto replIt = typeReplacements.find(rdcspv::Id::fromWord(it.word(1)));
if(replIt != typeReplacements.end())
{
if(!mod)
editor.PreModify(it);
mod = true;
it.word(1) = typeReplacements[it.word(1)];
it.word(1) = typeReplacements[rdcspv::Id::fromWord(it.word(1))].value();
}
if(mod)
@@ -222,23 +222,23 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
{
bool mod = false;
auto replIt = typeReplacements.find(it.word(1));
auto replIt = typeReplacements.find(rdcspv::Id::fromWord(it.word(1)));
if(replIt != typeReplacements.end())
{
editor.PreModify(it);
mod = true;
it.word(1) = typeReplacements[it.word(1)];
it.word(1) = typeReplacements[rdcspv::Id::fromWord(it.word(1))].value();
}
for(size_t i = 4; i < it.size(); it++)
{
replIt = typeReplacements.find(it.word(i));
replIt = typeReplacements.find(rdcspv::Id::fromWord(it.word(i)));
if(replIt != typeReplacements.end())
{
if(!mod)
editor.PreModify(it);
mod = true;
it.word(i) = typeReplacements[it.word(i)];
it.word(i) = typeReplacements[rdcspv::Id::fromWord(it.word(i))].value();
}
}
@@ -247,11 +247,11 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
}
else if(it.opcode() == spv::OpConstantNull)
{
auto replIt = typeReplacements.find(it.word(1));
auto replIt = typeReplacements.find(rdcspv::Id::fromWord(it.word(1)));
if(replIt != typeReplacements.end())
{
editor.PreModify(it);
it.word(1) = typeReplacements[it.word(1)];
it.word(1) = typeReplacements[rdcspv::Id::fromWord(it.word(1))].value();
editor.PostModify(it);
}
}
@@ -269,9 +269,9 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
editor.PreModify(it);
uint32_t &id = it.word(1);
auto replIt = typeReplacements.find(id);
auto replIt = typeReplacements.find(rdcspv::Id::fromWord(id));
if(replIt != typeReplacements.end())
id = typeReplacements[id];
id = typeReplacements[rdcspv::Id::fromWord(id)].value();
editor.PostModify(it);
}
@@ -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)
{
rdcspv::Id id = it.word(1);
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
if(outputs.find(id) != outputs.end() || inputs.find(id) != inputs.end())
editor.Remove(it);
@@ -316,7 +316,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
}
}
rdcspv::Id entryID = 0;
rdcspv::Id entryID;
std::set<rdcspv::Id> entries;
@@ -334,9 +334,10 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
it < end2; ++it)
{
if(it.opcode() == spv::OpName &&
(inputs.find(it.word(1)) != inputs.end() || outputs.find(it.word(1)) != outputs.end()))
(inputs.find(rdcspv::Id::fromWord(it.word(1))) != inputs.end() ||
outputs.find(rdcspv::Id::fromWord(it.word(1))) != outputs.end()))
{
rdcspv::Id id = it.word(1);
rdcspv::Id id = rdcspv::Id::fromWord(it.word(1));
std::string oldName = (const char *)&it.word(2);
editor.Remove(it);
if(typeReplacements.find(id) == typeReplacements.end())
@@ -344,7 +345,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
}
// remove any OpName for the old entry points
if(it.opcode() == spv::OpName && entries.find(it.word(1)) != entries.end())
if(it.opcode() == spv::OpName && entries.find(rdcspv::Id::fromWord(it.word(1))) != entries.end())
editor.Remove(it);
}
@@ -360,7 +361,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
// constant for this index
io.constID = editor.AddConstantImmediate(i);
io.variableID = patchData.outputs[i].ID;
io.variableID = rdcspv::Id::fromWord(patchData.outputs[i].ID);
// base type - either a scalar or a vector, since matrix outputs are decayed to vectors
{
@@ -401,7 +402,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
// constant for this index
io.constID = editor.AddConstantImmediate(i);
io.variableID = patchData.inputs[i].ID;
io.variableID = rdcspv::Id::fromWord(patchData.inputs[i].ID);
SPIRVScalar scalarType = scalar<uint32_t>();
@@ -447,13 +448,13 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
struct tbufferIDs
{
uint32_t imageTypeID;
uint32_t imageSampledTypeID;
uint32_t pointerTypeID;
uint32_t variableID;
rdcspv::Id imageTypeID;
rdcspv::Id imageSampledTypeID;
rdcspv::Id pointerTypeID;
rdcspv::Id variableID;
} tbuffers[tbuffer_count];
uint32_t arraySize = editor.AddConstantImmediate<uint32_t>(MeshOutputTBufferArraySize);
rdcspv::Id arraySize = editor.AddConstantImmediate<uint32_t>(MeshOutputTBufferArraySize);
for(tbufferType tb : {tbuffer_float, tbuffer_sint, tbuffer_uint})
{
@@ -475,11 +476,12 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
SPIRVImage(scalarType, spv::DimBuffer, 0, 0, 0, 1, spv::ImageFormatUnknown));
tbuffers[tb].imageSampledTypeID = editor.DeclareType(SPIRVSampledImage(tbuffers[tb].imageTypeID));
uint32_t arrayType = editor.MakeId();
editor.AddType(rdcspv::Operation(spv::OpTypeArray,
{arrayType, tbuffers[tb].imageSampledTypeID, arraySize}));
rdcspv::Id arrayType = editor.MakeId();
editor.AddType(rdcspv::Operation(
spv::OpTypeArray,
{arrayType.value(), tbuffers[tb].imageSampledTypeID.value(), arraySize.value()}));
uint32_t arrayPtrType =
rdcspv::Id arrayPtrType =
editor.DeclareType(SPIRVPointer(arrayType, spv::StorageClassUniformConstant));
tbuffers[tb].pointerTypeID = editor.DeclareType(
@@ -487,20 +489,23 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
tbuffers[tb].variableID = editor.MakeId();
editor.AddVariable(rdcspv::Operation(
spv::OpVariable, {arrayPtrType, tbuffers[tb].variableID, spv::StorageClassUniformConstant}));
spv::OpVariable,
{arrayPtrType.value(), tbuffers[tb].variableID.value(), spv::StorageClassUniformConstant}));
editor.SetName(tbuffers[tb].variableID, name);
editor.AddDecoration(rdcspv::Operation(
spv::OpDecorate, {tbuffers[tb].variableID, (uint32_t)spv::DecorationDescriptorSet, 0}));
spv::OpDecorate,
{tbuffers[tb].variableID.value(), (uint32_t)spv::DecorationDescriptorSet, 0}));
editor.AddDecoration(rdcspv::Operation(
spv::OpDecorate, {tbuffers[tb].variableID, (uint32_t)spv::DecorationBinding, (uint32_t)tb}));
spv::OpDecorate,
{tbuffers[tb].variableID.value(), (uint32_t)spv::DecorationBinding, (uint32_t)tb}));
}
rdcspv::Id uint32Vec4ID = 0;
rdcspv::Id idxImageTypeID = 0;
rdcspv::Id idxImagePtr = 0;
rdcspv::Id idxSampledTypeID = 0;
rdcspv::Id uint32Vec4ID;
rdcspv::Id idxImageTypeID;
rdcspv::Id idxImagePtr;
rdcspv::Id idxSampledTypeID;
if(draw->flags & DrawFlags::Indexed)
{
@@ -510,19 +515,20 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
SPIRVImage(scalar<uint32_t>(), spv::DimBuffer, 0, 0, 0, 1, spv::ImageFormatUnknown));
idxSampledTypeID = editor.DeclareType(SPIRVSampledImage(idxImageTypeID));
uint32_t idxImagePtrType =
rdcspv::Id idxImagePtrType =
editor.DeclareType(SPIRVPointer(idxSampledTypeID, spv::StorageClassUniformConstant));
idxImagePtr = editor.MakeId();
editor.AddVariable(rdcspv::Operation(
spv::OpVariable, {idxImagePtrType, idxImagePtr, spv::StorageClassUniformConstant}));
spv::OpVariable,
{idxImagePtrType.value(), idxImagePtr.value(), spv::StorageClassUniformConstant}));
editor.SetName(idxImagePtr, "ibuffer");
editor.AddDecoration(rdcspv::Operation(
spv::OpDecorate, {idxImagePtr, (uint32_t)spv::DecorationDescriptorSet, 0}));
editor.AddDecoration(
rdcspv::Operation(spv::OpDecorate, {idxImagePtr, (uint32_t)spv::DecorationBinding, 1}));
spv::OpDecorate, {idxImagePtr.value(), (uint32_t)spv::DecorationDescriptorSet, 0}));
editor.AddDecoration(rdcspv::Operation(
spv::OpDecorate, {idxImagePtr.value(), (uint32_t)spv::DecorationBinding, 1}));
}
if(numInputs > 0)
@@ -530,7 +536,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
editor.AddCapability(spv::CapabilitySampledBuffer);
}
rdcspv::Id outBufferVarID = 0;
rdcspv::Id outBufferVarID;
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);
@@ -541,7 +547,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
// declare the output buffer and its type
{
std::vector<uint32_t> words;
std::vector<rdcspv::Id> words;
for(uint32_t o = 0; o < numOutputs; o++)
words.push_back(outs[o].basetypeID);
@@ -550,8 +556,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
editor.SetName(vertStructID, "vertex_struct");
// vertex vertArray[];
rdcspv::Id runtimeArrayID =
editor.AddType(rdcspv::Operation(spv::OpTypeRuntimeArray, {editor.MakeId(), vertStructID}));
rdcspv::Id runtimeArrayID = editor.AddType(rdcspv::Operation(
spv::OpTypeRuntimeArray, {editor.MakeId().value(), vertStructID.value()}));
editor.SetName(runtimeArrayID, "vertex_array");
// struct meshOutput { vertex vertArray[]; };
@@ -565,7 +571,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
// meshOutput *outputData;
outBufferVarID = editor.AddVariable(rdcspv::Operation(
spv::OpVariable, {outputStructPtrID, editor.MakeId(), spv::StorageClassUniform}));
spv::OpVariable,
{outputStructPtrID.value(), editor.MakeId().value(), spv::StorageClassUniform}));
editor.SetName(outBufferVarID, "outputData");
uint32_t memberOffset = 0;
@@ -591,7 +598,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
// apply decoration to each member in the struct with its offset in the struct
editor.AddDecoration(rdcspv::Operation(
spv::OpMemberDecorate, {vertStructID, o, spv::DecorationOffset, memberOffset}));
spv::OpMemberDecorate, {vertStructID.value(), o, spv::DecorationOffset, memberOffset}));
memberOffset += elemSize * refl.outputSignature[o].compCount;
}
@@ -604,30 +611,31 @@ 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(
rdcspv::Operation(spv::OpMemberDecorate, {outputStructID, 0, spv::DecorationOffset, 0}));
editor.AddDecoration(rdcspv::Operation(spv::OpMemberDecorate,
{outputStructID.value(), 0, spv::DecorationOffset, 0}));
// set array stride
editor.AddDecoration(rdcspv::Operation(
spv::OpDecorate, {runtimeArrayID, spv::DecorationArrayStride, bufStride}));
spv::OpDecorate, {runtimeArrayID.value(), spv::DecorationArrayStride, bufStride}));
// set object type
editor.AddDecoration(
rdcspv::Operation(spv::OpDecorate, {outputStructID, spv::DecorationBufferBlock}));
rdcspv::Operation(spv::OpDecorate, {outputStructID.value(), spv::DecorationBufferBlock}));
// set binding
editor.AddDecoration(rdcspv::Operation(
spv::OpDecorate, {outBufferVarID.value(), spv::DecorationDescriptorSet, 0}));
editor.AddDecoration(
rdcspv::Operation(spv::OpDecorate, {outBufferVarID, spv::DecorationDescriptorSet, 0}));
editor.AddDecoration(
rdcspv::Operation(spv::OpDecorate, {outBufferVarID, spv::DecorationBinding, 0}));
rdcspv::Operation(spv::OpDecorate, {outBufferVarID.value(), spv::DecorationBinding, 0}));
}
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}));
rdcspv::Id invocationId = editor.AddVariable(rdcspv::Operation(
spv::OpVariable, {invocationPtr.value(), editor.MakeId().value(), spv::StorageClassInput}));
editor.AddDecoration(rdcspv::Operation(
spv::OpDecorate, {invocationId, spv::DecorationBuiltIn, spv::BuiltInGlobalInvocationId}));
spv::OpDecorate,
{invocationId.value(), spv::DecorationBuiltIn, spv::BuiltInGlobalInvocationId}));
editor.SetName(invocationId, "rdoc_invocation");
@@ -653,9 +661,9 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
it.nopRemove(5);
it.word(1) = spv::ExecutionModelGLCompute;
it.word(2) = wrapperEntry;
it.word(2) = wrapperEntry.value();
it.word(3) = MAKE_FOURCC('r', 'd', 'c', 0);
it.word(4) = invocationId;
it.word(4) = invocationId.value();
editor.PostModify(it);
@@ -671,7 +679,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
{
if(it.opcode() == spv::OpExecutionMode)
{
rdcspv::Id modeEntryID = rdcspv::Id(it.word(1));
rdcspv::Id modeEntryID = rdcspv::Id::fromWord(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.
@@ -704,94 +712,105 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
rdcspv::Id funcType = editor.DeclareType(SPIRVFunction(voidType, {}));
ops.push_back(rdcspv::Operation(
spv::OpFunction, {voidType, wrapperEntry, spv::FunctionControlMaskNone, funcType}));
spv::OpFunction,
{voidType.value(), wrapperEntry.value(), spv::FunctionControlMaskNone, funcType.value()}));
ops.push_back(rdcspv::Operation(spv::OpLabel, {editor.MakeId()}));
ops.push_back(rdcspv::Operation(spv::OpLabel, {editor.MakeId().value()}));
{
// uint3 invocationVec = gl_GlobalInvocationID;
uint32_t invocationVector = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpLoad, {uint32Vec3ID, invocationVector, invocationId}));
rdcspv::Id invocationVector = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpLoad, {uint32Vec3ID.value(), invocationVector.value(), invocationId.value()}));
// uint invocation = invocationVec.x
uint32_t uintInvocationID = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpCompositeExtract,
{uint32ID, uintInvocationID, invocationVector, 0U}));
rdcspv::Id uintInvocationID = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpCompositeExtract,
{uint32ID.value(), uintInvocationID.value(), invocationVector.value(), 0U}));
// arraySlotID = uintInvocationID;
uint32_t arraySlotID = uintInvocationID;
rdcspv::Id arraySlotID = uintInvocationID;
editor.SetName(uintInvocationID, "arraySlot");
// uint viewinst = uintInvocationID / numVerts
uint32_t viewinstID = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpUDiv,
{uint32ID, viewinstID, uintInvocationID, numVertsConstID}));
rdcspv::Id viewinstID = editor.MakeId();
ops.push_back(
rdcspv::Operation(spv::OpUDiv, {uint32ID.value(), viewinstID.value(),
uintInvocationID.value(), numVertsConstID.value()}));
editor.SetName(viewinstID, "viewInstance");
uint32_t instID = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpUMod, {uint32ID, instID, viewinstID, numInstConstID}));
rdcspv::Id instID = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpUMod, {uint32ID.value(), instID.value(),
viewinstID.value(), numInstConstID.value()}));
editor.SetName(instID, "instanceID");
uint32_t viewID = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpUDiv, {uint32ID, viewID, viewinstID, numInstConstID}));
rdcspv::Id viewID = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpUDiv, {uint32ID.value(), viewID.value(),
viewinstID.value(), numInstConstID.value()}));
editor.SetName(viewID, "viewID");
// bool inBounds = viewID < numViews;
uint32_t inBounds = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpULessThan, {editor.DeclareType(scalar<bool>()),
inBounds, viewID, numViewsConstID}));
rdcspv::Id inBounds = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpULessThan,
{editor.DeclareType(scalar<bool>()).value(), inBounds.value(),
viewID.value(), numViewsConstID.value()}));
// if(inBounds) goto continueLabel; else goto killLabel;
uint32_t killLabel = editor.MakeId();
uint32_t continueLabel = editor.MakeId();
ops.push_back(
rdcspv::Operation(spv::OpSelectionMerge, {killLabel, spv::SelectionControlMaskNone}));
ops.push_back(rdcspv::Operation(spv::OpBranchConditional, {inBounds, continueLabel, killLabel}));
rdcspv::Id killLabel = editor.MakeId();
rdcspv::Id continueLabel = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpSelectionMerge,
{killLabel.value(), spv::SelectionControlMaskNone}));
ops.push_back(rdcspv::Operation(
spv::OpBranchConditional, {inBounds.value(), continueLabel.value(), killLabel.value()}));
// continueLabel:
ops.push_back(rdcspv::Operation(spv::OpLabel, {continueLabel}));
ops.push_back(rdcspv::Operation(spv::OpLabel, {continueLabel.value()}));
// uint vtx = uintInvocationID % numVerts
uint32_t vtxID = editor.MakeId();
ops.push_back(
rdcspv::Operation(spv::OpUMod, {uint32ID, vtxID, uintInvocationID, numVertsConstID}));
rdcspv::Id vtxID = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpUMod,
{uint32ID.value(), vtxID.value(), uintInvocationID.value(), numVertsConstID.value()}));
editor.SetName(vtxID, "vertexID");
uint32_t vertexIndexID = vtxID;
rdcspv::Id vertexIndexID = vtxID;
// if we're indexing, look up the index buffer. We don't have to apply vertexOffset - it was
// already applied when we read back and uniq-ified the index buffer.
if(draw->flags & DrawFlags::Indexed)
{
// sampledimage idximg = *idximgPtr;
uint32_t loaded = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpLoad, {idxSampledTypeID, loaded, idxImagePtr}));
rdcspv::Id loaded = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpLoad, {idxSampledTypeID.value(), loaded.value(), idxImagePtr.value()}));
// image rawimg = imageFromSampled(idximg);
uint32_t rawimg = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpImage, {idxImageTypeID, rawimg, loaded}));
rdcspv::Id rawimg = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpImage,
{idxImageTypeID.value(), rawimg.value(), loaded.value()}));
// uvec4 result = texelFetch(rawimg, vtxID);
uint32_t result = editor.MakeId();
ops.push_back(
rdcspv::Operation(spv::OpImageFetch, {uint32Vec4ID, result, rawimg, vertexIndexID}));
rdcspv::Id result = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpImageFetch, {uint32Vec4ID.value(), result.value(),
rawimg.value(), vertexIndexID.value()}));
// vertexIndex = result.x;
vertexIndexID = editor.MakeId();
ops.push_back(
rdcspv::Operation(spv::OpCompositeExtract, {uint32ID, vertexIndexID, result, 0}));
ops.push_back(rdcspv::Operation(
spv::OpCompositeExtract, {uint32ID.value(), vertexIndexID.value(), result.value(), 0}));
}
// we use the current value of vertexIndex and use instID, to lookup per-vertex and
// per-instance attributes. This is because when we fetched the vertex data, we advanced by
// (in non-indexed draws) vertexOffset, and by instanceOffset. Rather than fetching data
// that's only used as padding skipped over by these offsets.
uint32_t vertexLookupID = vertexIndexID;
uint32_t instanceLookupID = instID;
rdcspv::Id vertexLookupID = vertexIndexID;
rdcspv::Id instanceLookupID = instID;
if(!(draw->flags & DrawFlags::Indexed))
{
@@ -799,26 +818,26 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
// 0-based one to calculate the array slot
vertexIndexID = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpIAdd, {uint32ID, vertexIndexID, vtxID,
editor.AddConstantImmediate<uint32_t>(draw->vertexOffset)}));
spv::OpIAdd, {uint32ID.value(), vertexIndexID.value(), vtxID.value(),
editor.AddConstantImmediate<uint32_t>(draw->vertexOffset).value()}));
}
editor.SetName(vertexIndexID, "vertexIndex");
// instIndex = inst + instOffset
uint32_t instIndexID = editor.MakeId();
rdcspv::Id instIndexID = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpIAdd, {uint32ID, instIndexID, instID,
editor.AddConstantImmediate<uint32_t>(draw->instanceOffset)}));
spv::OpIAdd, {uint32ID.value(), instIndexID.value(), instID.value(),
editor.AddConstantImmediate<uint32_t>(draw->instanceOffset).value()}));
editor.SetName(instIndexID, "instanceIndex");
uint32_t idxs[64] = {};
rdcspv::Id idxs[64] = {};
for(size_t i = 0; i < refl.inputSignature.size(); i++)
{
ShaderBuiltin builtin = refl.inputSignature[i].systemValue;
if(builtin != ShaderBuiltin::Undefined)
{
uint32_t valueID = 0;
rdcspv::Id valueID;
CompType compType = CompType::UInt;
if(builtin == ShaderBuiltin::VertexIndex)
@@ -858,15 +877,17 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
{
if(refl.inputSignature[i].compType == compType)
{
ops.push_back(rdcspv::Operation(spv::OpStore, {ins[i].variableID, valueID}));
ops.push_back(
rdcspv::Operation(spv::OpStore, {ins[i].variableID.value(), valueID.value()}));
}
else
{
uint32_t castedValue = editor.MakeId();
rdcspv::Id castedValue = editor.MakeId();
// assume we can just bitcast
ops.push_back(
rdcspv::Operation(spv::OpBitcast, {ins[i].basetypeID, castedValue, valueID}));
ops.push_back(rdcspv::Operation(spv::OpStore, {ins[i].variableID, castedValue}));
ops.push_back(rdcspv::Operation(
spv::OpBitcast, {ins[i].basetypeID.value(), castedValue.value(), valueID.value()}));
ops.push_back(rdcspv::Operation(spv::OpStore,
{ins[i].variableID.value(), castedValue.value()}));
}
}
else
@@ -887,22 +908,24 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
uint32_t location = refl.inputSignature[i].regIndex;
uint32_t ptrId = editor.MakeId();
rdcspv::Id ptrId = editor.MakeId();
// sampledimage *imgPtr = xxx_tbuffers[i];
ops.push_back(rdcspv::Operation(
spv::OpAccessChain,
{tb.pointerTypeID, ptrId, tb.variableID, idxs[refl.inputSignature[i].regIndex]}));
spv::OpAccessChain, {tb.pointerTypeID.value(), ptrId.value(), tb.variableID.value(),
idxs[refl.inputSignature[i].regIndex].value()}));
// sampledimage img = *imgPtr;
uint32_t loaded = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpLoad, {tb.imageSampledTypeID, loaded, ptrId}));
rdcspv::Id loaded = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpLoad, {tb.imageSampledTypeID.value(), loaded.value(), ptrId.value()}));
// image rawimg = imageFromSampled(img);
uint32_t rawimg = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpImage, {tb.imageTypeID, rawimg, loaded}));
rdcspv::Id rawimg = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpImage, {tb.imageTypeID.value(), rawimg.value(), loaded.value()}));
// vec4 result = texelFetch(rawimg, vtxID or instID);
uint32_t idx = vertexLookupID;
rdcspv::Id idx = vertexLookupID;
if(location < instDivisor.size())
{
@@ -927,23 +950,26 @@ 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(
rdcspv::Operation(spv::OpUDiv, {uint32ID, idx, instanceLookupID, divisor}));
rdcspv::Id divisorId = editor.AddConstantImmediate<uint32_t>(divisor);
ops.push_back(rdcspv::Operation(
spv::OpUDiv,
{uint32ID.value(), idx.value(), instanceLookupID.value(), divisorId.value()}));
}
}
if(refl.inputSignature[i].compType == CompType::Double)
{
// since doubles are packed into two uints, we need to multiply the index by two
uint32_t doubled = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpIMul, {uint32ID, doubled, idx, editor.AddConstantImmediate<uint32_t>(2)}));
rdcspv::Id doubled = editor.MakeId();
ops.push_back(
rdcspv::Operation(spv::OpIMul, {uint32ID.value(), doubled.value(), idx.value(),
editor.AddConstantImmediate<uint32_t>(2).value()}));
idx = doubled;
}
uint32_t result = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpImageFetch, {ins[i].vec4ID, result, rawimg, idx}));
rdcspv::Id result = editor.MakeId();
ops.push_back(rdcspv::Operation(spv::OpImageFetch, {ins[i].vec4ID.value(), result.value(),
rawimg.value(), idx.value()}));
if(refl.inputSignature[i].compType == CompType::Double)
{
@@ -951,27 +977,30 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
// packing. We can fetch the data unconditionally since it's harmless to read out of the
// bounds of the buffer
uint32_t nextidx = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpIAdd, {uint32ID, nextidx, idx, editor.AddConstantImmediate<uint32_t>(1)}));
uint32_t result2 = editor.MakeId();
rdcspv::Id nextidx = editor.MakeId();
ops.push_back(
rdcspv::Operation(spv::OpImageFetch, {ins[i].vec4ID, result2, rawimg, nextidx}));
rdcspv::Operation(spv::OpIAdd, {uint32ID.value(), nextidx.value(), idx.value(),
editor.AddConstantImmediate<uint32_t>(1).value()}));
uint32_t glsl450 = editor.ImportExtInst("GLSL.std.450");
rdcspv::Id result2 = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpImageFetch,
{ins[i].vec4ID.value(), result2.value(), rawimg.value(), nextidx.value()}));
uint32_t uvec2Type = editor.DeclareType(SPIRVVector(scalar<uint32_t>(), 2));
uint32_t comps[4] = {};
rdcspv::Id glsl450 = editor.ImportExtInst("GLSL.std.450");
rdcspv::Id uvec2Type = editor.DeclareType(SPIRVVector(scalar<uint32_t>(), 2));
rdcspv::Id comps[4] = {};
for(uint32_t c = 0; c < refl.inputSignature[i].compCount; c++)
{
// first extract the uvec2 we want
uint32_t packed = editor.MakeId();
rdcspv::Id packed = editor.MakeId();
// uvec2 packed = result.[xy/zw] / result2.[xy/zw];
ops.push_back(rdcspv::Operation(
spv::OpVectorShuffle, {uvec2Type, packed, result, result2, c * 2 + 0, c * 2 + 1}));
ops.push_back(rdcspv::Operation(spv::OpVectorShuffle,
{uvec2Type.value(), packed.value(), result.value(),
result2.value(), c * 2 + 0, c * 2 + 1}));
char swizzle[] = "xyzw";
@@ -981,8 +1010,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
comps[c] = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpExtInst, {
editor.DeclareType(scalar<double>()), comps[c], glsl450,
GLSLstd450PackDouble2x32, packed,
editor.DeclareType(scalar<double>()).value(), comps[c].value(),
glsl450.value(), GLSLstd450PackDouble2x32, packed.value(),
}));
}
@@ -995,10 +1024,10 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
{
result = editor.MakeId();
std::vector<uint32_t> words = {ins[i].basetypeID, result};
std::vector<uint32_t> words = {ins[i].basetypeID.value(), result.value()};
for(uint32_t c = 0; c < refl.inputSignature[i].compCount; c++)
words.push_back(comps[c]);
words.push_back(comps[c].value());
// baseTypeN value = result.xyz;
ops.push_back(rdcspv::Operation(spv::OpCompositeConstruct, words));
@@ -1008,20 +1037,22 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
{
// for one component, extract x
uint32_t swizzleIn = result;
rdcspv::Id swizzleIn = result;
result = editor.MakeId();
// baseType value = result.x;
ops.push_back(rdcspv::Operation(spv::OpCompositeExtract,
{ins[i].basetypeID, result, swizzleIn, 0}));
ops.push_back(rdcspv::Operation(
spv::OpCompositeExtract,
{ins[i].basetypeID.value(), result.value(), swizzleIn.value(), 0}));
}
else if(refl.inputSignature[i].compCount != 4)
{
// for less than 4 components, extract the sub-vector
uint32_t swizzleIn = result;
rdcspv::Id swizzleIn = result;
result = editor.MakeId();
std::vector<uint32_t> words = {ins[i].basetypeID, result, swizzleIn, swizzleIn};
std::vector<uint32_t> words = {ins[i].basetypeID.value(), result.value(),
swizzleIn.value(), swizzleIn.value()};
for(uint32_t c = 0; c < refl.inputSignature[i].compCount; c++)
words.push_back(c);
@@ -1036,84 +1067,90 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
if(patchData.inputs[i].accessChain.empty())
{
// *global = value
ops.push_back(rdcspv::Operation(spv::OpStore, {ins[i].variableID, result}));
ops.push_back(
rdcspv::Operation(spv::OpStore, {ins[i].variableID.value(), result.value()}));
}
else
{
// for composite types we need to access chain first
uint32_t subElement = editor.MakeId();
std::vector<uint32_t> words = {ins[i].privatePtrID, subElement, patchData.inputs[i].ID};
rdcspv::Id subElement = editor.MakeId();
std::vector<uint32_t> words = {ins[i].privatePtrID.value(), subElement.value(),
patchData.inputs[i].ID};
for(uint32_t accessIdx : patchData.inputs[i].accessChain)
{
if(idxs[accessIdx] == 0)
idxs[accessIdx] = editor.AddConstantImmediate<uint32_t>(accessIdx);
words.push_back(idxs[accessIdx]);
words.push_back(idxs[accessIdx].value());
}
ops.push_back(rdcspv::Operation(spv::OpAccessChain, words));
ops.push_back(rdcspv::Operation(spv::OpStore, {subElement, result}));
ops.push_back(rdcspv::Operation(spv::OpStore, {subElement.value(), result.value()}));
}
}
}
// real_main();
ops.push_back(rdcspv::Operation(spv::OpFunctionCall, {voidType, editor.MakeId(), entryID}));
ops.push_back(rdcspv::Operation(
spv::OpFunctionCall, {voidType.value(), editor.MakeId().value(), entryID.value()}));
rdcspv::Id zero = editor.AddConstantImmediate<uint32_t>(0);
for(uint32_t o = 0; o < numOutputs; o++)
{
uint32_t loaded = 0;
rdcspv::Id loaded;
// not a structure member or array child, can load directly
if(patchData.outputs[o].accessChain.empty())
{
loaded = editor.MakeId();
// type loaded = *globalvar;
ops.push_back(rdcspv::Operation(spv::OpLoad,
{outs[o].basetypeID, loaded, patchData.outputs[o].ID}));
ops.push_back(rdcspv::Operation(
spv::OpLoad, {outs[o].basetypeID.value(), loaded.value(), patchData.outputs[o].ID}));
}
else
{
uint32_t readPtr = editor.MakeId();
rdcspv::Id readPtr = editor.MakeId();
loaded = editor.MakeId();
// structure member, need to access chain first
std::vector<uint32_t> words = {outs[o].privatePtrID, readPtr, patchData.outputs[o].ID};
std::vector<uint32_t> words = {outs[o].privatePtrID.value(), readPtr.value(),
patchData.outputs[o].ID};
for(uint32_t idx : patchData.outputs[o].accessChain)
{
if(idxs[idx] == 0)
idxs[idx] = editor.AddConstantImmediate<uint32_t>(idx);
words.push_back(idxs[idx]);
words.push_back(idxs[idx].value());
}
// type *readPtr = globalvar.globalsub...;
ops.push_back(rdcspv::Operation(spv::OpAccessChain, words));
// type loaded = *readPtr;
ops.push_back(rdcspv::Operation(spv::OpLoad, {outs[o].basetypeID, loaded, readPtr}));
ops.push_back(rdcspv::Operation(
spv::OpLoad, {outs[o].basetypeID.value(), loaded.value(), readPtr.value()}));
}
// access chain the destination
// type *writePtr = outBuffer.verts[arraySlot].outputN
uint32_t writePtr = editor.MakeId();
rdcspv::Id writePtr = editor.MakeId();
ops.push_back(rdcspv::Operation(
spv::OpAccessChain,
{outs[o].uniformPtrID, writePtr, outBufferVarID, zero, arraySlotID, outs[o].constID}));
{outs[o].uniformPtrID.value(), writePtr.value(), outBufferVarID.value(), zero.value(),
arraySlotID.value(), outs[o].constID.value()}));
// *writePtr = loaded;
ops.push_back(rdcspv::Operation(spv::OpStore, {writePtr, loaded}));
ops.push_back(rdcspv::Operation(spv::OpStore, {writePtr.value(), loaded.value()}));
}
// goto killLabel;
ops.push_back(rdcspv::Operation(spv::OpBranch, {killLabel}));
ops.push_back(rdcspv::Operation(spv::OpBranch, {killLabel.value()}));
// killLabel:
ops.push_back(rdcspv::Operation(spv::OpLabel, {killLabel}));
ops.push_back(rdcspv::Operation(spv::OpLabel, {killLabel.value()}));
}
ops.push_back(rdcspv::Operation(spv::OpReturn, {}));
@@ -1132,7 +1169,7 @@ static void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData
rdcarray<SigParameter> outsig = refl.outputSignature;
std::vector<SPIRVPatchData::InterfaceAccess> outpatch = patchData.outputs;
uint32_t entryid = 0;
rdcspv::Id entryid;
for(const SPIRVEntry &entry : editor.GetEntries())
{
if(entry.name == entryName)
@@ -1147,7 +1184,7 @@ static void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData
for(rdcspv::Iter it = editor.Begin(SPIRVSection::ExecutionMode);
it < editor.End(SPIRVSection::ExecutionMode); ++it)
{
if(it.opcode() == spv::OpExecutionMode && it.word(1) == entryid &&
if(it.opcode() == spv::OpExecutionMode && rdcspv::Id::fromWord(it.word(1)) == entryid &&
it.word(2) == spv::ExecutionModeXfb)
{
hasXFB = true;