mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-30 07:31:12 +00:00
Create LLVMDrawers class as the external interface to the drawers
This commit is contained in:
parent
3aea3a0bee
commit
bfa291b02f
8 changed files with 302 additions and 226 deletions
|
@ -1426,6 +1426,7 @@ set (PCH_SOURCES
|
||||||
fragglescript/t_spec.cpp
|
fragglescript/t_spec.cpp
|
||||||
fragglescript/t_variable.cpp
|
fragglescript/t_variable.cpp
|
||||||
fragglescript/t_cmd.cpp
|
fragglescript/t_cmd.cpp
|
||||||
|
r_compiler/llvmdrawers.cpp
|
||||||
r_compiler/ssa/ssa_bool.cpp
|
r_compiler/ssa/ssa_bool.cpp
|
||||||
r_compiler/ssa/ssa_float.cpp
|
r_compiler/ssa/ssa_float.cpp
|
||||||
r_compiler/ssa/ssa_float_ptr.cpp
|
r_compiler/ssa/ssa_float_ptr.cpp
|
||||||
|
|
|
@ -11,151 +11,6 @@
|
||||||
#include "r_compiler/ssa/ssa_value.h"
|
#include "r_compiler/ssa/ssa_value.h"
|
||||||
#include "r_compiler/ssa/ssa_barycentric_weight.h"
|
#include "r_compiler/ssa/ssa_barycentric_weight.h"
|
||||||
|
|
||||||
RenderProgram::RenderProgram()
|
|
||||||
{
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
install_fatal_error_handler([](void *user_data, const std::string& reason, bool gen_crash_diag) {
|
|
||||||
I_FatalError("LLVM fatal error: %s", reason.c_str());
|
|
||||||
});
|
|
||||||
|
|
||||||
InitializeNativeTarget();
|
|
||||||
InitializeNativeTargetAsmPrinter();
|
|
||||||
InitializeNativeTargetAsmParser();
|
|
||||||
|
|
||||||
std::string errorstring;
|
|
||||||
|
|
||||||
std::string targetTriple = sys::getProcessTriple();
|
|
||||||
std::string cpuName = sys::getHostCPUName();
|
|
||||||
StringMap<bool> cpuFeatures;
|
|
||||||
sys::getHostCPUFeatures(cpuFeatures);
|
|
||||||
std::string cpuFeaturesStr;
|
|
||||||
for (const auto &it : cpuFeatures)
|
|
||||||
{
|
|
||||||
if (!cpuFeaturesStr.empty())
|
|
||||||
cpuFeaturesStr.push_back(' ');
|
|
||||||
cpuFeaturesStr.push_back(it.getValue() ? '+' : '-');
|
|
||||||
cpuFeaturesStr += it.getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Printf("LLVM target triple: %s\n", targetTriple.c_str());
|
|
||||||
//Printf("LLVM CPU and features: %s, %s\n", cpuName.c_str(), cpuFeaturesStr.c_str());
|
|
||||||
|
|
||||||
const Target *target = TargetRegistry::lookupTarget(targetTriple, errorstring);
|
|
||||||
if (!target)
|
|
||||||
I_FatalError("Could not find LLVM target: %s", errorstring.c_str());
|
|
||||||
|
|
||||||
TargetOptions opt;
|
|
||||||
auto relocModel = Optional<Reloc::Model>(Reloc::Static);
|
|
||||||
TargetMachine *machine = target->createTargetMachine(targetTriple, cpuName, cpuFeaturesStr, opt, relocModel, CodeModel::Default, CodeGenOpt::Aggressive);
|
|
||||||
if (!machine)
|
|
||||||
I_FatalError("Could not create LLVM target machine");
|
|
||||||
|
|
||||||
mContext = std::make_unique<LLVMContext>();
|
|
||||||
|
|
||||||
auto moduleOwner = std::make_unique<Module>("render", context());
|
|
||||||
mModule = moduleOwner.get();
|
|
||||||
mModule->setTargetTriple(targetTriple);
|
|
||||||
mModule->setDataLayout(machine->createDataLayout());
|
|
||||||
|
|
||||||
EngineBuilder engineBuilder(std::move(moduleOwner));
|
|
||||||
engineBuilder.setErrorStr(&errorstring);
|
|
||||||
engineBuilder.setOptLevel(CodeGenOpt::Aggressive);
|
|
||||||
engineBuilder.setRelocationModel(Reloc::Static);
|
|
||||||
engineBuilder.setEngineKind(EngineKind::JIT);
|
|
||||||
mEngine.reset(engineBuilder.create(machine));
|
|
||||||
if (!mEngine)
|
|
||||||
I_FatalError("Could not create LLVM execution engine: %s", errorstring.c_str());
|
|
||||||
|
|
||||||
mModulePassManager = std::make_unique<legacy::PassManager>();
|
|
||||||
mFunctionPassManager = std::make_unique<legacy::FunctionPassManager>(mModule);
|
|
||||||
|
|
||||||
PassManagerBuilder passManagerBuilder;
|
|
||||||
passManagerBuilder.OptLevel = 3;
|
|
||||||
passManagerBuilder.SizeLevel = 0;
|
|
||||||
passManagerBuilder.Inliner = createFunctionInliningPass();
|
|
||||||
passManagerBuilder.populateModulePassManager(*mModulePassManager.get());
|
|
||||||
passManagerBuilder.populateFunctionPassManager(*mFunctionPassManager.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderProgram::~RenderProgram()
|
|
||||||
{
|
|
||||||
mEngine.reset();
|
|
||||||
mContext.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void *RenderProgram::PointerToFunction(const char *name)
|
|
||||||
{
|
|
||||||
llvm::Function *function = mModule->getFunction(name);
|
|
||||||
if (!function)
|
|
||||||
return nullptr;
|
|
||||||
return mEngine->getPointerToFunction(function);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
FixedFunction::FixedFunction()
|
|
||||||
{
|
|
||||||
CodegenDrawSpan();
|
|
||||||
mProgram.engine()->finalizeObject();
|
|
||||||
mProgram.modulePassManager()->run(*mProgram.module());
|
|
||||||
|
|
||||||
DrawSpan = mProgram.GetProcAddress<void(const RenderArgs *)>("DrawSpan");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FixedFunction::CodegenDrawSpan()
|
|
||||||
{
|
|
||||||
llvm::IRBuilder<> builder(mProgram.context());
|
|
||||||
SSAScope ssa_scope(&mProgram.context(), mProgram.module(), &builder);
|
|
||||||
|
|
||||||
SSAFunction function("DrawSpan");
|
|
||||||
function.add_parameter(GetRenderArgsStruct(mProgram.context()));
|
|
||||||
function.create_public();
|
|
||||||
|
|
||||||
DrawSpanCodegen codegen;
|
|
||||||
codegen.Generate(function.parameter(0));
|
|
||||||
|
|
||||||
builder.CreateRetVoid();
|
|
||||||
|
|
||||||
if (llvm::verifyFunction(*function.func))
|
|
||||||
I_FatalError("verifyFunction failed for " __FUNCTION__);
|
|
||||||
|
|
||||||
mProgram.functionPassManager()->run(*function.func);
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::Type *FixedFunction::GetRenderArgsStruct(llvm::LLVMContext &context)
|
|
||||||
{
|
|
||||||
std::vector<llvm::Type *> elements;
|
|
||||||
elements.push_back(llvm::Type::getInt8PtrTy(context)); // uint8_t *destorg;
|
|
||||||
elements.push_back(llvm::Type::getInt8PtrTy(context)); // const uint8_t *source;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t destpitch;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t xfrac;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t yfrac;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t xstep;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t ystep;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t x1;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t x2;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t y;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t xbits;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t ybits;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // uint32_t light;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // uint32_t srcalpha;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // uint32_t destalpha;
|
|
||||||
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t light_alpha;
|
|
||||||
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t light_red;
|
|
||||||
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t light_green;
|
|
||||||
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t light_blue;
|
|
||||||
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t fade_alpha;
|
|
||||||
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t fade_red;
|
|
||||||
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t fade_green;
|
|
||||||
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t fade_blue;
|
|
||||||
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t desaturate;
|
|
||||||
elements.push_back(llvm::Type::getInt32Ty(context)); // uint32_t flags;
|
|
||||||
return llvm::StructType::get(context, elements, false)->getPointerTo();
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void DrawSpanCodegen::Generate(SSAValue args)
|
void DrawSpanCodegen::Generate(SSAValue args)
|
||||||
{
|
{
|
||||||
destorg = args[0][0].load();
|
destorg = args[0][0].load();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "r_compiler/llvmdrawers.h"
|
||||||
#include "r_compiler/ssa/ssa_value.h"
|
#include "r_compiler/ssa/ssa_value.h"
|
||||||
#include "r_compiler/ssa/ssa_vec4f.h"
|
#include "r_compiler/ssa/ssa_vec4f.h"
|
||||||
#include "r_compiler/ssa/ssa_vec4i.h"
|
#include "r_compiler/ssa/ssa_vec4i.h"
|
||||||
|
@ -17,66 +18,6 @@
|
||||||
#include "r_compiler/ssa/ssa_barycentric_weight.h"
|
#include "r_compiler/ssa/ssa_barycentric_weight.h"
|
||||||
#include "r_compiler/llvm_include.h"
|
#include "r_compiler/llvm_include.h"
|
||||||
|
|
||||||
class RenderProgram
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RenderProgram();
|
|
||||||
~RenderProgram();
|
|
||||||
|
|
||||||
template<typename Func>
|
|
||||||
Func *GetProcAddress(const char *name) { return reinterpret_cast<Func*>(PointerToFunction(name)); }
|
|
||||||
|
|
||||||
llvm::LLVMContext &context() { return *mContext; }
|
|
||||||
llvm::Module *module() { return mModule; }
|
|
||||||
llvm::ExecutionEngine *engine() { return mEngine.get(); }
|
|
||||||
llvm::legacy::PassManager *modulePassManager() { return mModulePassManager.get(); }
|
|
||||||
llvm::legacy::FunctionPassManager *functionPassManager() { return mFunctionPassManager.get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void *PointerToFunction(const char *name);
|
|
||||||
|
|
||||||
std::unique_ptr<llvm::LLVMContext> mContext;
|
|
||||||
llvm::Module *mModule;
|
|
||||||
std::unique_ptr<llvm::ExecutionEngine> mEngine;
|
|
||||||
std::unique_ptr<llvm::legacy::PassManager> mModulePassManager;
|
|
||||||
std::unique_ptr<llvm::legacy::FunctionPassManager> mFunctionPassManager;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RenderArgs
|
|
||||||
{
|
|
||||||
uint32_t *destorg;
|
|
||||||
const uint32_t *source;
|
|
||||||
int32_t destpitch;
|
|
||||||
int32_t xfrac;
|
|
||||||
int32_t yfrac;
|
|
||||||
int32_t xstep;
|
|
||||||
int32_t ystep;
|
|
||||||
int32_t x1;
|
|
||||||
int32_t x2;
|
|
||||||
int32_t y;
|
|
||||||
int32_t xbits;
|
|
||||||
int32_t ybits;
|
|
||||||
uint32_t light;
|
|
||||||
uint32_t srcalpha;
|
|
||||||
uint32_t destalpha;
|
|
||||||
|
|
||||||
uint16_t light_alpha;
|
|
||||||
uint16_t light_red;
|
|
||||||
uint16_t light_green;
|
|
||||||
uint16_t light_blue;
|
|
||||||
uint16_t fade_alpha;
|
|
||||||
uint16_t fade_red;
|
|
||||||
uint16_t fade_green;
|
|
||||||
uint16_t fade_blue;
|
|
||||||
uint16_t desaturate;
|
|
||||||
uint32_t flags;
|
|
||||||
enum Flags
|
|
||||||
{
|
|
||||||
simple_shade = 1,
|
|
||||||
nearest_filter = 2
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
class SSAShadeConstants
|
class SSAShadeConstants
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -144,18 +85,3 @@ private:
|
||||||
SSABool is_nearest_filter;
|
SSABool is_nearest_filter;
|
||||||
SSAShadeConstants shade_constants;
|
SSAShadeConstants shade_constants;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FixedFunction
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FixedFunction();
|
|
||||||
|
|
||||||
void(*DrawSpan)(const RenderArgs *) = nullptr;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void CodegenDrawSpan();
|
|
||||||
|
|
||||||
static llvm::Type *GetRenderArgsStruct(llvm::LLVMContext &context);
|
|
||||||
|
|
||||||
RenderProgram mProgram;
|
|
||||||
};
|
|
||||||
|
|
232
src/r_compiler/llvmdrawers.cpp
Normal file
232
src/r_compiler/llvmdrawers.cpp
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
|
||||||
|
#include "i_system.h"
|
||||||
|
#include "r_compiler/fixedfunction/fixedfunction.h"
|
||||||
|
#include "r_compiler/ssa/ssa_function.h"
|
||||||
|
#include "r_compiler/ssa/ssa_scope.h"
|
||||||
|
#include "r_compiler/ssa/ssa_for_block.h"
|
||||||
|
#include "r_compiler/ssa/ssa_if_block.h"
|
||||||
|
#include "r_compiler/ssa/ssa_stack.h"
|
||||||
|
#include "r_compiler/ssa/ssa_function.h"
|
||||||
|
#include "r_compiler/ssa/ssa_struct_type.h"
|
||||||
|
#include "r_compiler/ssa/ssa_value.h"
|
||||||
|
#include "r_compiler/ssa/ssa_barycentric_weight.h"
|
||||||
|
|
||||||
|
class LLVMProgram
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLVMProgram();
|
||||||
|
~LLVMProgram();
|
||||||
|
|
||||||
|
void StopLogFatalErrors();
|
||||||
|
|
||||||
|
template<typename Func>
|
||||||
|
Func *GetProcAddress(const char *name) { return reinterpret_cast<Func*>(PointerToFunction(name)); }
|
||||||
|
|
||||||
|
llvm::LLVMContext &context() { return *mContext; }
|
||||||
|
llvm::Module *module() { return mModule; }
|
||||||
|
llvm::ExecutionEngine *engine() { return mEngine.get(); }
|
||||||
|
llvm::legacy::PassManager *modulePassManager() { return mModulePassManager.get(); }
|
||||||
|
llvm::legacy::FunctionPassManager *functionPassManager() { return mFunctionPassManager.get(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *PointerToFunction(const char *name);
|
||||||
|
|
||||||
|
std::unique_ptr<llvm::LLVMContext> mContext;
|
||||||
|
llvm::Module *mModule;
|
||||||
|
std::unique_ptr<llvm::ExecutionEngine> mEngine;
|
||||||
|
std::unique_ptr<llvm::legacy::PassManager> mModulePassManager;
|
||||||
|
std::unique_ptr<llvm::legacy::FunctionPassManager> mFunctionPassManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LLVMDrawersImpl : public LLVMDrawers
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLVMDrawersImpl();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CodegenDrawSpan();
|
||||||
|
static llvm::Type *GetRenderArgsStruct(llvm::LLVMContext &context);
|
||||||
|
|
||||||
|
LLVMProgram mProgram;
|
||||||
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LLVMDrawers *LLVMDrawers::Singleton = nullptr;
|
||||||
|
|
||||||
|
void LLVMDrawers::Create()
|
||||||
|
{
|
||||||
|
if (!Singleton)
|
||||||
|
Singleton = new LLVMDrawersImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLVMDrawers::Destroy()
|
||||||
|
{
|
||||||
|
delete Singleton;
|
||||||
|
Singleton = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMDrawers *LLVMDrawers::Instance()
|
||||||
|
{
|
||||||
|
return Singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LLVMDrawersImpl::LLVMDrawersImpl()
|
||||||
|
{
|
||||||
|
CodegenDrawSpan();
|
||||||
|
mProgram.engine()->finalizeObject();
|
||||||
|
mProgram.modulePassManager()->run(*mProgram.module());
|
||||||
|
|
||||||
|
DrawSpan = mProgram.GetProcAddress<void(const RenderArgs *)>("DrawSpan");
|
||||||
|
|
||||||
|
mProgram.StopLogFatalErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLVMDrawersImpl::CodegenDrawSpan()
|
||||||
|
{
|
||||||
|
llvm::IRBuilder<> builder(mProgram.context());
|
||||||
|
SSAScope ssa_scope(&mProgram.context(), mProgram.module(), &builder);
|
||||||
|
|
||||||
|
SSAFunction function("DrawSpan");
|
||||||
|
function.add_parameter(GetRenderArgsStruct(mProgram.context()));
|
||||||
|
function.create_public();
|
||||||
|
|
||||||
|
DrawSpanCodegen codegen;
|
||||||
|
codegen.Generate(function.parameter(0));
|
||||||
|
|
||||||
|
builder.CreateRetVoid();
|
||||||
|
|
||||||
|
if (llvm::verifyFunction(*function.func))
|
||||||
|
I_FatalError("verifyFunction failed for " __FUNCTION__);
|
||||||
|
|
||||||
|
mProgram.functionPassManager()->run(*function.func);
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Type *LLVMDrawersImpl::GetRenderArgsStruct(llvm::LLVMContext &context)
|
||||||
|
{
|
||||||
|
std::vector<llvm::Type *> elements;
|
||||||
|
elements.push_back(llvm::Type::getInt8PtrTy(context)); // uint8_t *destorg;
|
||||||
|
elements.push_back(llvm::Type::getInt8PtrTy(context)); // const uint8_t *source;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t destpitch;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t xfrac;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t yfrac;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t xstep;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t ystep;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t x1;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t x2;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t y;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t xbits;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // int32_t ybits;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // uint32_t light;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // uint32_t srcalpha;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // uint32_t destalpha;
|
||||||
|
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t light_alpha;
|
||||||
|
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t light_red;
|
||||||
|
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t light_green;
|
||||||
|
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t light_blue;
|
||||||
|
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t fade_alpha;
|
||||||
|
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t fade_red;
|
||||||
|
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t fade_green;
|
||||||
|
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t fade_blue;
|
||||||
|
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t desaturate;
|
||||||
|
elements.push_back(llvm::Type::getInt32Ty(context)); // uint32_t flags;
|
||||||
|
return llvm::StructType::get(context, elements, false)->getPointerTo();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace { static bool LogFatalErrors = false; }
|
||||||
|
|
||||||
|
LLVMProgram::LLVMProgram()
|
||||||
|
{
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
// We have to extra careful about this because both LLVM and ZDoom made
|
||||||
|
// the very unwise decision to hook atexit. To top it off, LLVM decided
|
||||||
|
// to log something in the atexit handler..
|
||||||
|
LogFatalErrors = true;
|
||||||
|
|
||||||
|
install_fatal_error_handler([](void *user_data, const std::string& reason, bool gen_crash_diag) {
|
||||||
|
if (LogFatalErrors)
|
||||||
|
I_FatalError("LLVM fatal error: %s", reason.c_str());
|
||||||
|
});
|
||||||
|
|
||||||
|
InitializeNativeTarget();
|
||||||
|
InitializeNativeTargetAsmPrinter();
|
||||||
|
InitializeNativeTargetAsmParser();
|
||||||
|
|
||||||
|
std::string errorstring;
|
||||||
|
|
||||||
|
std::string targetTriple = sys::getProcessTriple();
|
||||||
|
std::string cpuName = sys::getHostCPUName();
|
||||||
|
StringMap<bool> cpuFeatures;
|
||||||
|
sys::getHostCPUFeatures(cpuFeatures);
|
||||||
|
std::string cpuFeaturesStr;
|
||||||
|
for (const auto &it : cpuFeatures)
|
||||||
|
{
|
||||||
|
if (!cpuFeaturesStr.empty())
|
||||||
|
cpuFeaturesStr.push_back(' ');
|
||||||
|
cpuFeaturesStr.push_back(it.getValue() ? '+' : '-');
|
||||||
|
cpuFeaturesStr += it.getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Printf("LLVM target triple: %s\n", targetTriple.c_str());
|
||||||
|
//Printf("LLVM CPU and features: %s, %s\n", cpuName.c_str(), cpuFeaturesStr.c_str());
|
||||||
|
|
||||||
|
const Target *target = TargetRegistry::lookupTarget(targetTriple, errorstring);
|
||||||
|
if (!target)
|
||||||
|
I_FatalError("Could not find LLVM target: %s", errorstring.c_str());
|
||||||
|
|
||||||
|
TargetOptions opt;
|
||||||
|
auto relocModel = Optional<Reloc::Model>(Reloc::Static);
|
||||||
|
TargetMachine *machine = target->createTargetMachine(targetTriple, cpuName, cpuFeaturesStr, opt, relocModel, CodeModel::Default, CodeGenOpt::Aggressive);
|
||||||
|
if (!machine)
|
||||||
|
I_FatalError("Could not create LLVM target machine");
|
||||||
|
|
||||||
|
mContext = std::make_unique<LLVMContext>();
|
||||||
|
|
||||||
|
auto moduleOwner = std::make_unique<Module>("render", context());
|
||||||
|
mModule = moduleOwner.get();
|
||||||
|
mModule->setTargetTriple(targetTriple);
|
||||||
|
mModule->setDataLayout(machine->createDataLayout());
|
||||||
|
|
||||||
|
EngineBuilder engineBuilder(std::move(moduleOwner));
|
||||||
|
engineBuilder.setErrorStr(&errorstring);
|
||||||
|
engineBuilder.setOptLevel(CodeGenOpt::Aggressive);
|
||||||
|
engineBuilder.setRelocationModel(Reloc::Static);
|
||||||
|
engineBuilder.setEngineKind(EngineKind::JIT);
|
||||||
|
mEngine.reset(engineBuilder.create(machine));
|
||||||
|
if (!mEngine)
|
||||||
|
I_FatalError("Could not create LLVM execution engine: %s", errorstring.c_str());
|
||||||
|
|
||||||
|
mModulePassManager = std::make_unique<legacy::PassManager>();
|
||||||
|
mFunctionPassManager = std::make_unique<legacy::FunctionPassManager>(mModule);
|
||||||
|
|
||||||
|
PassManagerBuilder passManagerBuilder;
|
||||||
|
passManagerBuilder.OptLevel = 3;
|
||||||
|
passManagerBuilder.SizeLevel = 0;
|
||||||
|
passManagerBuilder.Inliner = createFunctionInliningPass();
|
||||||
|
passManagerBuilder.populateModulePassManager(*mModulePassManager.get());
|
||||||
|
passManagerBuilder.populateFunctionPassManager(*mFunctionPassManager.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMProgram::~LLVMProgram()
|
||||||
|
{
|
||||||
|
mEngine.reset();
|
||||||
|
mContext.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void *LLVMProgram::PointerToFunction(const char *name)
|
||||||
|
{
|
||||||
|
llvm::Function *function = mModule->getFunction(name);
|
||||||
|
if (!function)
|
||||||
|
return nullptr;
|
||||||
|
return mEngine->getPointerToFunction(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLVMProgram::StopLogFatalErrors()
|
||||||
|
{
|
||||||
|
LogFatalErrors = false;
|
||||||
|
}
|
52
src/r_compiler/llvmdrawers.h
Normal file
52
src/r_compiler/llvmdrawers.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct RenderArgs
|
||||||
|
{
|
||||||
|
uint32_t *destorg;
|
||||||
|
const uint32_t *source;
|
||||||
|
int32_t destpitch;
|
||||||
|
int32_t xfrac;
|
||||||
|
int32_t yfrac;
|
||||||
|
int32_t xstep;
|
||||||
|
int32_t ystep;
|
||||||
|
int32_t x1;
|
||||||
|
int32_t x2;
|
||||||
|
int32_t y;
|
||||||
|
int32_t xbits;
|
||||||
|
int32_t ybits;
|
||||||
|
uint32_t light;
|
||||||
|
uint32_t srcalpha;
|
||||||
|
uint32_t destalpha;
|
||||||
|
|
||||||
|
uint16_t light_alpha;
|
||||||
|
uint16_t light_red;
|
||||||
|
uint16_t light_green;
|
||||||
|
uint16_t light_blue;
|
||||||
|
uint16_t fade_alpha;
|
||||||
|
uint16_t fade_red;
|
||||||
|
uint16_t fade_green;
|
||||||
|
uint16_t fade_blue;
|
||||||
|
uint16_t desaturate;
|
||||||
|
uint32_t flags;
|
||||||
|
enum Flags
|
||||||
|
{
|
||||||
|
simple_shade = 1,
|
||||||
|
nearest_filter = 2
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class LLVMDrawers
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~LLVMDrawers() { }
|
||||||
|
|
||||||
|
static void Create();
|
||||||
|
static void Destroy();
|
||||||
|
static LLVMDrawers *Instance();
|
||||||
|
|
||||||
|
void(*DrawSpan)(const RenderArgs *) = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static LLVMDrawers *Singleton;
|
||||||
|
};
|
|
@ -38,7 +38,7 @@
|
||||||
#include "r_data/colormaps.h"
|
#include "r_data/colormaps.h"
|
||||||
#include "r_plane.h"
|
#include "r_plane.h"
|
||||||
#include "r_draw_rgba.h"
|
#include "r_draw_rgba.h"
|
||||||
#include "r_compiler/fixedfunction/fixedfunction.h"
|
#include "r_compiler/llvmdrawers.h"
|
||||||
|
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
|
@ -303,7 +303,6 @@ void DrawerCommandQueue::StopThreads()
|
||||||
class DrawSpanLLVMCommand : public DrawerCommand
|
class DrawSpanLLVMCommand : public DrawerCommand
|
||||||
{
|
{
|
||||||
RenderArgs args;
|
RenderArgs args;
|
||||||
FixedFunction *_ff;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DrawSpanLLVMCommand()
|
DrawSpanLLVMCommand()
|
||||||
|
@ -337,16 +336,13 @@ public:
|
||||||
args.flags |= RenderArgs::simple_shade;
|
args.flags |= RenderArgs::simple_shade;
|
||||||
if (!SampleBgra::span_sampler_setup(args.source, args.xbits, args.ybits, args.xstep, args.ystep, ds_source_mipmapped))
|
if (!SampleBgra::span_sampler_setup(args.source, args.xbits, args.ybits, args.xstep, args.ystep, ds_source_mipmapped))
|
||||||
args.flags |= RenderArgs::nearest_filter;
|
args.flags |= RenderArgs::nearest_filter;
|
||||||
|
|
||||||
static FixedFunction ff;
|
|
||||||
_ff = &ff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute(DrawerThread *thread) override
|
void Execute(DrawerThread *thread) override
|
||||||
{
|
{
|
||||||
if (thread->skipped_by_thread(args.y))
|
if (thread->skipped_by_thread(args.y))
|
||||||
return;
|
return;
|
||||||
_ff->DrawSpan(&args);
|
LLVMDrawers::Instance()->DrawSpan(&args);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "textures/textures.h"
|
#include "textures/textures.h"
|
||||||
#include "r_data/voxels.h"
|
#include "r_data/voxels.h"
|
||||||
#include "r_draw_rgba.h"
|
#include "r_draw_rgba.h"
|
||||||
|
#include "r_compiler/llvmdrawers.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, r_shadercolormaps)
|
EXTERN_CVAR(Bool, r_shadercolormaps)
|
||||||
|
|
||||||
|
@ -51,6 +52,16 @@ void R_SetupColormap(player_t *);
|
||||||
void R_SetupFreelook();
|
void R_SetupFreelook();
|
||||||
void R_InitRenderer();
|
void R_InitRenderer();
|
||||||
|
|
||||||
|
FSoftwareRenderer::FSoftwareRenderer()
|
||||||
|
{
|
||||||
|
LLVMDrawers::Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
FSoftwareRenderer::~FSoftwareRenderer()
|
||||||
|
{
|
||||||
|
LLVMDrawers::Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// DCanvas :: Init
|
// DCanvas :: Init
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
|
|
||||||
struct FSoftwareRenderer : public FRenderer
|
struct FSoftwareRenderer : public FRenderer
|
||||||
{
|
{
|
||||||
|
FSoftwareRenderer();
|
||||||
|
~FSoftwareRenderer();
|
||||||
|
|
||||||
// Can be overridden so that the colormaps for sector color/fade won't be built.
|
// Can be overridden so that the colormaps for sector color/fade won't be built.
|
||||||
virtual bool UsesColormap() const override;
|
virtual bool UsesColormap() const override;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue