Nicolas Winkler пре 6 година
родитељ
комит
8997cd4a7a
6 измењених фајлова са 166 додато и 55 уклоњено
  1. 2 1
      Almond.cpp
  2. 1 1
      Almond.pro
  3. 35 27
      Generators.cpp
  4. 23 12
      Generators.h
  5. 76 13
      MandelWidget.cpp
  6. 29 1
      MandelWidget.h

+ 2 - 1
Almond.cpp

@@ -10,6 +10,7 @@ Almond::Almond(QWidget *parent) :
     ui.setupUi(this);
     printf("not yet created!\n");
     mw = std::make_unique<MandelWidget>(ui.centralWidget);
+    qRegisterMetaType<MandelWidget>("MandelWidget");
     printf("created!\n");
     ui.verticalLayout_left->addWidget(mw.get());
     //ui.verticalLayout_left->addWidget(new MyGLWidget(ui.centralWidget));
@@ -27,7 +28,7 @@ void Almond::on_pushButton_clicked()
         mi.bWidth = dialog.getWidth();
         mi.bHeight = dialog.getHeight();
         mi.view.adjustAspectRatio(mi.bWidth, mi.bHeight);
-        CpuGenerator<double> cpg;
+        ClGenerator cpg;
         auto bitmap = cpg.generate(mi);
         QImage img((unsigned char*)bitmap.pixels.get(), bitmap.width, bitmap.height, bitmap.width * 3, QImage::Format_RGB888);
         img.save(dialog.getPath());

+ 1 - 1
Almond.pro

@@ -68,7 +68,7 @@ else:unix:QMAKE_CXXFLAGS+= -fopenmp
 win32:QMAKE_LFLAGS +=  -openmp
 else:unix:QMAKE_LFLAGS+= -fopenmp
 LIBS += -fopenmp
-LIBS += -lm
+unix:LIBS += -lm
 
 QMAKE_CXXFLAGS += -mavx
 

+ 35 - 27
Generators.cpp

@@ -48,10 +48,11 @@ ClGenerator::ClGenerator(void)
     context = Context{ device };
     Program::Sources sources;
 
-    std::string kcode_alt =
-        "void kernel iterate(global float* A, const int width, float xl, float yt, float pixelScale, int max) {"
-        "   int x = get_global_id(0) % width;"
-        "   int y = get_global_id(0) / width;"
+    std::string kcode =
+        "__kernel void iterate(__global float* A, const int width, float xl, float yt, float pixelScale, int max) {"
+        "   int index = get_global_id(0);\n"
+        "   int x = index % width;"
+        "   int y = index / width;"
         "   float a = x * pixelScale + xl;"
         "   float b = y * pixelScale + yt;"
         "   float ca = a;"
@@ -62,35 +63,48 @@ ClGenerator::ClGenerator(void)
         "       float aa = a * a;"
         "       float bb = b * b;"
         "       float ab = a * b;"
+        "       if (aa + bb > 16) break;"
         "       a = aa - bb + ca;"
         "       b = 2 * ab + cb;"
-        "       if (aa + bb > 16) break;"
         "       n++;"
         "   }\n"
-        "   A[get_global_id(0)] = n;//((float)n) + (a + b - 16) / (256 - 16);\n"
+        "   A[index] = ((float)n) + 1 - (a * a + b * b - 16) / (256 - 16);\n"
 //        "   A[get_global_id(0)] = 5;"
         "}";
 
-    std::string kcode =
+    std::string kcode_alt =
         "__kernel void iterate(__global float* A, const int width, float xl, float yt, float pixelScale, int max) {\n"
-        "   int x = get_global_id(0) % (width);\n"
-        "   int y = get_global_id(0) / (width);\n"
-        "   float a = x * pixelScale + xl;\n"
-        "   float b = y * pixelScale + yt;\n"
-        "   float ca = a;\n"
-        "   float cb = b;\n"
+        "   int index = get_global_id(0) * 8;\n"
+        "   int x = index % (width);\n"
+        "   int y = index / (width);\n"
+        "   float8 av = (float8)(x * pixelScale + xl, (x + 1) * pixelScale + xl, (x + 2) * pixelScale + xl, (x + 3) * pixelScale + xl,"
+                        "(x + 4) * pixelScale + xl, (x + 5) * pixelScale + xl, (x + 6) * pixelScale + xl, (x + 7) * pixelScale + xl);\n"
+        "   float8 bv = (float8)(y * pixelScale + yt);\n"
+        "   float8 ca = av;\n"
+        "   float8 cb = bv;\n"
         ""
+        "   int8 counter = (int8)0;"
+        "   float8 threshold = (float8)16;"
         "   int n = 0;\n"
         "   while (n < max) {\n"
-        "       float aa = a * a;\n"
-        "       float bb = b * b;\n"
-        "       float ab = a * b;\n"
-        "       a = aa - bb + ca;\n"
-        "       b = 2 * ab + cb;\n"
-        "       if (aa + bb > 16) break;\n"
+        "       float8 aa = av * av;\n"
+        "       float8 bb = bv * bv;\n"
+        "       float8 ab = av * bv;\n"
+        "       av = aa - bb + ca;\n"
+        "       bv = 2 * ab + cb;\n"
+        "       counter += -(threshold > (aa + bb));\n"
+        "       if(all(threshold < (aa + bb))) break;\n"
+        "       //if (aa + bb > 16) break;\n"
         "       n++;\n"
         "   }\n\n"
-        "   A[get_global_id(0)] = n;//((float)n) + (a + b - 16) / (256 - 16);\n"
+        "   A[index] = (float) counter[0];\n"
+        "   A[index + 1] = (float) counter[1];\n"
+        "   A[index + 2] = (float) counter[2];\n"
+        "   A[index + 3] = (float) counter[3];\n"
+        "   A[index + 4] = (float) counter[4];\n"
+        "   A[index + 5] = (float) counter[5];\n"
+        "   A[index + 6] = (float) counter[6];\n"
+        "   A[index + 7] = (float) counter[7];\n"
 //        "   A[get_global_id(0)] = 1;\n"
         "}\n";
 
@@ -127,13 +141,7 @@ Bitmap<float> ClGenerator::generateRaw(const MandelInfo& info)
     iterate.setArg(5, int(info.maxIter));
 
     queue.enqueueNDRangeKernel(iterate, 0, NDRange(info.bWidth * info.bHeight));
-    float* fs = new float[info.bWidth * info.bHeight];
-    queue.enqueueReadBuffer(buffer_A, CL_TRUE, 0, bufferSize, fs);
-
-    for (int i = 0; i < info.bWidth * info.bHeight; i++) {
-        bitmap.pixels[i] = fs[i];
-    }
-    delete[] fs;
+    queue.enqueueReadBuffer(buffer_A, CL_TRUE, 0, bufferSize, bitmap.pixels.get());
 
     return bitmap;
 }

+ 23 - 12
Generators.h

@@ -105,13 +105,18 @@ inline Bitmap<float> CpuGenerator<double>::generateRaw(const MandelInfo& info)
                     break;
                 }
             }
-            double data[8];
-            void* aligned = data;
-            ::size_t length = sizeof data;
-            std::align(32, 4 * sizeof(double), aligned, length);
-            double* ftRes = static_cast<double*>(aligned);
+
+            auto alignVec = [](double* data) -> double* {
+                void* aligned = data;
+                ::size_t length = 64;
+                std::align(32, 4 * sizeof(double), aligned, length);
+                return static_cast<double*>(aligned);
+            };
+
+            double resData[8];
+            double* ftRes = alignVec(resData);
             _mm256_store_pd(ftRes, counter);
-            for (int k = 0; k < 4; k++)
+            for (int k = 0; k < 4 && i + k < res.width; k++)
                 res.get(i + k, j) = ftRes[k] > 0 ? float(ftRes[k]) : info.maxIter;
         }
     }
@@ -166,13 +171,19 @@ inline Bitmap<float> CpuGenerator<float>::generateRaw(const MandelInfo& info)
                     break;
                 }
             }
-            float data[16];
-            void* aligned = data;
-            ::size_t length = sizeof data;
-            std::align(32, 8 * sizeof(float), aligned, length);
-            float* ftRes = static_cast<float*>(aligned);
+
+            auto alignVec = [](float* data) -> float* {
+                void* aligned = data;
+                ::size_t length = 64;
+                std::align(32, 8 * sizeof(float), aligned, length);
+                return static_cast<float*>(aligned);
+            };
+
+            float resData[16];
+            float* ftRes = alignVec(resData);
+
             _mm256_store_ps(ftRes, counter);
-            for (int k = 0; k < 8; k++)
+            for (int k = 0; k < 8 && i + k < res.width; k++)
                 res.get(i + k, j) = ftRes[k] > 0 ? ftRes[k] : info.maxIter;
         }
     }

+ 76 - 13
MandelWidget.cpp

@@ -58,12 +58,52 @@ void Texture::drawRect(float x, float y, float width, float height)
 }
 
 
+void MandelView::adaptViewport(const MandelViewport& vp)
+{
+    //bmp->get(0, 0) = RGBColor{ 10, uint8_t(sin(1 / vp.width) * 127 + 127), 10 };
+    /*printf("adapted\n");
+    if (calc.valid()) {
+        auto status = calc.wait_for(std::chrono::milliseconds(0));
+        if (status == std::future_status::deferred) {
+            printf("deferred\n");
+        } else if (status == std::future_status::timeout) {
+            printf("timeout\n");
+        } else if (status == std::future_status::ready) {
+            printf("ready!\n");
+        }
+    }*/
+    if (!calc.valid() || calc.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) {
+        toCalc = vp;
+        hasToCalc = true;
+        calc = std::async([this] () {
+            do {
+                CpuGenerator<float> cpg;
+                MandelInfo mi;
+                mi.bWidth = 1024;//ql.geometry().width();
+                mi.bHeight = 1024; //ql.geometry().height();
+                mi.maxIter = 4000;
+                mi.view = toCalc;
+                Bitmap<RGBColor>* bmp = //new Bitmap<RGBColor>(1, 1);
+                                        new Bitmap<RGBColor>(cpg.generate(mi));
+                emit updated(bmp);
+            } while(hasToCalc.exchange(false));
+        });
+    }
+    else {
+        toCalc = vp;
+        hasToCalc = true;
+    }
+}
+
+
 MandelWidget::MandelWidget(QWidget* parent) :
     QGLWidget{ QGLFormat(QGL::SampleBuffers), parent }
 {
     this->setContentsMargins(0, 0, 0, 0);
     this->setSizePolicy(QSizePolicy::Expanding,
         QSizePolicy::Expanding);
+    QObject::connect(&mv, &MandelView::updated, this, &MandelWidget::viewUpdated, Qt::AutoConnection);
+    QObject::connect(this, &MandelWidget::needsUpdate, &mv, &MandelView::adaptViewport, Qt::AutoConnection);
 }
 
 
@@ -87,30 +127,36 @@ void MandelWidget::initializeGL(void)
     mi.view = viewport;
     auto bitmap = cpg.generate(mi);*/
     Bitmap<RGBColor> bitmap(1, 1);
-    bitmap.get(0, 0) = RGBColor{5, 150, 50};
+    bitmap.get(0, 0) = RGBColor{50, 50, 50};
 
     tex = std::make_unique<Texture>(bitmap);
+    emit needsUpdate(viewport);
 }
 
 
 void MandelWidget::paintGL(void)
 {
+    /*if (!initialized) {
+        emit needsUpdate(viewport);
+        initialized = true;
+    }*/
+
     int width = this->width();
     int height = this->height();
 
-    CpuGenerator<double> cpg;
+    /*CpuGenerator<double> cpg;
     ClGenerator clg;
     MandelGenerator& mg = cpg;
     MandelInfo mi;
     mi.bWidth = width;
     mi.bHeight = height;
     mi.maxIter = 5000;
-    mi.view = viewport;
+    mi.view = viewport;*/
     //auto bitmap = mg.generate(mi);
-    Bitmap<RGBColor> bitmap(1000, 1000);
+    /*Bitmap<RGBColor> bitmap(1000, 1000);
     for (int i = 0; i < 1000 * 1000; i++)
         bitmap.pixels[i] = RGBColor{5, uint8_t((i % 1000) ^ (i / 1000)), 50};
-    tex = std::make_unique<Texture>(bitmap);
+    tex = std::make_unique<Texture>(bitmap);*/
 
     glViewport(0, 0, width, height);
 
@@ -127,8 +173,10 @@ void MandelWidget::paintGL(void)
     glLoadIdentity();
     tex->drawRect(0, 0, width, height);
 
-    drawRubberband();
-    printf("omg\n");
+    if (rubberbandDragging)
+        drawRubberband();
+
+    printf("painted GL\n");
 }
 
 
@@ -149,7 +197,7 @@ void MandelWidget::resizeGL(int width, int height)
 }
 
 
-void MandelWidget::redraw(void)
+/*void MandelWidget::redraw(void)
 {
     /*CpuGenerator<double> cpg;
     MandelInfo mi;
@@ -157,10 +205,11 @@ void MandelWidget::redraw(void)
     mi.bHeight = this->geometry().height(); //ql.geometry().height();
     mi.maxIter = 250;
     mi.view = viewport;*/
-    update();
+    //update();
+    //emit needsUpdate(viewport);
 
     //auto bitmap = cpg.generate(mi).map<uint32_t>([](RGBColor rgb) { return 255 << 24 | rgb.b << 16 | rgb.g << 8 | rgb.r; });
-}
+//}
 
 
 void MandelWidget::resizeEvent(QResizeEvent* re)
@@ -171,14 +220,16 @@ void MandelWidget::resizeEvent(QResizeEvent* re)
         viewport.height = (viewport.width / aspect);
     //else
     //    viewport.width = (viewport.height * aspect);
-    
-    redraw();
+
+    emit needsUpdate(viewport);
+    //redraw();
 }
 
 
 void MandelWidget::mousePressEvent(QMouseEvent* me)
 {
     rubberband.setCoords(me->x(), me->y(), 0, 0);
+    rubberbandDragging = true;
 }
 
 
@@ -191,6 +242,8 @@ void MandelWidget::mouseMoveEvent(QMouseEvent* me)
         rect.setHeight(rect.width() / aspect);
     else
         rect.setWidth(rect.height() * aspect);
+    if (rubberbandDragging)
+        emit repaint();
 }
 
 
@@ -203,5 +256,15 @@ void MandelWidget::mouseReleaseEvent(QMouseEvent* me)
     viewport.y += double(rect.top()) * viewport.height / full.height();
     viewport.width *= double(rect.width()) / full.width();
     viewport.height *= double(rect.height()) / full.height();
-    redraw();
+    rubberbandDragging = false;
+    emit needsUpdate(viewport);
+}
+
+
+void MandelWidget::viewUpdated(const Bitmap<RGBColor>* bitmap)
+{
+    tex = std::make_unique<Texture>(*bitmap);
+    delete bitmap;
+    printf("viewUpdated\n");
+    emit repaint();
 }

+ 29 - 1
MandelWidget.h

@@ -10,6 +10,8 @@
 #include <qrubberband.h>
 #include "Generators.h"
 
+#include <atomic>
+
 class Texture
 {
     GLuint id;
@@ -22,20 +24,43 @@ public:
     void drawRect(float x, float y, float width, float height);
 };
 
+class MandelView : public QObject
+{
+    Q_OBJECT
+private:
+    std::future<void> calc;
+    std::atomic<MandelViewport> toCalc;
+    std::atomic_bool hasToCalc = false;
+public:
+public slots:
+    void adaptViewport(const MandelViewport& vp);
+signals:
+    void updated(const Bitmap<RGBColor>* bitmap);
+};
+
 class MandelWidget : public QGLWidget
 {
     Q_OBJECT
 private:
     //QScrollArea qsa;
     //QLabel ql;
+
+    bool initialized = false;
+
+    bool rubberbandDragging = false;
     QRectF rubberband;
 
     std::unique_ptr<Texture> tex;
     MandelViewport viewport;
+    MandelView mv;
 public:
     MandelWidget(QWidget* parent = nullptr);
     ~MandelWidget(void) override;
 
+
+    inline MandelWidget(const MandelWidget& other) {
+    }
+
     void initializeGL(void) override;
 
     void resizeGL(int w, int h) override;
@@ -44,7 +69,7 @@ public:
 
     void drawRubberband(void);
 
-    void redraw();
+    //void redraw();
 
     void resizeEvent(QResizeEvent* re) override;
     void mousePressEvent(QMouseEvent* me) override;
@@ -53,5 +78,8 @@ public:
 
     inline const MandelViewport& getViewport(void) const { return viewport; }
 signals:
+    void needsUpdate(const MandelViewport& vp);
+public slots:
+    void viewUpdated(const Bitmap<RGBColor>* bitmap);
 };