mirror of
https://github.com/yuzu-emu/sirit
synced 2024-11-22 06:43:37 +00:00
No description
13396c96ac
Suppose you try to call, say, `AddEntryPoint` with a `std::vector<Id>` as the `interfaces` argument - something that yuzu does. This can match the non-variadic overload, since `std::vector<Id>` is implicitly convertible to the argument type `std::span<const Id>`. But it can also match the variadic overload, and the compiler sees that as a 'better' match because it doesn't require implicit conversion. So it picks that overload and promptly errors out trying to convert `std::vector<Id>` to `Id`. To make the compiler pick the right overload, you would have to explicitly convert to `std::span<const Id>`, which is annoyingly verbose. To avoid this, add `requires` clauses to all variadic convenience overloads, requiring each of the variadic arguments to be convertible to the corresponding element type. If you pass a vector/array/etc., this rules out the variadic overload as a candidate, and the call goes through with the non-variadic overload. Also, use slightly different code to forward to the non-variadic overloads, that works even if the arguments need to be converted. Note: I used this in a WIP branch updating yuzu to the latest version of sirit. Note 2: I tried to run clang-format on this, but it mangled the requires clauses pretty horribly, so I didn't accept its changes. I googled it, and apparently clang-format doesn't properly support concepts yet... |
||
---|---|---|
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()};