Added start of runtime, started work on support functions
This commit is contained in:
@@ -21,12 +21,12 @@ add_definitions(${LLVM_DEFINITIONS})
|
|||||||
|
|
||||||
add_executable(bluebell
|
add_executable(bluebell
|
||||||
src/bluebell.cpp src/bluebell.hpp
|
src/bluebell.cpp src/bluebell.hpp
|
||||||
src/pre-compiler.cpp src/pre-compiler.hpp src/compiler.cpp src/compiler.hpp src/spv_meta.cpp src/spv_meta.hpp)
|
src/pre-compiler.cpp src/pre-compiler.hpp src/compiler.cpp src/compiler.hpp src/spv_meta.cpp src/spv_meta.hpp src/runtime.cpp src/runtime.hpp)
|
||||||
|
|
||||||
#target_link_libraries(bluebell PkgConfig::shaderc)
|
#target_link_libraries(bluebell PkgConfig::shaderc)
|
||||||
|
|
||||||
#print(${LLVM_AVAILABLE_LIBS})
|
#print(${LLVM_AVAILABLE_LIBS})
|
||||||
llvm_map_components_to_libnames(llvm_libs core native passes nativecodegen all)
|
llvm_map_components_to_libnames(llvm_libs core native passes nativecodegen OrcJIT)
|
||||||
|
|
||||||
target_link_libraries(bluebell shaderc_shared Boost::boost Boost::log ${llvm_libs})
|
target_link_libraries(bluebell shaderc_shared Boost::boost Boost::log ${llvm_libs})
|
||||||
|
|
||||||
|
|||||||
200
src/compiler.cpp
200
src/compiler.cpp
@@ -13,6 +13,13 @@
|
|||||||
#include <llvm/Support/TargetRegistry.h>
|
#include <llvm/Support/TargetRegistry.h>
|
||||||
#include <llvm/IR/LegacyPassManager.h>
|
#include <llvm/IR/LegacyPassManager.h>
|
||||||
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
||||||
|
#include <llvm/Transforms/InstCombine/InstCombine.h>
|
||||||
|
#include <llvm/Transforms/Scalar.h>
|
||||||
|
#include <llvm/Transforms/Scalar/GVN.h>
|
||||||
|
#include <llvm/Transforms/Scalar/DCE.h>
|
||||||
|
#include <llvm/Transforms/IPO.h>
|
||||||
|
#include <llvm/Transforms/Utils.h>
|
||||||
|
#include <llvm/IR/Verifier.h>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include <spirv-tools/libspirv.hpp>
|
#include <spirv-tools/libspirv.hpp>
|
||||||
@@ -360,6 +367,7 @@ struct CompilerImpl {
|
|||||||
std::map<uint32_t, std::shared_ptr<SpirvType>> types;
|
std::map<uint32_t, std::shared_ptr<SpirvType>> types;
|
||||||
std::map<uint32_t, std::shared_ptr<Constant>> constants;
|
std::map<uint32_t, std::shared_ptr<Constant>> constants;
|
||||||
std::map<std::string, std::shared_ptr<EntryPoint>> entry_points;
|
std::map<std::string, std::shared_ptr<EntryPoint>> entry_points;
|
||||||
|
std::map<std::pair<uint32_t, spv::Decoration>, uint32_t> decorations;
|
||||||
std::map<uint32_t, Global> globals;
|
std::map<uint32_t, Global> globals;
|
||||||
std::map<uint32_t, std::shared_ptr<FunctionContext>> functions;
|
std::map<uint32_t, std::shared_ptr<FunctionContext>> functions;
|
||||||
llvm::StructType* global_type;
|
llvm::StructType* global_type;
|
||||||
@@ -524,7 +532,19 @@ public:
|
|||||||
//endregion
|
//endregion
|
||||||
//region Annotations
|
//region Annotations
|
||||||
case Op::OpDecorate: {
|
case Op::OpDecorate: {
|
||||||
// TODO: save these for bindings
|
auto deco = spv::Decoration(OP_WORD(1));
|
||||||
|
switch(deco) {
|
||||||
|
case spv::Decoration::Binding:
|
||||||
|
case spv::Decoration::Location:
|
||||||
|
case spv::Decoration::DescriptorSet:
|
||||||
|
case spv::Decoration::BuiltIn:
|
||||||
|
decorations.emplace(std::make_pair(OP_WORD(0), deco), OP_WORD(2));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// ignore all others
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Op::OpMemberDecorate: {
|
case Op::OpMemberDecorate: {
|
||||||
@@ -1055,7 +1075,97 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generate_support() {
|
||||||
|
generate_support_setup_frame();
|
||||||
|
generate_support_get_context_size();
|
||||||
|
generate_support_render_frame();
|
||||||
|
}
|
||||||
|
void generate_support_get_context_size() const {
|
||||||
|
auto ty_fn = llvm::FunctionType::get(llvm::Type::getInt32Ty(*ctx), false);
|
||||||
|
auto fn = llvm::Function::Create(
|
||||||
|
ty_fn,
|
||||||
|
llvm::Function::LinkageTypes::ExternalLinkage,
|
||||||
|
"get_context_size",
|
||||||
|
*module);
|
||||||
|
auto bb = llvm::BasicBlock::Create(*ctx, "entry", fn);
|
||||||
|
builder->SetInsertPoint(bb);
|
||||||
|
auto global_null = llvm::ConstantPointerNull::get(global_type->getPointerTo());
|
||||||
|
auto next_ptr = builder->CreateConstGEP1_32(global_type,
|
||||||
|
global_null,
|
||||||
|
1);
|
||||||
|
auto ptr_as_int = builder->CreatePtrToInt(next_ptr, ty_fn->getReturnType());
|
||||||
|
builder->CreateRet(ptr_as_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_support_setup_frame() const {
|
||||||
|
// generate type for C-based uniform block
|
||||||
|
auto ty_f = llvm::Type::getFloatTy(*ctx);
|
||||||
|
auto ty_fx3 = llvm::ArrayType::get(ty_f, 3);
|
||||||
|
auto ty_fx4 = llvm::ArrayType::get(ty_f, 4);
|
||||||
|
auto ty_fx3x4 = llvm::ArrayType::get(ty_fx3, 4);
|
||||||
|
|
||||||
|
std::vector<llvm::Type*> cuniform_members = {
|
||||||
|
ty_fx3, // iResolution
|
||||||
|
ty_f, // iTime
|
||||||
|
ty_f, // iTimeDelta
|
||||||
|
ty_f, // iFrame
|
||||||
|
ty_fx4, // iChannelTime
|
||||||
|
ty_fx4, // iMouse
|
||||||
|
ty_fx4, // iDate
|
||||||
|
ty_f, // iSampleRate
|
||||||
|
ty_fx3x4, // iChannelResolution
|
||||||
|
};
|
||||||
|
auto ty_cuniform = llvm::StructType::create(cuniform_members, "c_uniforms");
|
||||||
|
|
||||||
|
std::vector<llvm::Type*> fnArgs = {
|
||||||
|
global_type->getPointerTo(),
|
||||||
|
ty_cuniform->getPointerTo(),
|
||||||
|
};
|
||||||
|
auto ty_fn = llvm::FunctionType::get(llvm::Type::getVoidTy(*ctx), fnArgs, false);
|
||||||
|
auto fn = llvm::Function::Create(ty_fn, llvm::Function::ExternalLinkage, "setup_frame", *module);
|
||||||
|
auto bb = llvm::BasicBlock::Create(*ctx, "entry", fn);
|
||||||
|
|
||||||
|
builder->SetInsertPoint(bb);
|
||||||
|
|
||||||
|
// figure out which global to access...
|
||||||
|
int32_t uniform_idx = -1;
|
||||||
|
uint32_t deco_dset, deco_binding;
|
||||||
|
for (auto &global: globals) {
|
||||||
|
auto id = global.first;
|
||||||
|
if (get_decoration(id, spv::Decoration::DescriptorSet, deco_dset)
|
||||||
|
&& get_decoration(id, spv::Decoration::Binding, deco_binding)
|
||||||
|
&& deco_dset == 0 && deco_binding == 0) {
|
||||||
|
uniform_idx = global.second.element_no;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Found uniforms at index " << uniform_idx;
|
||||||
|
|
||||||
|
auto uniforms = builder->CreateConstGEP2_32(global_type, fn->getArg(0), 0, uniform_idx);
|
||||||
|
make_conversion_code(uniforms, fn->getArg(1));
|
||||||
|
builder->CreateRetVoid();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void generate_support_render_frame() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
bool get_decoration(uint32_t id, spv::Decoration deco, uint32_t &result) const {
|
||||||
|
auto found = decorations.find(std::make_pair(id, deco));
|
||||||
|
if (found != decorations.end()) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Found deco " << (uint32_t)deco << " for " << id;
|
||||||
|
result = found->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "No deco " << (uint32_t )deco << " for " << id;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
llvm::Value* get_value(uint32_t id, llvm::Type* type) {
|
llvm::Value* get_value(uint32_t id, llvm::Type* type) {
|
||||||
auto value_it = cur_function->values.find(id);
|
auto value_it = cur_function->values.find(id);
|
||||||
if (value_it != cur_function->values.end()) {
|
if (value_it != cur_function->values.end()) {
|
||||||
@@ -1067,6 +1177,44 @@ private:
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void make_conversion_code(llvm::Value* dst, llvm::Value* src) const {
|
||||||
|
// dst and src are both pointers
|
||||||
|
// src is always an array
|
||||||
|
auto dst_ty = dst->getType()->getPointerElementType();
|
||||||
|
auto src_ty = src->getType()->getPointerElementType();
|
||||||
|
if (dst_ty->isFloatTy()) {
|
||||||
|
builder->CreateStore(builder->CreateLoad(dst_ty, src), dst);
|
||||||
|
} else if (llvm::isa<llvm::ArrayType>(dst_ty)) {
|
||||||
|
auto n_elem = dst_ty->getArrayNumElements();
|
||||||
|
for (uint64_t i = 0; i < n_elem; i++) {
|
||||||
|
auto s1 = builder->CreateConstGEP2_32(src_ty, src, 0, i);
|
||||||
|
auto d1 = builder->CreateConstGEP2_32(dst_ty, dst, 0, i);
|
||||||
|
make_conversion_code(d1, s1);
|
||||||
|
}
|
||||||
|
} else if (llvm::isa<llvm::StructType>(dst_ty)) {
|
||||||
|
auto n_elem = dst_ty->getStructNumElements();
|
||||||
|
for (uint64_t i = 0; i < n_elem; i++) {
|
||||||
|
auto s1 = builder->CreateConstGEP2_32(src_ty, src, 0, i);
|
||||||
|
auto d1 = builder->CreateConstGEP2_32(dst_ty, dst, 0, i);
|
||||||
|
make_conversion_code(d1, s1);
|
||||||
|
}
|
||||||
|
} else if (auto dst_vty = llvm::dyn_cast<llvm::VectorType>(dst_ty)) {
|
||||||
|
auto ec = dst_vty->getElementCount().getFixedValue();
|
||||||
|
llvm::Value* result = llvm::UndefValue::get(dst_vty);
|
||||||
|
auto float_ty = llvm::Type::getFloatTy(*ctx);
|
||||||
|
// auto src_v = builder->CreateLoad(src_ty, src);
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < ec; i++) {
|
||||||
|
auto septr = builder->CreateConstGEP2_32(src_ty, src, 0, i);
|
||||||
|
auto src_el = builder->CreateLoad(float_ty, septr);
|
||||||
|
// auto src_el = builder->CreateExtractValue(src_v, i);
|
||||||
|
result = builder->CreateInsertElement(result, src_el, i);
|
||||||
|
}
|
||||||
|
builder->CreateStore(result, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void put_value(uint32_t id, llvm::Value* value) {
|
void put_value(uint32_t id, llvm::Value* value) {
|
||||||
auto sv_it = cur_function->speculative_values.find(id);
|
auto sv_it = cur_function->speculative_values.find(id);
|
||||||
if (sv_it != cur_function->speculative_values.end()) {
|
if (sv_it != cur_function->speculative_values.end()) {
|
||||||
@@ -1076,6 +1224,7 @@ private:
|
|||||||
cur_function->values[id] = value;
|
cur_function->values[id] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitLLVM() {
|
void InitLLVM() {
|
||||||
@@ -1085,11 +1234,15 @@ void InitLLVM() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Compiler::Compiler(): impl(std::make_unique<CompilerImpl>()) {
|
Compiler::Compiler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::compile(std::vector<uint32_t> &spv_module) {
|
llvm::Optional<llvm::orc::ThreadSafeModule> Compiler::compile(std::vector<uint32_t> &spv_module) {
|
||||||
|
auto impl = std::make_unique<CompilerImpl>();
|
||||||
auto ret = impl->process_module(spv_module);
|
auto ret = impl->process_module(spv_module);
|
||||||
|
impl->generate_support();
|
||||||
|
|
||||||
|
llvm::verifyModule(*impl->module);
|
||||||
|
|
||||||
// impl->module->print(llvm::outs(), nullptr, false, true);
|
// impl->module->print(llvm::outs(), nullptr, false, true);
|
||||||
|
|
||||||
@@ -1100,9 +1253,10 @@ bool Compiler::compile(std::vector<uint32_t> &spv_module) {
|
|||||||
auto target = llvm::TargetRegistry::lookupTarget(target_triple, error);
|
auto target = llvm::TargetRegistry::lookupTarget(target_triple, error);
|
||||||
if (!target) {
|
if (!target) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "Failed to load target: " << error;
|
BOOST_LOG_TRIVIAL(error) << "Failed to load target: " << error;
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dunno if this is actually necessary, but leaving it in for now.
|
||||||
llvm::TargetOptions opt;
|
llvm::TargetOptions opt;
|
||||||
auto CPU = llvm::sys::getHostCPUName();
|
auto CPU = llvm::sys::getHostCPUName();
|
||||||
auto reloc_model = llvm::Optional<llvm::Reloc::Model>();
|
auto reloc_model = llvm::Optional<llvm::Reloc::Model>();
|
||||||
@@ -1114,11 +1268,39 @@ bool Compiler::compile(std::vector<uint32_t> &spv_module) {
|
|||||||
llvm::PassManagerBuilder pass_builder;
|
llvm::PassManagerBuilder pass_builder;
|
||||||
target_machine->adjustPassManager(pass_builder);
|
target_machine->adjustPassManager(pass_builder);
|
||||||
llvm::legacy::PassManager pass;
|
llvm::legacy::PassManager pass;
|
||||||
|
pass.add(llvm::createArgumentPromotionPass());
|
||||||
|
pass.add(llvm::createPromoteMemoryToRegisterPass());
|
||||||
|
pass.add(llvm::createInstructionCombiningPass());
|
||||||
|
pass.add(llvm::createReassociatePass());
|
||||||
|
pass.add(llvm::createGVNPass());
|
||||||
|
pass.add(llvm::createCFGSimplificationPass());
|
||||||
|
pass.add(llvm::createFunctionInliningPass(3, 0, false));
|
||||||
|
pass.add(llvm::createAggressiveDCEPass());
|
||||||
|
pass.add(llvm::createLICMPass());
|
||||||
|
|
||||||
pass_builder.populateModulePassManager(pass);
|
pass_builder.populateModulePassManager(pass);
|
||||||
|
// add output to object file
|
||||||
|
std::error_code err_code;
|
||||||
|
llvm::raw_fd_ostream objfile("shader.o", err_code);
|
||||||
|
llvm::raw_fd_ostream asfile("shader.s", err_code);
|
||||||
|
if (err_code) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Failed to open object file: " << err_code.message();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
// if (target_machine->addPassesToEmitFile(pass, asfile, nullptr, llvm::CGFT_AssemblyFile)) {
|
||||||
|
// BOOST_LOG_TRIVIAL(error) << "target can't create an assembly file :-(";
|
||||||
|
// }
|
||||||
|
if (target_machine->addPassesToEmitFile(pass, objfile, nullptr, llvm::CGFT_ObjectFile)) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "target can't create an object file :-(";
|
||||||
|
}
|
||||||
pass.run(*impl->module);
|
pass.run(*impl->module);
|
||||||
|
objfile.flush();
|
||||||
|
asfile.flush();
|
||||||
|
|
||||||
// impl->module->print(llvm::outs(), nullptr, false, true);
|
// impl->module->print(llvm::outs(), nullptr, false, true);
|
||||||
return ret;
|
return {llvm::orc::ThreadSafeModule(std::move(impl->module),
|
||||||
|
std::move(impl->ctx))};
|
||||||
}
|
}
|
||||||
|
|
||||||
Compiler::~Compiler() = default;
|
Compiler::~Compiler() = default;
|
||||||
@@ -1143,13 +1325,19 @@ FunctionContext::FunctionContext(struct CompilerImpl &compiler, llvm::FunctionTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!name.empty()) {
|
||||||
|
// prefix the name
|
||||||
|
name = "sh_" + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (auto &v: compiler.constants) {
|
for (auto &v: compiler.constants) {
|
||||||
values[v.first] = v.second->get_llvm_const(*compiler.ctx);
|
values[v.first] = v.second->get_llvm_const(*compiler.ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
std::stringstream name_builder;
|
std::stringstream name_builder;
|
||||||
name_builder << "shaderfunc_" << id;
|
name_builder << "sh_func_" << id;
|
||||||
name = name_builder.str();
|
name = name_builder.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,15 +6,19 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "runtime.hpp"
|
||||||
|
#include <llvm/ExecutionEngine/Orc/ThreadSafeModule.h>
|
||||||
|
|
||||||
|
|
||||||
struct CompilerImpl;
|
struct CompilerImpl;
|
||||||
class Compiler {
|
class Compiler {
|
||||||
std::unique_ptr<CompilerImpl> impl;
|
|
||||||
public:
|
public:
|
||||||
Compiler();
|
Compiler();
|
||||||
|
|
||||||
bool compile(std::vector<uint32_t> &spv_module);
|
llvm::Optional<llvm::orc::ThreadSafeModule> compile(std::vector<uint32_t> &spv_module);
|
||||||
|
|
||||||
virtual ~Compiler();
|
virtual ~Compiler();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void InitLLVM();
|
void InitLLVM();
|
||||||
68
src/runtime.cpp
Normal file
68
src/runtime.cpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// Created by thequux on 5/25/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "runtime.hpp"
|
||||||
|
#include <llvm/IR/LegacyPassManager.h>
|
||||||
|
#include <llvm/Transforms/InstCombine/InstCombine.h>
|
||||||
|
#include <llvm/Transforms/Scalar.h>
|
||||||
|
#include <llvm/Transforms/Scalar/GVN.h>
|
||||||
|
#include <llvm/Transforms/Scalar/DCE.h>
|
||||||
|
#include <llvm/Transforms/IPO.h>
|
||||||
|
#include <llvm/Transforms/Utils.h>
|
||||||
|
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
|
||||||
|
|
||||||
|
struct RuntimeImpl {
|
||||||
|
|
||||||
|
std::unique_ptr<llvm::legacy::PassManager> passManager;
|
||||||
|
std::unique_ptr<llvm::orc::LLJIT> jit;
|
||||||
|
|
||||||
|
explicit RuntimeImpl() {
|
||||||
|
|
||||||
|
// construct the pass manager
|
||||||
|
passManager = std::make_unique<llvm::legacy::PassManager>();
|
||||||
|
passManager->add(llvm::createArgumentPromotionPass());
|
||||||
|
passManager->add(llvm::createPromoteMemoryToRegisterPass());
|
||||||
|
passManager->add(llvm::createInstructionCombiningPass());
|
||||||
|
passManager->add(llvm::createReassociatePass());
|
||||||
|
passManager->add(llvm::createGVNPass());
|
||||||
|
passManager->add(llvm::createCFGSimplificationPass());
|
||||||
|
passManager->add(llvm::createFunctionInliningPass(3, 0, false));
|
||||||
|
passManager->add(llvm::createAggressiveDCEPass());
|
||||||
|
passManager->add(llvm::createLICMPass());
|
||||||
|
// probably good for now, but need to look into further passes
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Error setModule(llvm::orc::ThreadSafeModule mod) {
|
||||||
|
mod.withModuleDo([&] (llvm::Module &mod1){
|
||||||
|
passManager->run(mod1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// construct the runtime
|
||||||
|
auto jit_builder = llvm::orc::LLJITBuilder();
|
||||||
|
jit = cantFail(jit_builder.create(), "Failed to create JIT");
|
||||||
|
|
||||||
|
if (auto err = jit->addIRModule(std::move(mod))) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
auto sym = jit->lookup("setup");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return llvm::Error::success();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Runtime::Runtime(): impl(std::make_unique<RuntimeImpl>()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Error Runtime::set_module(llvm::orc::ThreadSafeModule module) {
|
||||||
|
return impl->setModule(std::move(module));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Runtime::render_frame(const Uniforms &uniforms, float buf[32][32][3]) {
|
||||||
|
|
||||||
|
}
|
||||||
35
src/runtime.hpp
Normal file
35
src/runtime.hpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// Created by thequux on 5/25/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "compiler.hpp"
|
||||||
|
#include <llvm/IR/Module.h>
|
||||||
|
#include <llvm/IR/LLVMContext.h>
|
||||||
|
#include <llvm/ExecutionEngine/Orc/ThreadSafeModule.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct Uniforms {
|
||||||
|
float iResolution[3];
|
||||||
|
float iTime;
|
||||||
|
float iTImeDelta;
|
||||||
|
float iFrame;
|
||||||
|
float iChannelTime[4];
|
||||||
|
float iMouse[4];
|
||||||
|
float iDate[4];
|
||||||
|
float iSampleRate;
|
||||||
|
float iChannelResolution[3][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
class Runtime {
|
||||||
|
// the compiler will construct this from its internals
|
||||||
|
friend class Compiler;
|
||||||
|
std::unique_ptr<struct RuntimeImpl> impl;
|
||||||
|
protected:
|
||||||
|
Runtime();
|
||||||
|
|
||||||
|
public:
|
||||||
|
llvm::Error set_module(llvm::orc::ThreadSafeModule module);
|
||||||
|
void render_frame(const Uniforms &uniforms, float buf[32][32][3]);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user