Nicolas Winkler 5 jaren geleden
bovenliggende
commit
7819f9705a
7 gewijzigde bestanden met toevoegingen van 176 en 22 verwijderingen
  1. 109 3
      MandelWidget.cpp
  2. 42 1
      MandelWidget.h
  3. 18 14
      benchmarkdialog.cpp
  4. 1 1
      benchmarkdialog.h
  5. 3 0
      libmandel/include/MandelUtil.h
  6. 2 2
      libmandel/src/CpuGeneratorsAVX.cpp
  7. 1 1
      libmandel/src/mandel.cpp

+ 109 - 3
MandelWidget.cpp

@@ -88,6 +88,105 @@ void Texture::drawRect(float x, float y, float width, float height)
 }
 
 
+std::pair<int, int> TexGrid::getCellIndices(double x, double y)
+{
+    return { int(x / dpp / 64), int(y / dpp / 64) };
+}
+
+
+std::pair<double, double> TexGrid::getPositions(int x, int y)
+{
+    return { x * dpp * 64, y * dpp * 64 };
+}
+
+
+Texture* TexGrid::getCell(int i, int j)
+{
+    auto cIt = cells.find({i, j});
+    if (cIt != cells.end()) {
+        return &cIt->second;
+    }
+    else {
+        return nullptr;
+    }
+}
+
+
+MandelV::MandelV(QOpenGLContext* context) :
+    empty{ Bitmap<RGBColor>(1, 1) }
+{
+    Bitmap<RGBColor> emp(8, 8);
+    for(auto i = 0; i < emp.width; i++) {
+        for(auto j = 0; j < emp.height; j++) {
+            if((i + j) & 0x1) { // if i+j is odd
+                emp.get(i, j) = RGBColor{ 255, 255, 255 };
+            }
+            else {
+                emp.get(i, j) = RGBColor{ 120, 120, 120 };
+            }
+        }
+    }
+    context->makeCurrent(nullptr);
+    empty = Texture(emp, context);
+}
+
+
+int MandelV::getLevel(double dpp) {
+    return -int(::log2(dpp / 64));
+}
+
+
+double MandelV::getDpp(int level)
+{
+    return ::pow(2, -level) * 64;
+}
+
+
+TexGrid& MandelV::getGrid(int level)
+{
+    auto it = levels.find(level);
+    if (it != levels.end())
+        return it->second;
+    else {
+        levels.insert({ level, TexGrid(getDpp(level)) });
+        return levels[level];
+    }
+}
+
+
+void MandelV::paint(const mnd::MandelViewport& mvp)
+{
+    this->empty.drawRect(0, 0, 100, 100);
+    return;
+    int width = 1024;
+    double dpp = mvp.width / width;
+    int level = getLevel(dpp);
+
+    auto& grid = getGrid(level);
+    double gw = getDpp(level) * 64;
+
+    auto [left, top] = grid.getCellIndices(mvp.x, mvp.y);
+    auto [right, bottom] = grid.getCellIndices(mvp.right(), mvp.bottom());
+    for(int i = left; i <= right; i++) {
+        for(int j = top; j <= bottom; j++) {
+
+            auto [absX, absY] = grid.getPositions(i, j);
+            double x = (absX - mvp.x) * width / mvp.width;
+            double y = (absY - mvp.y) * width / mvp.height;
+            double w = width / mvp.width * gw;
+
+            Texture* t = grid.getCell(i, j);
+            if (t != nullptr) {
+                t->drawRect(x, y, w, w);
+            }
+            else {
+                this->empty.drawRect(x, y, w, w);
+            }
+        }
+    }
+}
+
+
 MandelView::MandelView(mnd::Generator& generator, Gradient &gradient, MandelWidget* mWidget) :
     generator{ &generator },
     gradient{ gradient },
@@ -218,7 +317,7 @@ void MandelView::adaptViewport(const MandelInfo mi)
 
 
 MandelWidget::MandelWidget(mnd::MandelContext& ctxt, QWidget* parent) :
-    QGLWidget{ QGLFormat(QGL::SampleBuffers), parent },
+    QOpenGLWidget{ parent },
     mndContext{ ctxt },
     mv{ ctxt.getDefaultGenerator(), gradient, this }
 {
@@ -243,7 +342,7 @@ MandelWidget::~MandelWidget()
 
 void MandelWidget::initializeGL(void)
 {
-    qglClearColor(Qt::black);
+    this->context()->functions()->glClearColor(0, 0, 0, 0);
 
     glDisable(GL_DEPTH_TEST);
 
@@ -261,8 +360,9 @@ void MandelWidget::initializeGL(void)
     auto bitmap = cpg.generate(mi);*/
     Bitmap<RGBColor> bitmap(1, 1);
     bitmap.get(0, 0) = RGBColor{50, 50, 50};
+    v = std::make_unique<MandelV>(context());
 
-    tex = std::make_unique<Texture>(bitmap, context()->contextHandle());
+    tex = std::make_unique<Texture>(bitmap, context());
     mv.start();
     requestRecalc();
 }
@@ -307,6 +407,12 @@ void MandelWidget::paintGL(void)
     glLoadIdentity();
     tex->drawRect(0, 0, width, height);
 
+    //v->empty = std::move(*tex)
+    //v->empty.bind();
+    v->paint(this->viewport);
+    //*tex = std::move(v->empty);
+
+
     if (rubberbandDragging)
         drawRubberband();
 

+ 42 - 1
MandelWidget.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include <QGLWidget>
+#include <QOpenGLWidget>
 #include <QThread>
 #include <qopengl.h>
 #include <qopenglfunctions.h>
@@ -18,6 +19,7 @@
 #include <thread>
 #include <mutex>
 #include <atomic>
+#include <unordered_map>
 
 class MandelWidget;
 
@@ -37,6 +39,7 @@ public:
     Texture& operator=(Texture&& other) = default;
 
     void bind(void) const;
+    inline GLuint getId(void) const { return id; }
 
     void drawRect(float x, float y, float width, float height);
 };
@@ -45,7 +48,44 @@ public:
 struct MandelClip
 {
     mnd::MandelViewport view;
+};
+
+struct PairHash {
+    template <typename T1, typename T2>
+    std::size_t operator () (const std::pair<T1, T2>& p) const {
+        auto h1 = std::hash<T1>{}(p.first);
+        auto h2 = std::hash<T2>{}(p.second);
+        return (h1 ^ 234579245) * 23452354 + h2;
+    }
+};
+
+
+class TexGrid
+{
+    double dpp;
+    std::unordered_map<std::pair<int, int>, Texture, PairHash> cells;
+public:
+    inline TexGrid(void) : dpp{ 1.0 } {}
+    inline TexGrid(double dpp) : dpp{ dpp } {}
+    std::pair<int, int> getCellIndices(double x, double y);
+    std::pair<double, double> getPositions(int i, int j);
+    Texture* getCell(int i, int j);
+};
+
+
+class MandelV
+{
+public:
+    Texture empty;
+    std::unordered_map<int, TexGrid> levels;
+public:
+    MandelV(QOpenGLContext* context);
+    int getLevel(double dpp);
+    double getDpp(int level);
+
+    TexGrid& getGrid(int level);
 
+    void paint(const mnd::MandelViewport& mvp);
 };
 
 
@@ -80,7 +120,7 @@ signals:
     void updated(Bitmap<RGBColor>* bitmap);
 };
 
-class MandelWidget : public QGLWidget
+class MandelWidget : public QOpenGLWidget
 {
     Q_OBJECT
 private:
@@ -99,6 +139,7 @@ private:
     std::unique_ptr<Texture> tex;
     mnd::MandelViewport viewport;
     MandelView mv;
+    std::unique_ptr<MandelV> v;
 public:
     MandelWidget(mnd::MandelContext& ctxt, QWidget* parent = nullptr);
     ~MandelWidget(void) override;

+ 18 - 14
benchmarkdialog.cpp

@@ -10,6 +10,10 @@ mnd::MandelViewport Benchmarker::benchViewport(void)
 }
 
 const std::vector<mnd::MandelInfo> Benchmarker::benches {
+    mnd::MandelInfo{ benchViewport(), 50, 50, 250 },
+    mnd::MandelInfo{ benchViewport(), 50, 50, 500 },
+    mnd::MandelInfo{ benchViewport(), 50, 100, 500 },
+    mnd::MandelInfo{ benchViewport(), 100, 100, 500 },
     mnd::MandelInfo{ benchViewport(), 100, 100, 1000 },
     mnd::MandelInfo{ benchViewport(), 100, 200, 1000 },
     mnd::MandelInfo{ benchViewport(), 200, 200, 1000 },
@@ -47,16 +51,16 @@ const std::vector<mnd::MandelInfo> Benchmarker::benches {
 };
 
 
-std::pair<long long, std::chrono::nanoseconds> Benchmarker::measureMips(const std::function<Bitmap<float>()>& bench) const
+std::pair<long long, std::chrono::nanoseconds> Benchmarker::measureMips(const std::function<Bitmap<float>*()>& bench) const
 {
     using namespace std::chrono;
     auto before = high_resolution_clock::now();
-    auto bitmap = bench();
+    auto* bitmap = bench();
     auto after = high_resolution_clock::now();
 
     long long sum = 0;
-    for (int i = 0; i < bitmap.width * bitmap.height; i++) {
-        sum += std::floor(bitmap.pixels[size_t(i)]);
+    for (int i = 0; i < bitmap->width * bitmap->height; i++) {
+        sum += std::floor(bitmap->pixels[size_t(i)]);
     }
 
     return std::make_pair(sum, duration_cast<nanoseconds>(after - before));
@@ -66,29 +70,29 @@ double Benchmarker::benchmarkResult(mnd::Generator& mg) const
 {
     int testIndex = 0;
 
-    for (int i = 0; i < benches.size(); i++) {
+    for (size_t i = 0; i < benches.size(); i++) {
         const mnd::MandelInfo& mi = benches[i];
-        auto data = std::make_unique<float[]>(mi.bWidth * mi.bHeight);
-        auto [iters, time] = measureMips([&mg, &mi, &data]() {
-            Bitmap<float> bmp(mi.bWidth, mi.bHeight);
+        //auto data = std::make_unique<float[]>(size_t(mi.bWidth * mi.bHeight));
+        Bitmap<float> bmp(mi.bWidth, mi.bHeight);
+        auto [iters, time] = measureMips([&mg, &mi, &bmp]() {
             mg.generate(mi, bmp.pixels.get());
-            return bmp;
+            return &bmp;
         });
         //printf("benchmark lvl %d, time %d ms\n", i, time.count() / 1000 / 1000);
         //fflush(stdout);
         if (time > std::chrono::milliseconds(1000)) {
-            testIndex = i + 2;
+            testIndex = i + 1;
             break;
         }
     }
 
 
     const mnd::MandelInfo& mi = benches[(testIndex >= benches.size()) ? (benches.size() - 1) : testIndex];
-    auto data = std::make_unique<float[]>(mi.bWidth * mi.bHeight);
-    auto [iters, time] = measureMips([&mg, &mi, &data]() {
-        Bitmap<float> bmp(mi.bWidth, mi.bHeight);
+    //auto data = std::make_unique<float[]>(mi.bWidth * mi.bHeight);
+    Bitmap<float> bmp(mi.bWidth, mi.bHeight);
+    auto [iters, time] = measureMips([&mg, &mi, &bmp]() {
         mg.generate(mi, bmp.pixels.get());
-        return bmp;
+        return &bmp;
     });
     //printf("bench time %d ms\n", time.count() / 1000 / 1000);
     //fflush(stdout);

+ 1 - 1
benchmarkdialog.h

@@ -31,7 +31,7 @@ public:
 
     static mnd::MandelViewport benchViewport(void);
 
-    std::pair<long long, std::chrono::nanoseconds> measureMips(const std::function<Bitmap<float>()>& bench) const;
+    std::pair<long long, std::chrono::nanoseconds> measureMips(const std::function<Bitmap<float>*()>& bench) const;
     double benchmarkResult(mnd::Generator& mg) const;
 
 public slots:

+ 3 - 0
libmandel/include/MandelUtil.h

@@ -42,6 +42,9 @@ struct mnd::MandelViewport
      * \brief returns a viewport where the whole mandelbrot set can be observed
      */
     static MandelViewport standardView(void);
+
+    inline double right() const { return x + width; }
+    inline double bottom() const { return y + height; }
 };
 
 struct mnd::MandelInfo

+ 2 - 2
libmandel/src/CpuGeneratorsAVX.cpp

@@ -44,8 +44,8 @@ void CpuGenerator<float, mnd::X86_AVX, parallel, smooth>::generate(const mnd::Ma
 
             __m256 counter = {0, 0, 0, 0, 0, 0, 0, 0};
             __m256 adder = {1, 1, 1, 1, 1, 1, 1, 1};
-            __m256 resultsa;
-            __m256 resultsb;
+            __m256 resultsa = {0, 0, 0, 0, 0, 0, 0, 0};
+            __m256 resultsb = {0, 0, 0, 0, 0, 0, 0, 0};
 
             __m256 threshold = {16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f, 16.0f};
 

+ 1 - 1
libmandel/src/mandel.cpp

@@ -92,7 +92,7 @@ std::vector<MandelDevice> MandelContext::createDevices(void)
 #ifdef WITH_OPENCL
     std::vector<cl::Platform> platforms;
     cl::Platform::get(&platforms);
-    platforms.erase(platforms.begin() + 1);
+    //platforms.erase(platforms.begin() + 1);
 
     for (auto& platform : platforms) {
         std::string name = platform.getInfo<CL_PLATFORM_NAME>();