mirror of
https://github.com/shadps4-emu/sirit.git
synced 2024-11-26 20:50:35 +00:00
A runtime SPIR-V assembler
0b9ee36247
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. |
||
---|---|---|
externals | ||
include/sirit | ||
src | ||
tests | ||
.clang-format | ||
.gitignore | ||
.gitmodules | ||
CMakeLists.txt | ||
LICENSE.txt | ||
README.md |
Sirit
A runtime SPIR-V assembler. It aims to ease dynamic SPIR-V code generation
without calling external applications (like Khronos' spirv-as
)
Its design aims to move code that does not belong in the application to the library, without limiting its functionality.
What Sirit does for you:
- Sort declaration opcodes
- Handle types and constant duplicates
- Emit SPIR-V opcodes
What Sirit won't do for you:
- Avoid ID duplicates (e.g. emitting the same label twice)
- Dump code to disk
- Handle control flow
- Compile from a higher level language
It's in early stages of development, many instructions are missing since they are written manually instead of being generated from a file.
Example
class MyModule : public Sirit::Module {
public:
MyModule() {}
~MyModule() = default;
void Generate() {
AddCapability(spv::Capability::Shader);
SetMemoryModel(spv::AddressingModel::Logical, spv::MemoryModel::GLSL450);
auto main_type{TypeFunction(TypeVoid())};
auto main_func{OpFunction(TypeVoid(), spv::FunctionControlMask::MaskNone, main_type)};
AddLabel(OpLabel());
OpReturn();
OpFunctionEnd();
AddEntryPoint(spv::ExecutionModel::Vertex, main_func, "main");
}
};
// Then...
MyModule module;
module.Generate();
std::vector<std::uint32_t> code{module.Assemble()};