Nicolas Winkler 5 anni fa
parent
commit
2b2997b77a

+ 16 - 4
Almond.cpp

@@ -18,6 +18,12 @@ Almond::Almond(QWidget* parent) :
                                         &mandelContext.getDefaultGenerator(),
                                         ui.centralWidget);
 
+    on_maxIterations_editingFinished();
+    mw->setSmoothColoring(ui.smooth->isChecked());
+    mw->getMandelInfo().julia = true;
+    mw->getMandelInfo().juliaX = 0.2;
+    mw->getMandelInfo().juliaY = -0.4;
+
     currentView = MANDELBROT;
     mandelGeneratorSave = &mandelContext.getDefaultGenerator();
     mandelViewSave = mw->getViewport();
@@ -130,6 +136,7 @@ void Almond::on_exportImage_clicked()
         mi.view.adjustAspectRatio(mi.bWidth, mi.bHeight);
         mi.smooth = mw->getSmoothColoring();
         if (currentView == JULIA) {
+            mi.julia = mw->getMandelInfo().julia;
             mi.juliaX = mw->getJuliaX();
             mi.juliaY = mw->getJuliaY();
         }
@@ -170,8 +177,9 @@ void Almond::on_chooseGenerator_clicked()
     else {
         mandelGeneratorSave = &mandelContext.getDefaultGenerator();
     }
-    this->currentView = MANDELBROT;
+    //this->currentView = MANDELBROT;
     this->mw->setGenerator(mandelGeneratorSave);
+    //this->mw->getMandelInfo().julia = false;
     printf("dialog executed\n"); fflush(stdout);
 }
 
@@ -186,11 +194,13 @@ void Almond::on_selectPoint_clicked()
 void Almond::pointSelected(mnd::Real x, mnd::Real y)
 {
     if (currentView != JULIA) {
-        auto& gen = mandelContext.getJuliaGenerator();
+        //auto& gen = mandelContext.getJuliaGenerator();
         mandelViewSave = mw->getViewport();
-        this->mw->setGenerator(&gen);
+        //this->mw->setGenerator(&gen);
         this->mw->setViewport(mnd::MandelViewport::centerView());
         this->mw->setJuliaPos(x, y);
+        this->mw->getMandelInfo().julia = true;
+        this->mw->clearAll();
     }
     currentView = JULIA;
 }
@@ -198,8 +208,10 @@ void Almond::pointSelected(mnd::Real x, mnd::Real y)
 void Almond::on_viewMandelbrot_clicked()
 {
     if (currentView != MANDELBROT) {
-        this->mw->setGenerator(mandelGeneratorSave);
+        //this->mw->setGenerator(mandelGeneratorSave);
         this->mw->setViewport(mandelViewSave);
+        this->mw->getMandelInfo().julia = false;
+        this->mw->clearAll();
         currentView = MANDELBROT;
     }
 }

+ 37 - 55
MandelWidget.cpp

@@ -221,19 +221,15 @@ void Job::run(void)
     mnd::Real gw = grid->dpp * MandelView::chunkSize;
 
     Bitmap<float> f(MandelView::chunkSize, MandelView::chunkSize);
-    std::unique_ptr<mnd::MandelInfo> mi = std::make_unique<mnd::MandelInfo>();
-    mi->view.x = absX;
-    mi->view.y = absY;
-    mi->view.width = mi->view.height = gw;
-    mi->bWidth = mi->bHeight = MandelView::chunkSize;
-    mi->maxIter = owner.getMaxIterations();
-    mi->smooth = owner.getSmoothColoring();
-    mi->juliaX = juliaX;
-    mi->juliaY = juliaY;
+    mnd::MandelInfo mi = owner.getMandelInfo();
+    mi.view.x = absX;
+    mi.view.y = absY;
+    mi.view.width = mi.view.height = gw;
+    mi.bWidth = mi.bHeight = MandelView::chunkSize;
     try {
-        generator->generate(*mi, f.pixels.get());
-        auto* rgb = new Bitmap<RGBColor>(f.map<RGBColor>([&mi, this](float i) {
-            return i >= mi->maxIter ? RGBColor{ 0, 0, 0 } : gradient.get(i);
+        generator->generate(mi, f.pixels.get());
+        auto* rgb = new Bitmap<RGBColor>(f.map<RGBColor>([&mi, this] (float i) {
+            return i >= mi.maxIter ? RGBColor{ 0, 0, 0 } : gradient.get(i);
         }));
         emit done(level, i, j, calcState, rgb);
     }
@@ -248,46 +244,28 @@ void Job::run(void)
 }
 
 
-Calcer::Calcer(mnd::MandelGenerator* generator, MandelWidget& owner, int maxIter, bool smooth) :
+Calcer::Calcer(mnd::MandelGenerator* generator, MandelWidget& owner) :
     jobsMutex{ QMutex::Recursive },
     generator{ generator },
     threadPool{ std::make_unique<QThreadPool>() },
     owner{ owner },
-    gradient{ owner.getGradient() },
-    maxIter{ maxIter },
-    smooth{ smooth }
+    gradient{ owner.getGradient() }
 {
     threadPool->setMaxThreadCount(1);
 }
 
 
-void Calcer::setMaxIter(int maxIter)
-{
-    this->maxIter = maxIter;
-    clearAll();
-    changeState();
-}
-
-
 void Calcer::clearAll(void)
 {
     this->threadPool->clear();
 }
 
 
-void Calcer::setJuliaPos(const mnd::Real& x, const mnd::Real& y)
-{
-    this->juliaX = x;
-    this->juliaY = y;
-    changeState();
-}
-
-
 void Calcer::calc(TexGrid& grid, int level, GridIndex i, GridIndex j, int priority)
 {
     jobsMutex.lock();
     if (jobs.find({ level, i, j }) == jobs.end()) {
-        Job* job = new Job(generator, gradient, owner, &grid, level, i, j, juliaX, juliaY, calcState);
+        Job* job = new Job(generator, gradient, owner, &grid, level, i, j, calcState);
         connect(job, &Job::done, this, &Calcer::redirect);
         connect(job, &QObject::destroyed, this, [this, level, i, j] () { this->notFinished(level, i, j); });
         jobs.emplace(std::tuple{level, i, j}, job);
@@ -343,11 +321,10 @@ void Calcer::redirect(int level, GridIndex i, GridIndex j, long calcState, Bitma
 
 const int MandelView::chunkSize = 256;
 
-MandelView::MandelView(mnd::MandelGenerator* generator, MandelWidget& owner, int maxIter) :
+MandelView::MandelView(mnd::MandelGenerator* generator, MandelWidget& owner) :
     generator{ generator },
-    calcer{ generator, owner, maxIter, owner.getSmoothColoring() },
-    owner{ owner },
-    maxIter{ maxIter }
+    calcer{ generator, owner },
+    owner{ owner }
 {
     Bitmap<RGBColor> emp(8, 8);
     for(auto i = 0; i < emp.width; i++) {
@@ -389,17 +366,6 @@ TexGrid& MandelView::getGrid(int level)
 }
 
 
-void MandelView::setMaxIter(int maxIter)
-{
-    if (this->maxIter != maxIter) {
-        this->maxIter = maxIter;
-        calcer.setMaxIter(maxIter);
-        clearCells();
-        emit redrawRequested();
-    }
-}
-
-
 void MandelView::setGenerator(mnd::MandelGenerator* generator)
 {
     if (this->generator != generator) {
@@ -633,8 +599,8 @@ void MandelWidget::setGradient(Gradient g)
 
 void MandelWidget::setSmoothColoring(bool sc)
 {
-    if (sc != this->smoothColoring) {
-        this->smoothColoring = sc;
+    if (sc != mandelInfo.smooth) {
+        mandelInfo.smooth = sc;
         if (mandelView) {
             mandelView->clearCells();
             emit update();
@@ -654,16 +620,25 @@ void MandelWidget::setDisplayInfo(bool di)
 
 void MandelWidget::setMaxIterations(int maxIter)
 {
-    this->maxIterations = maxIter;
-    if (mandelView)
-        mandelView->setMaxIter(maxIter);
+    if (mandelInfo.maxIter != maxIter) {
+        mandelInfo.maxIter = maxIter;
+        if (mandelView) {
+            mandelView->clearCells();
+            mandelView->calcer.clearAll();
+            mandelView->calcer.changeState();
+        }
+        emit update();
+    }
 }
 
 
 void MandelWidget::setJuliaPos(const mnd::Real& x, const mnd::Real& y)
 {
+    mandelInfo.juliaX = x;
+    mandelInfo.juliaY = y;
     if (mandelView)
-        mandelView->calcer.setJuliaPos(x, y);
+        mandelView->calcer.changeState();
+    emit update();
 }
 
 
@@ -677,6 +652,13 @@ void MandelWidget::setGenerator(mnd::MandelGenerator* generator)
 }
 
 
+void MandelWidget::clearAll(void)
+{
+    mandelView->clearCells();
+    mandelView->calcer.clearAll();
+}
+
+
 void MandelWidget::initializeGL(void)
 {
     this->context()->functions()->glClearColor(0, 0, 0, 0);
@@ -697,7 +679,7 @@ void MandelWidget::initializeGL(void)
 void MandelWidget::paintGL(void)
 {
     if (mandelView == nullptr) {
-        mandelView = std::make_unique<MandelView>(generator, *this, maxIterations);
+        mandelView = std::make_unique<MandelView>(generator, *this);
         QObject::connect(mandelView.get(), &MandelView::redrawRequested, this, static_cast<void(QOpenGLWidget::*)(void)>(&QOpenGLWidget::update));
     }
 

+ 13 - 27
MandelWidget.h

@@ -181,8 +181,6 @@ public:
     TexGrid* grid;
     int level;
     GridIndex i, j;
-    mnd::Real juliaX;
-    mnd::Real juliaY;
     long calcState = 0;
 
     inline Job(mnd::MandelGenerator* generator,
@@ -190,7 +188,6 @@ public:
                MandelWidget& owner,
                TexGrid* grid,
                int level, GridIndex i, GridIndex j,
-               const mnd::Real& juliaX, const mnd::Real& juliaY,
                long calcState) :
         generator{ generator },
         gradient{ gradient },
@@ -198,7 +195,6 @@ public:
         grid{ grid },
         level{ level },
         i{ i }, j{ j },
-        juliaX{ juliaX }, juliaY{ juliaY },
         calcState{ calcState }
     {}
 
@@ -215,24 +211,16 @@ class Calcer : public QObject
     std::unordered_map<std::tuple<int, GridIndex, GridIndex>, Job*, TripleHash> jobs;
     QMutex jobsMutex;
     mnd::MandelGenerator* generator;
-public:
-    mnd::Real juliaX;
-    mnd::Real juliaY;
-private:
     std::unique_ptr<QThreadPool> threadPool;
     MandelWidget& owner;
     const Gradient& gradient;
-    int maxIter;
-    bool smooth;
     int currentLevel;
 
-    volatile long calcState = 0;
+    volatile unsigned int calcState = 0;
 public:
-    Calcer(mnd::MandelGenerator* generator, MandelWidget& owner, int maxIter, bool smooth);
-    void setMaxIter(int maxIter);
+    Calcer(mnd::MandelGenerator* generator, MandelWidget& owner);
     void clearAll(void);
     void setGenerator(mnd::MandelGenerator* generator) { this->generator = generator; changeState(); }
-    void setJuliaPos(const mnd::Real& x, const mnd::Real& y);
 
     inline void changeState(void) { calcState++; }
 
@@ -258,20 +246,16 @@ public:
     mnd::MandelGenerator* generator;
     Calcer calcer;
     MandelWidget& owner;
-    int maxIter;
     int width;
     int height;
 public:
     static const int chunkSize;
-    MandelView(mnd::MandelGenerator* generator, MandelWidget& owner, int maxIter);
+    MandelView(mnd::MandelGenerator* generator, MandelWidget& owner);
     int getLevel(mnd::Real dpp);
     mnd::Real getDpp(int level);
 
     TexGrid& getGrid(int level);
 
-    inline int getMaxIter(void) const { return this->maxIter; }
-    void setMaxIter(int maxIter);
-
     void setGenerator(mnd::MandelGenerator* generator);
 
     void clearCells(void);
@@ -293,14 +277,12 @@ class MandelWidget : public QOpenGLWidget
 private:
     mnd::MandelContext& mndContext;
     mnd::MandelGenerator* generator;
+    mnd::MandelInfo mandelInfo;
 
-    bool smoothColoring = true;
+    bool initialized = false;
 
     Gradient gradient;
 
-    bool initialized = false;
-    int maxIterations = 2000;
-
     volatile bool selectingPoint = false;
     float pointX;
     float pointY;
@@ -324,21 +306,25 @@ public:
     inline const Gradient& getGradient(void) const { return gradient; }
     void setGradient(Gradient g);
 
-    inline bool getSmoothColoring(void) const { return smoothColoring; }
+    inline bool getSmoothColoring(void) const { return mandelInfo.smooth; }
     void setSmoothColoring(bool sc);
 
     inline bool doesDisplayInfo(void) const { return displayInfo; }
     void setDisplayInfo(bool di);
 
-    inline int getMaxIterations(void) const { return maxIterations; }
+    inline int getMaxIterations(void) const { return mandelInfo.maxIter; }
     void setMaxIterations(int maxIter);
 
+    inline const mnd::MandelInfo& getMandelInfo(void) const { return mandelInfo; }
+    inline mnd::MandelInfo& getMandelInfo(void) { return mandelInfo; }
+
     void setJuliaPos(const mnd::Real& x, const mnd::Real& y);
-    const mnd::Real& getJuliaX(void) { return mandelView->calcer.juliaX; }
-    const mnd::Real& getJuliaY(void) { return mandelView->calcer.juliaY; }
+    const mnd::Real& getJuliaX(void) { return mandelInfo.juliaX; }
+    const mnd::Real& getJuliaY(void) { return mandelInfo.juliaY; }
 
     inline mnd::MandelGenerator* getGenerator(void) const { return generator; }
     void setGenerator(mnd::MandelGenerator* generator);
+    void clearAll(void);
 
     void initializeGL(void) override;
     void paintGL() override;

+ 1 - 0
libmandel/CMakeLists.txt

@@ -101,6 +101,7 @@ if (ARCH STREQUAL "X86_64" OR ARCH STREQUAL "X86")
         set_source_files_properties(src/CpuGeneratorsAVXFMA.cpp PROPERTIES COMPILE_FLAGS /arch:AVX)
     else()
         set_source_files_properties(src/CpuGeneratorsAVX.cpp PROPERTIES COMPILE_FLAGS -mavx)
+        set_source_files_properties(src/JuliaGenerators.cpp PROPERTIES COMPILE_FLAGS -mavx)
         set_source_files_properties(src/CpuGeneratorsAVXFMA.cpp PROPERTIES COMPILE_FLAGS -mavx)
     endif(MSVC)
 

+ 1 - 0
libmandel/include/MandelUtil.h

@@ -79,6 +79,7 @@ struct mnd::MandelInfo
     /// smooth coloring
     bool smooth;
 
+    bool julia = false;
     Real juliaX;
     Real juliaY;
 };

+ 8 - 2
libmandel/src/CpuGenerators.cpp

@@ -64,6 +64,9 @@ void CpuGenerator<T, mnd::NONE, parallel>::generate(const mnd::MandelInfo& info,
     T wpp = mnd::convert<T>(view.width / info.bWidth);
     T hpp = mnd::convert<T>(view.height / info.bHeight);
 
+    T juliaX = mnd::convert<T>(info.juliaX);
+    T juliaY = mnd::convert<T>(info.juliaY);
+
     if constexpr (parallel)
         omp_set_num_threads(omp_get_num_procs());
 #pragma omp parallel for schedule(static, 1) if (parallel)
@@ -76,13 +79,16 @@ void CpuGenerator<T, mnd::NONE, parallel>::generate(const mnd::MandelInfo& info,
             T a = x;
             T b = y;
 
+            T cx = info.julia ? juliaX : x;
+            T cy = info.julia ? juliaY : y;
+
             int k = 0;
             for (k = 0; k < info.maxIter; k++) {
                 T aa = a * a;
                 T bb = b * b;
                 T ab = a * b;
-                a = aa - bb + x;
-                b = ab + ab + y;
+                a = aa - bb + cx;
+                b = ab + ab + cy;
                 if (aa + bb > T(16.0)) {
                     break;
                 }

+ 13 - 4
libmandel/src/CpuGeneratorsAVX.cpp

@@ -31,6 +31,11 @@ void CpuGenerator<float, mnd::X86_AVX, parallel>::generate(const mnd::MandelInfo
     __m256 viewx = { viewxf, viewxf, viewxf, viewxf, viewxf, viewxf, viewxf, viewxf };
     __m256 dpp = { dppf, dppf, dppf, dppf, dppf, dppf, dppf, dppf };
 
+    T jX = info.juliaX;
+    T jY = info.juliaY;
+    __m256 juliaX = { jX, jX, jX, jX, jX, jX, jX, jX };
+    __m256 juliaY = { jY, jY, jY, jY, jY, jY, jY, jY };
+
     if constexpr(parallel)
         omp_set_num_threads(omp_get_num_procs());
 #pragma omp parallel for schedule(static, 1) if (parallel)
@@ -52,13 +57,17 @@ void CpuGenerator<float, mnd::X86_AVX, parallel>::generate(const mnd::MandelInfo
 
             __m256 a = xs;
             __m256 b = ys;
+
+            __m256 cx = info.julia ? juliaX : xs;
+            __m256 cy = info.julia ? juliaY : ys;
+
             if (info.smooth) {
                 for (int k = 0; k < info.maxIter; k++) {
                     __m256 aa = _mm256_mul_ps(a, a);
                     __m256 bb = _mm256_mul_ps(b, b);
                     __m256 abab = _mm256_mul_ps(a, b); abab = _mm256_add_ps(abab, abab);
-                    a = _mm256_add_ps(_mm256_sub_ps(aa, bb), xs);
-                    b = _mm256_add_ps(abab, ys);
+                    a = _mm256_add_ps(_mm256_sub_ps(aa, bb), cx);
+                    b = _mm256_add_ps(abab, cy);
                     __m256 cmp = _mm256_cmp_ps(_mm256_add_ps(aa, bb), threshold, _CMP_LE_OQ);
                     resultsa = _mm256_or_ps(_mm256_andnot_ps(cmp, resultsa), _mm256_and_ps(cmp, a));
                     resultsb = _mm256_or_ps(_mm256_andnot_ps(cmp, resultsb), _mm256_and_ps(cmp, b));
@@ -74,8 +83,8 @@ void CpuGenerator<float, mnd::X86_AVX, parallel>::generate(const mnd::MandelInfo
                     __m256 aa = _mm256_mul_ps(a, a);
                     __m256 bb = _mm256_mul_ps(b, b);
                     __m256 abab = _mm256_mul_ps(a, b); abab = _mm256_add_ps(abab, abab);
-                    a = _mm256_add_ps(_mm256_sub_ps(aa, bb), xs);
-                    b = _mm256_add_ps(abab, ys);
+                    a = _mm256_add_ps(_mm256_sub_ps(aa, bb), cx);
+                    b = _mm256_add_ps(abab, cy);
                     __m256 cmp = _mm256_cmp_ps(_mm256_add_ps(aa, bb), threshold, _CMP_LE_OQ);
                     adder = _mm256_and_ps(adder, cmp);
                     counter = _mm256_add_ps(counter, adder);

+ 1 - 0
libmandel/src/JuliaGenerators.cpp

@@ -1,6 +1,7 @@
 #include "Generators.h"
 #include "JuliaGenerators.h"
 
+#include <immintrin.h>
 #include <omp.h>
 
 mnd::JuliaGeneratorFloat::JuliaGeneratorFloat(const mnd::Real& precision) :