Explorar o código

yea, compile!

Nicolas Winkler %!s(int64=5) %!d(string=hai) anos
pai
achega
dff64af9e2

+ 2 - 0
Almond.h

@@ -40,6 +40,8 @@ private:
     ViewType currentView;
     mnd::MandelViewport mandelViewSave;
     mnd::MandelGenerator* mandelGeneratorSave;
+
+    mnd::MandelGenerator* currentGenerator;
 public:
     Almond(QWidget *parent = Q_NULLPTR);
     ~Almond(void);

+ 1 - 1
Almond.pro

@@ -128,7 +128,7 @@ unix|win32: LIBS += -L$FFMPEGPATH -lswscale
 
 RESOURCES += Almond.qrc
 
-unix|win32: LIBS += -L$$PWD/libmandel/ -lmandel -lqd
+unix|win32: LIBS += -L$$PWD/libmandel/ -lmandel -lqd -lasmjit -lrt
 
 INCLUDEPATH += $$PWD/libmandel/include $$PWD/libmandel/qd-2.3.22/include
 DEPENDPATH += $$PWD/libmandel/include $$PWD/libmandel/qd-2.3.22/include

+ 4 - 2
choosegenerators.cpp

@@ -253,7 +253,7 @@ void ChooseGenerators::on_buttonBox_accepted()
         // TODO
         adGen = nullptr;
     }
-    chosenGenerator = std::move(adGen);
+    //chosenGenerator = std::move(adGen);
 }
 
 
@@ -290,10 +290,12 @@ void ChooseGenerators::on_generatorTable_cellDoubleClicked(int row, int column)
     }
 }
 
+#include <IterationCompiler.h>
 
 void ChooseGenerators::on_compile_clicked()
 {
     QString formula = this->ui->formula->text();
     mnd::IterationFormula itf{ mnd::parse(formula.toStdString()) };
-    chosenGenerator = std::make_unique<mnd::NaiveGenerator>(std::move(itf), mnd::getPrecision<double>());
+    //chosenGenerator = std::make_unique<mnd::NaiveGenerator>(std::move(itf), mnd::getPrecision<double>());
+    chosenGenerator = std::make_unique<mnd::CompiledGenerator>(mndCtxt);
 }

+ 15 - 0
libmandel/include/IterationCompiler.h

@@ -1,13 +1,28 @@
 #ifndef MANDEL_ITERATIONCOMPILER_H
 #define MANDEL_ITERATIONCOMPILER_H
 
+#include "Generators.h"
 
 namespace mnd
 {
+    struct ExecData;
+    class CompiledGenerator;
 
+    class MandelContext;
+
+    mnd::ExecData compile(mnd::MandelContext& mndCtxt);
 }
 
 
+class mnd::CompiledGenerator : public mnd::MandelGenerator
+{
+    std::unique_ptr<ExecData> execData;
+public:
+    CompiledGenerator(MandelContext& mndContext);
+    virtual ~CompiledGenerator(void);
+    virtual void generate(const MandelInfo& info, float* data);
+};
+
 
 #endif // MANDEL_ITERATIONCOMPILER_H
 

+ 127 - 17
libmandel/src/IterationCompiler.cpp

@@ -3,6 +3,65 @@
 #include <asmjit/asmjit.h>
 #include "Mandel.h"
 
+namespace mnd
+{
+    struct ExecData
+    {
+        std::unique_ptr<asmjit::JitRuntime> jitRuntime;
+        std::unique_ptr<asmjit::CodeHolder> code;
+        std::unique_ptr<asmjit::x86::Compiler> compiler;
+        void* iterationFunc;
+
+        ExecData(void) :
+            jitRuntime{ std::make_unique<asmjit::JitRuntime>() },
+            code{ std::make_unique<asmjit::CodeHolder>() },
+            compiler{ nullptr },
+            iterationFunc{ nullptr }
+        {
+            code->init(jitRuntime->codeInfo());
+            compiler = std::make_unique<asmjit::x86::Compiler>(code.get());
+        }
+
+        ExecData(ExecData&&) = default;
+        ExecData(const ExecData&) = delete;
+        ExecData& operator=(ExecData&&) = default;
+        ExecData& operator=(const ExecData&) = delete;
+
+        ~ExecData(void) = default;
+    };
+}
+
+
+using mnd::CompiledGenerator;
+
+
+
+CompiledGenerator::CompiledGenerator(mnd::MandelContext& mndContext) :
+    MandelGenerator{ 1.0e-15 },
+    execData{ std::make_unique<ExecData>(compile(mndContext)) }
+{
+}
+
+
+CompiledGenerator::~CompiledGenerator(void)
+{
+}
+
+
+void CompiledGenerator::generate(const mnd::MandelInfo& info, float* data)
+{
+    using IterFunc = int (*)(double, double, int);
+    for (int i = 0; i < info.bHeight; i++) {
+        double y = mnd::convert<double>(info.view.y + info.view.height * i / info.bHeight);
+        for (int j = 0; j < info.bWidth; j++) {
+            double x = mnd::convert<double>(info.view.x + info.view.width * j / info.bWidth);
+            IterFunc iterFunc = asmjit::ptr_as_func<IterFunc>(this->execData->iterationFunc);
+            int k = iterFunc(x, y, info.maxIter);
+            data[i * info.bWidth + j] = k;
+        }
+    }
+}
+
 using namespace asmjit;
 
 struct Visitor
@@ -10,29 +69,80 @@ struct Visitor
 
 };
 
-void compile(mnd::MandelContext& mndCtxt)
+
+namespace mnd
 {
-    JitRuntime& jitRuntime = mndCtxt.getJitRuntime();
+    mnd::ExecData compile(mnd::MandelContext& mndCtxt)
+    {
 
-    CodeHolder code;
-    code.init(jitRuntime.codeInfo());
+        mnd::ExecData ed;
+        JitRuntime& jitRuntime = *ed.jitRuntime;
+        ed.code->init(jitRuntime.codeInfo());
 
-    x86::Compiler compiler;
-    x86::Gp maxIter;
-    x86::Gp k;
-    x86::Xmm x;
-    x86::Xmm y;
-    x86::Xmm a;
-    x86::Xmm b;
-    compiler.addFunc(FuncSignatureT<int, double, double, int>(CallConv::kIdHost));
-    compiler.setArg(0, x);
-    compiler.setArg(1, x);
-    compiler.setArg(2, maxIter);
+        x86::Compiler& comp = *ed.compiler;
 
-    auto err = compiler.finalize();
+        x86::Mem sixteen = comp.newDoubleConst(ConstPool::kScopeLocal, 16.0);
 
-}
+        Label startLoop = comp.newLabel();
+        Label endLoop = comp.newLabel();
+
+        x86::Gp maxIter = comp.newInt32();
+        x86::Gp k = comp.newInt32();
+        x86::Xmm x = comp.newXmmSd();
+        x86::Xmm y = comp.newXmmSd();
+        x86::Xmm a = comp.newXmmSd();
+        x86::Xmm b = comp.newXmmSd();
+        x86::Xmm aa = comp.newXmmSd();
+        x86::Xmm bb = comp.newXmmSd();
+        x86::Xmm sumSq = comp.newXmmSd();
 
+        comp.addFunc(FuncSignatureT<int, double, double, int>(CallConv::kIdHost));
+        comp.setArg(0, x);
+        comp.setArg(1, y);
+        comp.setArg(2, maxIter);
+
+        comp.movapd(a, x);
+        comp.movapd(b, y);
+
+        comp.xor_(k, k);
+
+        comp.bind(startLoop);
+        comp.movapd(aa, a);
+        comp.mulsd(aa, a);
+        comp.movsd(bb, b);
+        comp.mulsd(bb, b);
+
+        comp.movapd(sumSq, aa);
+        comp.addsd(sumSq, bb);
+        comp.comisd(sumSq, sixteen);
+        comp.jle(endLoop);
+
+        comp.subsd(aa, bb);
+        comp.mulsd(b, a);
+        comp.addsd(b, b);
+
+        comp.addsd(aa, x);
+        comp.addsd(b, y);
+        comp.movapd(a, aa);
+
+        comp.inc(k);
+        comp.cmp(k, maxIter);
+        comp.jne(startLoop);
+        comp.bind(endLoop);
+        comp.ret(k);
+        comp.endFunc();
+        auto err = comp.finalize();
+        if (err == asmjit::kErrorOk) {
+            err = jitRuntime.add(&ed.iterationFunc, ed.code.get());
+            if (err != asmjit::kErrorOk)
+                throw "error adding function";
+        }
+        else {
+            throw "error compiling";
+        }
+        return ed;
+    }
+}
 
 
 

+ 2 - 1
libmandel/src/Mandel.cpp

@@ -103,7 +103,8 @@ std::vector<mnd::GeneratorType> MandelDevice::getSupportedTypes(void) const
 }
 
 
-MandelContext::MandelContext(void)
+MandelContext::MandelContext(void) :
+    jitRuntime{ std::make_unique<asmjit::JitRuntime>() }
 {
 
 #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)