/* This file is part of the sirit project. * Copyright (c) 2018 ReinUsesLisp * This software may be used and distributed according to the terms of the GNU * Lesser General Public License version 3 or any later version. */ #include #include #include "common_types.h" #include "op.h" #include "sirit/sirit.h" #include "stream.h" namespace Sirit { template static void WriteSet(Stream& stream, const T& set) { for (const auto& item : set) { item->Write(stream); } } Module::Module(u32 version) : version(version) {} Module::~Module() = default; std::vector Module::Assemble() const { std::vector bytes; Stream stream{bytes}; stream.Write(spv::MagicNumber); stream.Write(version); stream.Write(GENERATOR_MAGIC_NUMBER); stream.Write(bound); stream.Write(static_cast(0)); for (const auto capability : capabilities) { Op op(spv::Op::OpCapability); op.Add(static_cast(capability)); op.Write(stream); } for (const auto& extension_name : extensions) { Op op(spv::Op::OpExtension); op.Add(extension_name); op.Write(stream); } if (glsl_std_450) { glsl_std_450->Write(stream); } Op memory_model_ref{spv::Op::OpMemoryModel}; memory_model_ref.Add(static_cast(addressing_model)); memory_model_ref.Add(static_cast(memory_model)); memory_model_ref.Write(stream); WriteSet(stream, entry_points); WriteSet(stream, execution_modes); WriteSet(stream, debug); WriteSet(stream, annotations); WriteSet(stream, declarations); WriteSet(stream, global_variables); WriteSet(stream, code); return bytes; } void Module::AddExtension(const std::string& extension_name) { extensions.insert(extension_name); } void Module::AddCapability(spv::Capability capability) { capabilities.insert(capability); } void Module::SetMemoryModel(spv::AddressingModel addressing_model, spv::MemoryModel memory_model) { this->addressing_model = addressing_model; this->memory_model = memory_model; } void Module::AddEntryPoint(spv::ExecutionModel execution_model, Id entry_point, const std::string& name, const std::vector& interfaces) { auto op{std::make_unique(spv::Op::OpEntryPoint)}; op->Add(static_cast(execution_model)); op->Add(entry_point); op->Add(name); op->Add(interfaces); entry_points.push_back(std::move(op)); } void Module::AddExecutionMode(Id entry_point, spv::ExecutionMode mode, const std::vector& literals) { auto op{std::make_unique(spv::Op::OpExecutionMode)}; op->Add(entry_point); op->Add(static_cast(mode)); op->Add(literals); execution_modes.push_back(std::move(op)); } Id Module::Emit(Id op) { code.push_back(op); return op; } Id Module::AddGlobalVariable(Id variable) { assert(variable); global_variables.push_back(variable); return variable; } Id Module::AddCode(std::unique_ptr op) { const auto id = op.get(); code_store.push_back(std::move(op)); return id; } Id Module::AddCode(spv::Op opcode, std::optional id) { return AddCode(std::make_unique(opcode, id)); } Id Module::AddDeclaration(std::unique_ptr op) { const auto& found{std::find_if(declarations.begin(), declarations.end(), [&op](const auto& other) { return *other == *op; })}; if (found != declarations.end()) { return found->get(); } const auto id = op.get(); declarations.push_back(std::move(op)); bound++; return id; } void Module::AddAnnotation(std::unique_ptr op) { const auto id = op.get(); annotations.push_back(std::move(op)); } Id Module::GetGLSLstd450() { if (!glsl_std_450) { glsl_std_450 = std::make_unique(spv::Op::OpExtInstImport, bound++); glsl_std_450->Add("GLSL.std.450"); } return glsl_std_450.get(); } } // namespace Sirit