These Vulkan 1.1 operations can be used in place of
`OpSubgroup{All,Any,AllEqual,Ballot}KHR`, among other things.
For `OpGroupNonUniformShuffleXor`, which was already implemented, turns
out the scope argument needs to be encoded not as an immediate, but as
an id that points to a constant integer.
Before this commit sirit generated a stream of tokens that would then be
inserted to the final SPIR-V binary. This design was carried from the
initial design of manually inserting opcodes into the code. Now that
all instructions but labels are inserted when their respective function
is called, the old design can be dropped in favor of generating a valid
stream of SPIR-V opcodes.
The API for variables is broken, but adopting the new one is trivial.
Instead of calling OpVariable and then adding a global or local
variable, OpVariable was removed and global or local variables are
generated when they are called.
Avoiding duplicates is now done with an std::unordered_set instead of
using a linear search jumping through vtables.
All instructions but OpVariable and OpLabel are automatically emitted.
These functions have to call AddLocalVariable/AddGlobalVariable or
AddLabel respectively.
By taking the std::string by value in the constructor, this allows for
certain situations where copies can be elided entirely (when moving an
instance into the constructor)
e.g.
std::string var = ...
...
... = LiteralString(std::move(var)) // Or whatever other initialization
// is done.
No copy will be done in this case, the move transfers it into the
constructor, and then the move within the initializer list transfers it
into the member variable.
tl;dr: This allows the calling code to potentially construct less
std::string instances by allowing moving into the parameters themselves.