diff --git a/.gitignore b/.gitignore index e31839a..b4e9b6f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ *.exe /.idea/ -/*build*/ \ No newline at end of file +/*build*/ +/.vs/ \ No newline at end of file diff --git a/programs/lab1/src/main.cpp b/programs/lab1/src/main.cpp index 1261949..3f88957 100644 --- a/programs/lab1/src/main.cpp +++ b/programs/lab1/src/main.cpp @@ -1,8 +1,7 @@ -#include #include #include +#include #include -#include #include #include #include @@ -10,10 +9,36 @@ int main(int argc, char **argv) { QApplication qApplication{argc, argv}; - qRegisterMetaType("OwnedQImage"); +// qRegisterMetaType("OwnedQImage"); + QTimer fps_timeout; + unsigned frames = 0; + fps_timeout.callOnTimeout([&] { + qCritical() << (frames * 4) << "\n"; + qDebug() << (frames * 4) << "\n"; + frames = 0; + }); + fps_timeout.setInterval(250); + fps_timeout.start(); QMainWindow w{}; + class o : public QObject { + public: + unsigned *frames; + + explicit o(unsigned *f) : QObject{}, frames{f} {} + + public slots: + + void hit() { + (*this->frames)++; + } + }; + + + o oo{&frames}; + BGTU::ComputerGraphicsLabWork::QtUtilities::SeparateThreadedDefaultRendererLinear renderer{}; + QObject::connect(&renderer, &BGTU::ComputerGraphicsLabWork::QtUtilities::_SeparateThreadedRenderer_Signals::frame_rendered, &oo, &o::hit); renderer.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0}); BGTU::ComputerGraphicsLabWork::QtUtilities::RendererWidget canvas{&renderer, &w}; w.setCentralWidget(&canvas); diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_renderer_widget.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_renderer_widget.hpp index 25b3669..1a57cb1 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_renderer_widget.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_renderer_widget.hpp @@ -31,7 +31,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { private slots: - virtual void receive_image(OwnedQImage img) = 0; + virtual void receive_image(OwnedQImage *img) = 0; }; } \ No newline at end of file diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_separate_threaded_renderer.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_separate_threaded_renderer.hpp index fbb790c..b9badb7 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_separate_threaded_renderer.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_separate_threaded_renderer.hpp @@ -13,13 +13,16 @@ #include "owned_qimage.hpp" namespace BGTU::ComputerGraphicsLabWork::QtUtilities { - template *const *, std::size_t, sprite_data_t const *)> + template + using _SeparateThreadedRenderer_RenderProcedureType = void (renderer_context_t::*)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite *const *, std::size_t, sprite_data_t const *); + + template> class SeparateThreadedRenderer; class _SeparateThreadedRenderer_Signals : public QObject { Q_OBJECT - template *const *, std::size_t, sprite_data_t const *)> + template> friend class SeparateThreadedRenderer; @@ -27,6 +30,16 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { explicit _SeparateThreadedRenderer_Signals(QObject *owner = nullptr) : QObject{owner} {} signals: - void frame_rendered(OwnedQImage img); + + void frame_rendered(OwnedQImage *img); + + public slots: + + virtual void set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height) = 0; + + virtual void set_ms_per_frame(std::uint_fast64_t ms) = 0; + + virtual void set_background(RendererApi::Color) = 0; + }; } \ No newline at end of file diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp index c72c94a..9f5718d 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -30,6 +31,31 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { OwnedQImage() : QImage(), owners{nullptr} {} + OwnedQImage &operator=(OwnedQImage const ©) { + if (this == ©) + return *this; + if (this->owners != nullptr) + delete[] this->owners; + if (copy.owners == nullptr) { + this->owners = nullptr; + } else { + this->owners = new RendererApi::SpriteMetadata const *[copy.width() * copy.height()]; + std::memcpy(this->owners, copy.owners, copy.width() * copy.height() * sizeof(RendererApi::SpriteMetadata const *)); + } + return *this; + } + + OwnedQImage(OwnedQImage const ©) : QImage{copy} { + *this = copy; + } + + OwnedQImage(OwnedQImage &&move) noexcept : QImage{std::move(move)} { + if (this->owners != nullptr) + delete[] this->owners; + this->owners = move.owners; + move.owners = nullptr; + } + void setPixelOwner(unsigned x, unsigned y, RendererApi::SpriteMetadata const *o) { assert(x < this->width()); @@ -51,8 +77,10 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { } ~OwnedQImage() override { - if (this->owners != nullptr) + if (this->owners != nullptr) { delete[] this->owners; + this->owners = nullptr; + } } }; } \ No newline at end of file diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp index 2f283eb..9712560 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include "owned_qimage.hpp" #include "separate_threaded_renderer.hpp" @@ -21,15 +23,17 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { class RendererWidget : public _RendererWidget_Slots { private: QMutex sync; - OwnedQImage next_image; - OwnedQImage current_image; + OwnedQImage *next_image; + OwnedQImage *current_image; _SeparateThreadedRenderer_Signals *renderer; private slots: - void receive_image(OwnedQImage img) { + void receive_image(BGTU::ComputerGraphicsLabWork::QtUtilities::OwnedQImage *img) final { this->sync.lock(); - std::swap(this->next_image, img); + if (this->next_image != nullptr) + delete this->next_image; + this->next_image = img; this->sync.unlock(); this->update(); } @@ -43,16 +47,26 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { protected: void paintEvent(QPaintEvent *event) final { this->sync.lock(); - this->current_image = std::move(this->next_image); + if (this->next_image != nullptr) { + if (this->current_image != nullptr) + delete this->current_image; + this->current_image = this->next_image; + this->next_image = nullptr; + } this->sync.unlock(); QPainter painter; painter.begin(this); painter.setPen(Qt::NoPen); painter.setBrush(QApplication::style()->standardPalette().brush(QPalette::Background)); - painter.drawRect(this->rect().x(), this->rect().y(), this->rect().width()-1, this->rect().height()-1); - painter.drawImage(this->current_image.rect(), this->current_image); + painter.drawRect(this->rect().x(), this->rect().y(), this->rect().width() - 1, this->rect().height() - 1); + if (this->current_image != nullptr) + painter.drawImage(this->current_image->rect(), *this->current_image); painter.end(); } + + void resizeEvent(QResizeEvent *event) override { + this->renderer->set_frame_size(event->size().width(), event->size().height()); + } }; } \ No newline at end of file diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp index 98b6a77..4692b12 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp @@ -15,10 +15,10 @@ #include "_separate_threaded_renderer.hpp" namespace BGTU::ComputerGraphicsLabWork::QtUtilities { - template *const *, std::size_t, sprite_data_t const *)> + template renderer_procedure> class SeparateThreadedRenderer : public _SeparateThreadedRenderer_Signals { private: - struct data { + struct data_t { public: RendererApi::Sprite *const *sprites; std::size_t sprites_count; @@ -44,6 +44,10 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { this->intr.wakeAll(); } + void force_redraw() { + this->intr.wakeAll(); + } + protected: void run() final; @@ -57,7 +61,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { }; - volatile data next_data; + volatile data_t next_data; QMutex sync; RendererThread *thread; QImage *sentinel_img; @@ -67,9 +71,9 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { public slots: - void set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height); + void set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height) final; - void set_ms_per_frame(std::uint_fast64_t ms); + void set_ms_per_frame(std::uint_fast64_t ms) final; void set_sprites(RendererApi::Sprite *const *sprites, std::size_t sprites_count); @@ -77,14 +81,14 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { void set_sprites_and_data(RendererApi::Sprite *const *sprites, std::size_t sprites_count, sprite_data_t const *data); - void set_background(RendererApi::Color); + void set_background(RendererApi::Color) final; public: ~SeparateThreadedRenderer(); }; - template *const *, std::size_t, sprite_data_t const *)> + template renderer_procedure> SeparateThreadedRenderer::SeparateThreadedRenderer(renderer_context_t *renderer_context, QObject *owner): _SeparateThreadedRenderer_Signals{owner}, sync{}, @@ -103,74 +107,81 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { this->thread->start(); } - template *const *, std::size_t, sprite_data_t const *)> + template renderer_procedure> void SeparateThreadedRenderer::set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height) { this->sync.lock(); - const_cast(&this->next_data)->width = width; - const_cast(&this->next_data)->height = height; + const_cast(&this->next_data)->width = width; + const_cast(&this->next_data)->height = height; + this->thread->force_redraw(); this->sync.unlock(); } - template *const *, std::size_t, sprite_data_t const *)> + template renderer_procedure> void SeparateThreadedRenderer::set_ms_per_frame(std::uint_fast64_t ms) { this->sync.lock(); - const_cast(&this->next_data)->ms_per_frame = ms; + const_cast(&this->next_data)->ms_per_frame = ms; this->sync.unlock(); } - template *const *, std::size_t, sprite_data_t const *)> + template renderer_procedure> void SeparateThreadedRenderer::set_sprites(RendererApi::Sprite *const *sprites, std::size_t sprites_count) { this->sync.lock(); - const_cast(&this->next_data)->sprites = sprites; - const_cast(&this->next_data)->sprites_count = sprites_count; + const_cast(&this->next_data)->sprites = sprites; + const_cast(&this->next_data)->sprites_count = sprites_count; + this->thread->force_redraw(); this->sync.unlock(); } - template *const *, std::size_t, sprite_data_t const *)> + template renderer_procedure> void SeparateThreadedRenderer::set_sprite_data(sprite_data_t const *sprite_data) { this->sync.lock(); - const_cast(&this->next_data)->sprite_data = sprite_data; + const_cast(&this->next_data)->sprite_data = sprite_data; + this->thread->force_redraw(); this->sync.unlock(); } - template *const *, std::size_t, sprite_data_t const *)> + template renderer_procedure> void SeparateThreadedRenderer::set_sprites_and_data(RendererApi::Sprite *const *sprites, std::size_t sprites_count, sprite_data_t const *sprite_data) { this->sync.lock(); - const_cast(&this->next_data)->sprites = sprites; - const_cast(&this->next_data)->sprites_count = sprites_count; - const_cast(&this->next_data)->sprite_data = sprite_data; + const_cast(&this->next_data)->sprites = sprites; + const_cast(&this->next_data)->sprites_count = sprites_count; + const_cast(&this->next_data)->sprite_data = sprite_data; + this->thread->force_redraw(); this->sync.unlock(); } - template *const *, std::size_t, sprite_data_t const *)> + template renderer_procedure> void SeparateThreadedRenderer::set_background(RendererApi::Color c) { this->sync.lock(); - const_cast(&this->next_data)->bg = c; + const_cast(&this->next_data)->bg = c; + this->thread->force_redraw(); this->sync.unlock(); } - template *const *, std::size_t, sprite_data_t const *)> + template renderer_procedure> void SeparateThreadedRenderer::RendererThread::run() { try { QElapsedTimer timer; while (!this->isInterruptionRequested()) { timer.start(); this->owner->sync.lock(); - data cached = *const_cast(&this->owner->next_data); + data_t cached = *const_cast(&this->owner->next_data); this->owner->sync.unlock(); - OwnedQImage img{cached.width, cached.height}; + auto img = new OwnedQImage{cached.width, cached.height}; (this->owner->renderer_context->*renderer_procedure)( cached.width, cached.height, - &img, + img, cached.bg, cached.projection, cached.sprites, cached.sprites_count, cached.sprite_data ); emit this->owner->frame_rendered(img); - this->sleepms(std::max(cached.ms_per_frame - static_cast(timer.elapsed()), 0)); + auto elapsed = timer.elapsed(); + qCritical() << elapsed << "ms"; + this->sleepms(std::max(static_cast(cached.ms_per_frame) - elapsed, 0)); } } catch (std::exception const &e) { qCritical() << typeid(e).name() << ": " << e.what() << "\n" << "Renderer thread died" << "\n"; @@ -178,7 +189,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { } - template *const *, std::size_t, sprite_data_t const *)> + template renderer_procedure> SeparateThreadedRenderer::~SeparateThreadedRenderer() { this->thread->requestInterruption(); this->thread->wait(); diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp index 5649744..95732b3 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp @@ -228,6 +228,10 @@ namespace BGTU::ComputerGraphicsLabWork { this->pixel_trace_elements_allocator.reset_allocations(); VoxelDrawerImpl painter{w, h, this->pixel_metadata_cache.buffer, &this->pixel_trace_elements_allocator}; + for (std::int_fast64_t i = w * h - 1; i >= 0; i--) { + new(&this->pixel_metadata_cache.buffer[i]) pixel_trace_metadata{}; + } + for (; sprites_count-- > 0; sprites++) { painter.current_artist = *sprites; (*sprites)->draw(&painter, projection, sprite_data); @@ -237,15 +241,19 @@ namespace BGTU::ComputerGraphicsLabWork { std::uint_fast16_t x = 0; for (std::int_fast64_t i = w * h - 1; i >= 0; i--) { + this->sorter.clear(); for (ZElement *e = this->pixel_metadata_cache.buffer[i].voxels; e != nullptr; e = e->next) { - sorter.push_back(e); + this->sorter.push_back(e); } - std::sort(sorter.rbegin(), sorter.rend(), [](ZElement *l, ZElement *r) { return l->z < r->z; }); + std::sort(this->sorter.begin(), this->sorter.end(), [](ZElement *l, ZElement *r) { return l->z > r->z; }); RendererApi::Color p = bg; - for (auto a: sorter) { + for (auto a: this->sorter) { p = apply_transparent_color(p, a->color); } - frame->set_pixel(x, y, p, sorter[sorter.size() - 1]->owner); + if (this->sorter.empty()) + frame->set_pixel(x, y, p, nullptr); + else + frame->set_pixel(x, y, p, this->sorter[this->sorter.size() - 1]->owner); if (++x >= w) { y++; diff --git a/utilities/src/memory_pages_management.cpp b/utilities/src/memory_pages_management.cpp index bd7f49a..3143ddd 100644 --- a/utilities/src/memory_pages_management.cpp +++ b/utilities/src/memory_pages_management.cpp @@ -1,7 +1,8 @@ -#include +#include #include #include #include +#include #if defined(_WIN32)