Bläddra i källkod

adjusting background tasks and compileable for x86

Nicolas Winkler 5 år sedan
förälder
incheckning
332f2c1094

+ 13 - 1
Almond.cpp

@@ -33,6 +33,7 @@ Almond::Almond(QWidget* parent) :
     ui.maxIterations->setValidator(new QIntValidator(1, 1000000000, this));
     ui.backgroundProgress->setVisible(false);
 
+    backgroundTasks.setMaxThreadCount(1);
     this->setWindowIcon(QIcon(":/icons/icon"));
     //ui.verticalLayout_left->addWidget(new MyGLWidget(ui.centralWidget));
     //mw->show();
@@ -57,8 +58,19 @@ void Almond::submitBackgroundTask(BackgroundTask* task)
 }
 
 
-void Almond::backgroundTaskFinished(bool succ)
+void Almond::backgroundTaskFinished(bool succ, QString message)
 {
+    if (succ) {
+        QMessageBox info = QMessageBox(QMessageBox::Icon::Information, "Task Finished", message);
+        //info->setParent(this);
+        emit info.exec();
+    }
+    else {
+        QMessageBox info = QMessageBox(QMessageBox::Icon::Critical, "Task Failed", message);
+        //info->setParent(this);
+        emit info.exec();
+    }
+
     ui.backgroundProgress->setVisible(false);
     ui.backgroundProgress->setFormat("");
 }

+ 1 - 1
Almond.h

@@ -73,7 +73,7 @@ private slots:
 
     void on_chooseGenerator_clicked();
 
-    void backgroundTaskFinished(bool);
+    void backgroundTaskFinished(bool, QString message);
     void backgroundTaskProgress(float percentage);
 
     void pointSelected(mnd::Real x, mnd::Real y);

+ 21 - 16
BackgroundTask.cpp

@@ -1,5 +1,4 @@
 #include "BackgroundTask.h"
-#include <QMessageBox>
 
 BackgroundTask::BackgroundTask(const std::string& shortDescription) :
     shortDescription{ shortDescription }
@@ -8,7 +7,7 @@ BackgroundTask::BackgroundTask(const std::string& shortDescription) :
 
 
 ImageExportTask::ImageExportTask(const alm::ImageExportInfo& iei) :
-    BackgroundTask{ "exporting image" },
+    BackgroundTask{ "Exporting Image" },
     iei{ iei }
 {
 }
@@ -16,15 +15,20 @@ ImageExportTask::ImageExportTask(const alm::ImageExportInfo& iei) :
 
 void ImageExportTask::run(void)
 {
-    alm::exportPng(iei, [this](float percentage) {
-        emit progress(percentage);
-    });
-    emit finished(true);
+    try {
+        alm::exportPng(iei, [this](float percentage) {
+            emit progress(percentage);
+        });
+        emit finished(true, "Image successfully exported.");
+    }
+    catch (...) {
+        emit finished(false, "Error occurred during image export.");
+    }
 }
 
 
 VideoExportTask::VideoExportTask(MandelVideoGenerator mvg, mnd::MandelGenerator& generator) :
-    BackgroundTask{ "exporting video" },
+    BackgroundTask{ "Exporting Video" },
     mvg{ std::move(mvg) },
     generator{ generator }
 {
@@ -33,14 +37,15 @@ VideoExportTask::VideoExportTask(MandelVideoGenerator mvg, mnd::MandelGenerator&
 
 void VideoExportTask::run(void)
 {
-
-    mvg.addProgressCallback([this](const MandelVideoProgressInfo& mvpi) {
-        emit progress(0);
-    });
-    mvg.generate(generator);
-    emit finished(true);
-    QMessageBox* msgBox = new QMessageBox;
-    msgBox->setText("Video successfully exported.");
-    emit msgBox->exec();
+    try {
+        mvg.addProgressCallback([this](const MandelVideoProgressInfo& mvpi) {
+            emit progress(mvpi.progress);
+        });
+        mvg.generate(generator);
+        emit finished(true, "Video successfully exported.");
+    }
+    catch (...) {
+        emit finished(false, "Error occurred during video export.");
+    }
 }
 

+ 1 - 1
BackgroundTask.h

@@ -22,7 +22,7 @@ public:
 
 signals:
     void progress(float percentage);
-    void finished(bool success);
+    void finished(bool success, QString message);
 };
 
 

+ 7 - 5
exportdialogs.cpp

@@ -141,9 +141,11 @@ void ExportVideoDialog::on_buttonBox_accepted()
     }
 
     evi.path = evd.savePath->text().toStdString();
-    evi.width = evd.vidWidth->text().toInt();
-    evi.height = evd.vidHeight->text().toInt();
-    evi.maxIterations = evd.maxIterations->text().toInt();
+
+    evi.mi = almond->mw->getMandelInfo();
+    evi.mi.bWidth = evd.vidWidth->text().toInt();
+    evi.mi.bHeight = evd.vidHeight->text().toInt();
+    evi.mi.maxIter = evd.maxIterations->text().toInt();
 
     evi.bitrate = evd.bitrate->text().toInt();
     evi.preset = evd.encodingPresetBox->currentText().toStdString();
@@ -162,8 +164,8 @@ void ExportVideoDialog::on_buttonBox_accepted()
         evd.endH->text().toDouble(),
     };*/
 
-    evi.start.adjustAspectRatio(evi.width, evi.height);
-    evi.end.adjustAspectRatio(evi.width, evi.height);
+    evi.start.adjustAspectRatio(evi.mi.bWidth, evi.mi.bHeight);
+    evi.end.adjustAspectRatio(evi.mi.bWidth, evi.mi.bHeight);
     evi.gradient = almond->mw->getGradient();
 
     //}

+ 9 - 3
libalmond/include/MandelVideoGenerator.h

@@ -8,13 +8,18 @@
 
 struct ExportVideoInfo
 {
+    /// the viewport at the start of the video
     mnd::MandelViewport start;
+    /// the viewport at the end of the video
     mnd::MandelViewport end;
+    /// Info struct to hold further data about the generation
+    /// of mandelbrot images. The Viewport specified in this
+    /// struct is ignored.
+    mnd::MandelInfo mi;
+
+    /// the gradient to use
     Gradient gradient;
 
-    int width;
-    int height;
-    int maxIterations;
     int fps;
     double zoomSpeed;
 
@@ -30,6 +35,7 @@ struct ExportVideoInfo
 struct MandelVideoProgressInfo
 {
     int64_t framesExported;
+    float progress;
 };
 
 

+ 18 - 23
libalmond/src/MandelVideoGenerator.cpp

@@ -17,7 +17,9 @@ void MandelVideoGenerator::addProgressCallback(ProgressCallback pc)
 
 void MandelVideoGenerator::generate(mnd::MandelGenerator& gen)
 {
-    VideoStream vs(evi.width, evi.height, evi.path, evi.bitrate, evi.fps, evi.preset.c_str());
+    const long width = evi.mi.bWidth;
+    const long height = evi.mi.bHeight;
+    VideoStream vs(width, height, evi.path, evi.bitrate, evi.fps, evi.preset.c_str());
 
     mnd::Real x = evi.end.x + evi.end.width / 2;
     mnd::Real y = evi.end.y + evi.end.height / 2;
@@ -33,56 +35,49 @@ void MandelVideoGenerator::generate(mnd::MandelGenerator& gen)
 
     const float oversizeFactor = 2;
     const float sqrFactor = sqrt(oversizeFactor);
-    //const mnd::Real invsqrt2 = mnd::Real(1.0) / mnd::sqrt(mnd::Real(2));
 
-    mnd::MandelInfo mi;
-    mi.bWidth = evi.width * oversizeFactor;
-    mi.bHeight = evi.height * oversizeFactor;
-    mi.maxIter = evi.maxIterations;
+    mnd::MandelInfo mi = evi.mi;
+    mi.bHeight *= oversizeFactor;
+    mi.bWidth *= oversizeFactor;
 
     bool first = true;
 
-    while(w > evi.end.width || h > evi.end.height) {
+    double zoomFactor = ::pow(0.99, evi.zoomSpeed);
+    double approxFrames = double(mnd::log(evi.end.width / evi.start.width) / mnd::log(zoomFactor));
 
+    while(w > evi.end.width || h > evi.end.height) {
         if (bigW > sqrt(oversizeFactor) * w) {
             mi.view = mnd::MandelViewport{ x - w/2, y - h/2, w, h };
-            Bitmap<float> raw{ long(evi.width * oversizeFactor), long(evi.height * oversizeFactor) };
-            Bitmap<float> rawSmall{ long(evi.width * oversizeFactor), long(evi.height * oversizeFactor) };
+            Bitmap<float> raw{ long(width * oversizeFactor), long(height * oversizeFactor) };
+            Bitmap<float> rawSmall{ long(width * oversizeFactor), long(height * oversizeFactor) };
             mi.view.zoomCenter(oversizeFactor);
             gen.generate(mi, rawSmall.pixels.get());
-            //mi.view.zoomCenter(sqrt(oversizeFactor));
-            //gen.generate(mi, raw.pixels.get());
-            //auto before = std::chrono::high_resolution_clock::now();
             if (first) {
                 mi.view.zoomCenter(sqrt(oversizeFactor));
                 gen.generate(mi, raw.pixels.get());
                 small = raw.map<RGBColor>([&mi, this] (float i) {
                     return i >= mi.maxIter ? RGBColor{ 0, 0, 0 } : evi.gradient.get(i);
                 });
+                first = false;
             }
             big = std::move(small);
             small = rawSmall.map<RGBColor>([&mi, this] (float i) {
                 return i >= mi.maxIter ? RGBColor{ 0, 0, 0 } : evi.gradient.get(i);
             });
             printf("recalced\n");
-            /*mi.view.zoomCenter(0.5);
-            gen.generate(mi, raw.pixels.get());
-            small = raw.map<RGBColor>([] (float x) { return
-                RGBColor{ uint8_t(::sin(x / 100) * 127 + 127), uint8_t(::sin(x / 213) * 127 + 127), uint8_t(::cos(x / 173) * 127 + 127) };
-            });*/
             bigW = w;
             bigFac = 1.0;
-            first = false;
         }
 
-        vs.addFrame(overlay(big, small, evi.width, evi.height, bigFac, sqrt(oversizeFactor)));
+        vs.addFrame(overlay(big, small, evi.mi.bWidth, evi.mi.bHeight, bigFac, sqrt(oversizeFactor)));
         frameCounter++;
-        MandelVideoProgressInfo mvpi{ frameCounter };
+        float progress = float(frameCounter / approxFrames);
+        MandelVideoProgressInfo mvpi{ frameCounter, progress * 100 };
         callCallbacks(mvpi);
 
-        w *= ::pow(0.99, evi.zoomSpeed);
-        h *= ::pow(0.99, evi.zoomSpeed);
-        bigFac *= ::pow(0.99, evi.zoomSpeed);
+        w *= zoomFactor;
+        h *= zoomFactor;
+        bigFac *= zoomFactor;
     }
 }
 

+ 6 - 5
libmandel/include/NaiveIRGenerator.h

@@ -66,10 +66,10 @@ namespace mnd
         struct Sub : BinaryOperation {};
         struct Mul : BinaryOperation {};
         struct Div : BinaryOperation {};
-    
+
         struct Neg : UnaryOperation {};
-    
-    
+
+
         struct Atan2 : BinaryOperation {};
         struct Pow : BinaryOperation {};
         struct Cos : UnaryOperation {};
@@ -83,9 +83,10 @@ namespace mnd
         struct EvalStruct
         {
             std::map<std::string, size_t> variableNames;
-            std::vector<T> variables;
+            std::vector<T*> variables;
+            std::vector<T> temporaries;
 
-            void prepare(const T& zre, const T& zim, const T& cre, const T& cim)
+            void prepare(T* zre, T* zim, T* cre, T* cim)
             {
                 auto z_re = variableNames.find("z_re");
                 auto z_im = variableNames.find("z_im");

+ 6 - 2
libmandel/src/IterationCompiler.cpp

@@ -18,6 +18,7 @@ using namespace std::string_literals;
 namespace mnd
 {
 #ifdef WITH_ASMJIT
+#if defined(__x86_64__) || defined(_M_X64)
     struct CompileVisitor
     {
         using Reg = asmjit::x86::Xmm;
@@ -564,6 +565,7 @@ namespace mnd
         return CompiledGeneratorVec{ std::move(ed) };
     }
 
+#endif // defined(__x86_64__) || defined(_M_X64)
 #endif // WITH_ASMJIT
 
     struct OpenClVisitor
@@ -783,6 +785,7 @@ namespace mnd
 
 
 #ifdef WITH_ASMJIT
+#if defined(__x86_64__) || defined(_M_X64)
         printf("ir: %s\n", irf.toString().c_str()); fflush(stdout);
         auto dg = std::make_unique<CompiledGenerator>(compile(irf));
         printf("asm: %s\n", dg->dump().c_str()); fflush(stdout);
@@ -792,10 +795,11 @@ namespace mnd
             printf("asm avxvec: %s\n", dgavx->dump().c_str()); fflush(stdout);
             vec.push_back(std::move(dgavx));
         }
+#endif // defined(__x86_64__) || defined(_M_X64)
 #endif // WITH_ASMJIT
 
-        vec.push_back(std::make_unique<NaiveIRGenerator<mnd::DoubleDouble>>(irf));
-        vec.push_back(std::make_unique<NaiveIRGenerator<mnd::QuadDouble>>(irf));
+        //vec.push_back(std::make_unique<NaiveIRGenerator<mnd::DoubleDouble>>(irf));
+        //vec.push_back(std::make_unique<NaiveIRGenerator<mnd::QuadDouble>>(irf));
         
         //auto dg = std::make_unique<NaiveIRGenerator>(*irf, mnd::getPrecision<double>());
 

+ 2 - 24
libmandel/src/IterationGenerator.cpp

@@ -125,6 +125,7 @@ std::complex<double> NaiveGenerator::calc(mnd::Expression& expr, std::complex<do
 }
 
 #ifdef WITH_ASMJIT
+#if defined(__x86_64__) || defined(_M_X64)
 
 #include "ExecData.h"
 
@@ -148,29 +149,6 @@ CompiledGenerator::~CompiledGenerator(void)
 }
 
 
-/*__declspec(noinline)
-int iter(double x, double y, int maxIter)
-{
-int k = 0;
-
-double a = x;
-double b = y;
-
-for (k = 0; k < maxIter; k++) {
-double aa = a * a;
-double bb = b * b;
-double abab = a * b + a * b;
-a = aa - bb + x;
-b = abab + y;
-if (aa + bb >= 16)
-break;
-}
-
-return k;
-}*/
-
-
-
 void CompiledGenerator::generate(const mnd::MandelInfo& info, float* data)
 {
     using IterFunc = int (*)(double, double, int);
@@ -236,7 +214,7 @@ void CompiledGeneratorVec::generate(const mnd::MandelInfo& info, float* data)
         }
     }
 }
-
+#endif // defined(__x86_64__) || defined(_M_X64)
 #endif // WITH_ASMJIT
 
 #ifdef WITH_OPENCL

+ 24 - 17
libmandel/src/NaiveIRGenerator.cpp

@@ -55,19 +55,21 @@ namespace mnd::eval
 
         size_t createTemp(void)
         {
-            es.variables.push_back(0);
+            es.temporaries.push_back(0);
+            es.variables.push_back(&es.temporaries[es.temporaries.size() - 1]);
             return es.variables.size() - 1;
         }
 
         size_t createConstant(mnd::Real& value)
         {
-            es.variables.push_back(mnd::convert<T>(value));
+            es.temporaries.push_back(mnd::convert<T>(value));
+            es.variables.push_back(&es.temporaries[es.temporaries.size() - 1]);
             return es.variables.size() - 1;
         }
 
         size_t createVariable(std::string& value)
         {
-            es.variables.push_back(0);
+            es.variables.push_back(nullptr);
             es.variableNames.emplace(value, es.variables.size() - 1);
             return es.variables.size() - 1;
         }
@@ -79,25 +81,31 @@ namespace mnd::eval
             return Load{ createVariable(x.name) };
         }
         EvalNode operator()(ir::Addition& x) {
-            return Add{ visit(x.left), visit(x.right) };
+            auto left = visit(x.left);
+            return Add{ std::move(left), visit(x.right) };
         }
         EvalNode operator()(ir::Subtraction& x) {
-            return Sub{ visit(x.left), visit(x.right) };
+            auto left = visit(x.left);
+            return Sub{ std::move(left), visit(x.right) };
         }
         EvalNode operator()(ir::Multiplication& x) {
-            return Mul{ visit(x.left), visit(x.right) };
+            auto left = visit(x.left);
+            return Mul{ std::move(left), visit(x.right) };
         }
         EvalNode operator()(ir::Division& x) {
-            return Div{ visit(x.left), visit(x.right) };
+            auto left = visit(x.left);
+            return Div{ std::move(left), visit(x.right) };
         }
         EvalNode operator()(ir::Negation& x) {
             return Neg{ visit(x.value) };
         }
         EvalNode operator()(ir::Atan2& x) {
-            return Atan2{ visit(x.left), visit(x.right) };
+            auto left = visit(x.left);
+            return Atan2{ std::move(left), visit(x.right) };
         }
         EvalNode operator()(ir::Pow& x) {
-            return Pow{ visit(x.left), visit(x.right) };
+            auto left = visit(x.left);
+            return Pow{ std::move(left), visit(x.right) };
         }
         EvalNode operator()(ir::Cos& x) {
             return Cos{ visit(x.value) };
@@ -125,12 +133,12 @@ namespace mnd::eval
         }
 
         T operator()(const Load& x) {
-            return es.variables[x.index];
+            return *es.variables[x.index];
         }
 
         T operator()(const Store& x) {
             T r = visit(*x.v);
-            es.variables[x.index] = r;
+            *es.variables[x.index] = r;
             return r;
         }
 
@@ -216,15 +224,14 @@ void NaiveIRGenerator<T>::generate(const mnd::MandelInfo& info, float* data)
         long i = 0;
         for (i; i < info.bWidth; i++) {
             T x = viewx + T(double(i)) * wpp;
-
-            es.prepare(0, 0, x, y);
+            T a;
+            T b;
+            es.prepare(&a, &b, &x, &y);
 
             eval::EvalVisitor<T> visitor{ es };
 
-            T a = visitor.visit(*start_re);
-            T b = visitor.visit(*start_im);
-
-            es.prepare(a, b, x, y);
+            a = visitor.visit(*start_re);
+            b = visitor.visit(*start_im);
 
             int k = 0;
             for (k = 0; k < info.maxIter; k++) {