Commit c25b8077 by Chris Forbes

Add support for SPIRV decorations

This works in a single pass, and supports both toplevel and member decorations. Includes support for 5 new opcodes: - OpDecorate introduces a single decoration for a toplevel id. - OpMemberDecorate introduces a single decoration for a <id, memberIndex> pair. - OpDecorationGroup introduces a new value category which has no representation downstream at all. This is safely implemented by doing nothing at all [we don't need to be able to introspect later]. - OpGroupDecorate applies all decorations in a decoration group to each of a list of other ids. - OpGroupMemberDecorate applies all decorations in a decoration group to each of a list of members (<id>, memberIndex pairs). Bug: b/120799499 Change-Id: Iaea970b23348e70d57ddb96a4df0726cfb511e03 Reviewed-on: https://swiftshader-review.googlesource.com/c/23174Tested-by: 's avatarChris Forbes <chrisforbes@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent 48d47a49
......@@ -37,6 +37,60 @@ namespace sw
ProcessExecutionMode(insn);
break;
case spv::OpDecorate:
{
auto targetId = insn.word(1);
decorations[targetId].Apply(
static_cast<spv::Decoration>(insn.word(2)),
insn.wordCount() > 3 ? insn.word(3) : 0);
break;
}
case spv::OpMemberDecorate:
{
auto targetId = insn.word(1);
auto memberIndex = insn.word(2);
auto &d = memberDecorations[targetId];
if (memberIndex >= d.size())
d.resize(memberIndex + 1); // on demand; exact size would require another pass...
d[memberIndex].Apply(
static_cast<spv::Decoration>(insn.word(3)),
insn.wordCount() > 4 ? insn.word(4) : 0);
break;
}
case spv::OpDecorationGroup:
// Nothing to do here. We don't need to record the definition of the group; we'll just have
// the bundle of decorations float around. If we were to ever walk the decorations directly,
// we might think about introducing this as a real Object.
break;
case spv::OpGroupDecorate:
{
auto const &srcDecorations = decorations[insn.word(1)];
for (auto i = 2u; i < insn.wordCount(); i++)
{
// remaining operands are targets to apply the group to.
decorations[insn.word(i)].Apply(srcDecorations);
}
break;
}
case spv::OpGroupMemberDecorate:
{
auto const &srcDecorations = decorations[insn.word(1)];
for (auto i = 2u; i < insn.wordCount(); i += 2)
{
// remaining operands are pairs of <id>, literal for members to apply to.
auto &d = memberDecorations[insn.word(i)];
auto memberIndex = insn.word(i + 1);
if (memberIndex >= d.size())
d.resize(memberIndex + 1); // on demand resize, see above...
d[memberIndex].Apply(srcDecorations);
}
break;
}
case spv::OpTypeVoid:
case spv::OpTypeBool:
case spv::OpTypeInt:
......@@ -73,6 +127,17 @@ namespace sw
object.definition = insn;
object.storageClass = storageClass;
object.sizeInComponents = defs[typeId].sizeInComponents;
// Register builtins
auto &d = decorations[resultId];
if (d.HasBuiltIn && storageClass == spv::StorageClassInput)
{
inputBuiltins[d.BuiltIn] = resultId;
}
if (d.HasBuiltIn && storageClass == spv::StorageClassOutput)
{
outputBuiltins[d.BuiltIn] = resultId;
}
break;
}
......@@ -170,4 +235,69 @@ namespace sw
UNIMPLEMENTED("Only types are supported");
}
}
}
\ No newline at end of file
void SpirvShader::Decorations::Apply(spv::Decoration decoration, uint32_t arg)
{
switch (decoration)
{
case spv::DecorationLocation:
HasLocation = true;
Location = static_cast<int32_t>(arg);
break;
case spv::DecorationComponent:
HasComponent = true;
Component = arg;
break;
case spv::DecorationBuiltIn:
HasBuiltIn = true;
BuiltIn = static_cast<spv::BuiltIn>(arg);
break;
case spv::DecorationFlat:
Flat = true;
break;
case spv::DecorationNoPerspective:
Noperspective = true;
break;
case spv::DecorationCentroid:
Centroid = true;
break;
case spv::DecorationBlock:
Block = true;
break;
case spv::DecorationBufferBlock:
BufferBlock = true;
break;
default:
// Intentionally partial, there are many decorations we just don't care about.
break;
}
}
void SpirvShader::Decorations::Apply(const sw::SpirvShader::Decorations &src)
{
// Apply a decoration group to this set of decorations
if (src.HasBuiltIn)
{
HasBuiltIn = true;
BuiltIn = src.BuiltIn;
}
if (src.HasLocation)
{
HasLocation = true;
Location = src.Location;
}
if (src.HasComponent)
{
HasComponent = true;
Component = src.Component;
}
Flat |= src.Flat;
Noperspective |= src.Noperspective;
Centroid |= src.Centroid;
Block |= src.Block;
BufferBlock |= src.BufferBlock;
}
}
......@@ -143,6 +143,7 @@ namespace sw
ATTRIBTYPE_FLOAT,
ATTRIBTYPE_INT,
ATTRIBTYPE_UINT,
ATTRIBTYPE_UNUSED,
ATTRIBTYPE_LAST = ATTRIBTYPE_UINT
};
......@@ -152,6 +153,38 @@ namespace sw
return inputBuiltins.find(b) != inputBuiltins.end();
}
struct Decorations
{
int32_t Location;
int32_t Component;
spv::BuiltIn BuiltIn;
bool HasLocation : 1;
bool HasComponent : 1;
bool HasBuiltIn : 1;
bool Flat : 1;
bool Centroid : 1;
bool Noperspective : 1;
bool Block : 1;
bool BufferBlock : 1;
Decorations()
: Location{-1}, Component{0}, BuiltIn{}, HasLocation{false}, HasComponent{false}, HasBuiltIn{false},
Flat{false},
Centroid{false}, Noperspective{false}, Block{false},
BufferBlock{false}
{
}
Decorations(Decorations const &) = default;
void Apply(Decorations const &src);
void Apply(spv::Decoration decoration, uint32_t arg);
};
std::unordered_map<uint32_t, Decorations> decorations;
std::unordered_map<uint32_t, std::vector<Decorations>> memberDecorations;
private:
const int serialID;
static volatile int serialCounter;
......@@ -166,4 +199,4 @@ namespace sw
};
}
#endif // sw_SpirvShader_hpp
\ No newline at end of file
#endif // sw_SpirvShader_hpp
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment