mirror of
https://github.com/yuzu-emu/sirit.git
synced 2024-12-22 19:25:39 +00:00
f6f5913b5f
While looping here does work fine, it's mildly inefficient, particularly if the number of members being added is large, because it can result in multiple allocations over the period of the insertion, depending on how much extra memory push_back may allocate for successive elements. Instead, we can just tell the std::vector that we want to slap the whole contained sequence at the back of it with insert, which lets it allocate the whole memory block in one attempt. |
||
---|---|---|
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 to the application in the library without, limitting its functionality.
What it does for you:
- Sort declaration opcodes
- Handle types and constant duplicates
- Emit SPIR-V opcodes
What does not do for you:
- Avoid ID duplicates (emitting the same instruction twice)
- Dump code to disk
- Handle code blocks/branches
- 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{Emit(OpFunction(TypeVoid(), spv::FunctionControlMask::MaskNone, main_type))};
Emit(OpLabel());
Emit(OpReturn());
Emit(OpFunctionEnd());
AddEntryPoint(spv::ExecutionModel::Vertex, main_func, "main");
}
};
// Then...
MyModule module;
module.Generate();
std::vector<std::uint8_t> code{module.Assemble()};