mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-12 16:55:49 +00:00
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:
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user