aboutsummaryrefslogtreecommitdiff
path: root/externals/sirit/src/sirit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'externals/sirit/src/sirit.cpp')
-rw-r--r--externals/sirit/src/sirit.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/externals/sirit/src/sirit.cpp b/externals/sirit/src/sirit.cpp
new file mode 100644
index 0000000000..7075f23e15
--- /dev/null
+++ b/externals/sirit/src/sirit.cpp
@@ -0,0 +1,142 @@
+/* This file is part of the sirit project.
+ * Copyright (c) 2019 sirit
+ * This software may be used and distributed according to the terms of the
+ * 3-Clause BSD License
+ */
+
+#include <cassert>
+
+#include "sirit/sirit.h"
+
+#include "common_types.h"
+#include "stream.h"
+
+namespace Sirit {
+
+constexpr u32 MakeWord0(spv::Op op, size_t word_count) {
+ return static_cast<u32>(op) | static_cast<u32>(word_count) << 16;
+}
+
+Module::Module(u32 version_)
+ : version{version_}, ext_inst_imports{std::make_unique<Stream>(&bound)},
+ entry_points{std::make_unique<Stream>(&bound)},
+ execution_modes{std::make_unique<Stream>(&bound)}, debug{std::make_unique<Stream>(&bound)},
+ annotations{std::make_unique<Stream>(&bound)}, declarations{std::make_unique<Declarations>(
+ &bound)},
+ global_variables{std::make_unique<Stream>(&bound)}, code{std::make_unique<Stream>(&bound)} {}
+
+Module::~Module() = default;
+
+std::vector<u32> Module::Assemble() const {
+ std::vector<u32> words = {spv::MagicNumber, version, GENERATOR_MAGIC_NUMBER, bound + 1, 0};
+ const auto insert = [&words](std::span<const u32> input) {
+ words.insert(words.end(), input.begin(), input.end());
+ };
+
+ words.reserve(words.size() + capabilities.size() * 2);
+ for (const spv::Capability capability : capabilities) {
+ insert(std::array{
+ MakeWord0(spv::Op::OpCapability, 2),
+ static_cast<u32>(capability),
+ });
+ }
+
+ for (const std::string_view extension_name : extensions) {
+ size_t string_words = WordsInString(extension_name);
+ words.push_back(MakeWord0(spv::Op::OpExtension, string_words + 1));
+ size_t insert_index = words.size();
+ words.resize(words.size() + string_words);
+ InsertStringView(words, insert_index, extension_name);
+ }
+
+ insert(ext_inst_imports->Words());
+
+ insert(std::array{
+ MakeWord0(spv::Op::OpMemoryModel, 3),
+ static_cast<u32>(addressing_model),
+ static_cast<u32>(memory_model),
+ });
+
+ insert(entry_points->Words());
+ insert(execution_modes->Words());
+ insert(debug->Words());
+ insert(annotations->Words());
+ insert(declarations->Words());
+ insert(global_variables->Words());
+ insert(code->Words());
+
+ return words;
+}
+
+void Module::PatchDeferredPhi(const std::function<Id(std::size_t index)>& func) {
+ for (const u32 phi_index : deferred_phi_nodes) {
+ const u32 first_word = code->Value(phi_index);
+ [[maybe_unused]] const spv::Op op = static_cast<spv::Op>(first_word & 0xffff);
+ assert(op == spv::Op::OpPhi);
+ const u32 num_words = first_word >> 16;
+ const u32 num_args = (num_words - 3) / 2;
+ u32 cursor = phi_index + 3;
+ for (u32 arg = 0; arg < num_args; ++arg, cursor += 2) {
+ code->SetValue(cursor, func(arg).value);
+ }
+ }
+}
+
+void Module::AddExtension(std::string extension_name) {
+ extensions.insert(std::move(extension_name));
+}
+
+void Module::AddCapability(spv::Capability capability) {
+ capabilities.insert(capability);
+}
+
+void Module::SetMemoryModel(spv::AddressingModel addressing_model_,
+ spv::MemoryModel memory_model_) {
+ addressing_model = addressing_model_;
+ memory_model = memory_model_;
+}
+
+void Module::AddEntryPoint(spv::ExecutionModel execution_model, Id entry_point,
+ std::string_view name, std::span<const Id> interfaces) {
+ entry_points->Reserve(4 + WordsInString(name) + interfaces.size());
+ *entry_points << spv::Op::OpEntryPoint << execution_model << entry_point << name << interfaces
+ << EndOp{};
+}
+
+void Module::AddExecutionMode(Id entry_point, spv::ExecutionMode mode,
+ std::span<const Literal> literals) {
+ execution_modes->Reserve(3 + literals.size());
+ *execution_modes << spv::Op::OpExecutionMode << entry_point << mode << literals << EndOp{};
+}
+
+Id Module::AddLabel(Id label) {
+ assert(label.value != 0);
+ code->Reserve(2);
+ *code << MakeWord0(spv::Op::OpLabel, 2) << label.value;
+ return label;
+}
+
+Id Module::AddLocalVariable(Id result_type, spv::StorageClass storage_class,
+ std::optional<Id> initializer) {
+ code->Reserve(5);
+ return *code << OpId{spv::Op::OpVariable, result_type} << storage_class << initializer
+ << EndOp{};
+}
+
+Id Module::AddGlobalVariable(Id result_type, spv::StorageClass storage_class,
+ std::optional<Id> initializer) {
+ global_variables->Reserve(5);
+ return *global_variables << OpId{spv::Op::OpVariable, result_type} << storage_class
+ << initializer << EndOp{};
+}
+
+Id Module::GetGLSLstd450() {
+ if (!glsl_std_450) {
+ ext_inst_imports->Reserve(3 + 4);
+ glsl_std_450 = *ext_inst_imports << OpId{spv::Op::OpExtInstImport} << "GLSL.std.450"
+ << EndOp{};
+ }
+ return *glsl_std_450;
+}
+
+} // namespace Sirit