Compilable and runnable example
This commit is contained in:
parent
08ced011c6
commit
52561c8004
@ -6,6 +6,16 @@ set(CMAKE_CXX_STANDARD 20)
|
|||||||
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui)
|
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui)
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
|
enable_language(ASM_NASM)
|
||||||
|
|
||||||
|
option(__AVX2__ "Tells compiler to use AVX2 extension if possible" OFF)
|
||||||
|
|
||||||
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
if (__AVX2__)
|
||||||
|
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/arch:AVX2>)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
add_executable(
|
add_executable(
|
||||||
cg1
|
cg1
|
||||||
|
|
||||||
@ -27,4 +37,5 @@ qt5_use_modules(cg1 Widgets)
|
|||||||
|
|
||||||
add_subdirectory(renderer-api)
|
add_subdirectory(renderer-api)
|
||||||
add_subdirectory(utilities)
|
add_subdirectory(utilities)
|
||||||
add_subdirectory(qt-utilities)
|
add_subdirectory(qt-utilities)
|
||||||
|
add_subdirectory(programs/lab1)
|
2
programs/lab1/CMakeLists.txt
Normal file
2
programs/lab1/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
add_executable(lab1 src/main.cpp)
|
||||||
|
target_link_libraries(lab1 PRIVATE Qt5::Core Qt5::Widgets renderer_api utilities qt_utilities)
|
19
programs/lab1/src/main.cpp
Normal file
19
programs/lab1/src/main.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
|
||||||
|
#include <bgtu/computer_graphics_lab_work/utilities/color.hpp>
|
||||||
|
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
|
||||||
|
#include <bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
QApplication qApplication{argc, argv};
|
||||||
|
QMainWindow w{};
|
||||||
|
|
||||||
|
BGTU::ComputerGraphicsLabWork::QtUtilities::SeparateThreadedDefaultRendererLinear<void> renderer{};
|
||||||
|
BGTU::ComputerGraphicsLabWork::QtUtilities::RendererWidget<void> canvas{&renderer, &w};
|
||||||
|
w.setCentralWidget(&canvas);
|
||||||
|
w.show();
|
||||||
|
QApplication::exec();
|
||||||
|
}
|
@ -1,3 +1,3 @@
|
|||||||
add_library(qt_utilities OBJECT src/separate_threaded_renderer.cpp)
|
add_library(qt_utilities OBJECT include/bgtu/computer_graphics_lab_work/qt_utilities/_separate_threaded_renderer.hpp include/bgtu/computer_graphics_lab_work/qt_utilities/_renderer_widget.hpp)
|
||||||
target_include_directories(qt_utilities PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
target_include_directories(qt_utilities PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
target_link_libraries(qt_utilities PUBLIC Qt5::Core Qt5::Widgets Qt5::Gui renderer_api utilities)
|
target_link_libraries(qt_utilities PUBLIC Qt5::Core Qt5::Widgets Qt5::Gui renderer_api utilities)
|
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <Qt>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QBrush>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QPalette>
|
||||||
|
#include <QStyle>
|
||||||
|
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
|
||||||
|
#include "owned_qimage.hpp"
|
||||||
|
#include "separate_threaded_renderer.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
||||||
|
template<class sprite_data_t>
|
||||||
|
class RendererWidget;
|
||||||
|
|
||||||
|
class _RendererWidget_Slots : public QWidget {
|
||||||
|
template<class>
|
||||||
|
friend
|
||||||
|
class RendererWidget;
|
||||||
|
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline _RendererWidget_Slots(QWidget *owner) : QWidget{owner} {}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
virtual void receive_image(OwnedQImage<void> img) = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <Qt>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp>
|
||||||
|
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
||||||
|
#include "owned_qimage.hpp"
|
||||||
|
|
||||||
|
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
||||||
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
|
class SeparateThreadedRenderer;
|
||||||
|
|
||||||
|
class _SeparateThreadedRenderer_Signals : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
|
friend
|
||||||
|
class SeparateThreadedRenderer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit _SeparateThreadedRenderer_Signals(QObject *owner = nullptr) : QObject{owner} {}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void frame_rendered(OwnedQImage<void> img);
|
||||||
|
};
|
||||||
|
}
|
@ -4,6 +4,9 @@
|
|||||||
#include <Qt>
|
#include <Qt>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
|
#include <QColor>
|
||||||
|
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
|
||||||
|
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
|
||||||
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp>
|
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp>
|
||||||
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
||||||
|
|
||||||
@ -11,15 +14,18 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
|||||||
template<class sprite_data_t>
|
template<class sprite_data_t>
|
||||||
class OwnedQImage : public QImage, public RendererApi::VoxelDrawer::Exporter<sprite_data_t> {
|
class OwnedQImage : public QImage, public RendererApi::VoxelDrawer::Exporter<sprite_data_t> {
|
||||||
private:
|
private:
|
||||||
RendererApi::Sprite<sprite_data_t> const *owners;
|
RendererApi::Sprite<sprite_data_t> const **owners;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OwnedQImage(unsigned width, unsigned height) : QImage(width, height, QImage::Format_ARGB32), owners{new RendererApi::Sprite<sprite_data_t> const *[width * height]} {
|
OwnedQImage(unsigned width, unsigned height) : QImage(width, height, QImage::Format_ARGB32), owners{new RendererApi::Sprite<sprite_data_t> const *[width * height]} {
|
||||||
for (RendererApi::Sprite<sprite_data_t> const *&e: this->owners) {
|
for (RendererApi::Sprite<sprite_data_t> const **p = this->owners - 1; p-- >= this->owners;) {
|
||||||
e = nullptr;
|
*p = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OwnedQImage() : QImage(), owners{nullptr} {}
|
||||||
|
|
||||||
|
|
||||||
void setPixelOwner(unsigned x, unsigned y, RendererApi::Sprite<sprite_data_t> const *o) {
|
void setPixelOwner(unsigned x, unsigned y, RendererApi::Sprite<sprite_data_t> const *o) {
|
||||||
assert(x < this->width());
|
assert(x < this->width());
|
||||||
assert(y < this->height());
|
assert(y < this->height());
|
||||||
@ -33,5 +39,15 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
|||||||
|
|
||||||
return this->owners[y * this->width() + x];
|
return this->owners[y * this->width() + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_pixel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, RendererApi::Color c, RendererApi::Sprite<sprite_data_t> const *owner) final {
|
||||||
|
this->setPixelColor(x, y, QColor{c.red, c.green, c.blue});
|
||||||
|
this->setPixelOwner(x, y, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
~OwnedQImage() override {
|
||||||
|
if (this->owners != nullptr)
|
||||||
|
delete[] this->owners;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -1,22 +1,57 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <Qt>
|
#include <Qt>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QBrush>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QPalette>
|
||||||
|
#include <QStyle>
|
||||||
|
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
|
||||||
#include "owned_qimage.hpp"
|
#include "owned_qimage.hpp"
|
||||||
#include "separate_threaded_renderer.hpp"
|
#include "separate_threaded_renderer.hpp"
|
||||||
|
#include "_renderer_widget.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
||||||
template<class sprite_data_t>
|
template<class sprite_data_t>
|
||||||
class RendererWidget : public QWidget {
|
class RendererWidget : public _RendererWidget_Slots {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMutex sync;
|
QMutex sync;
|
||||||
OwnedQImage <sprite_data_t> *next_image;
|
OwnedQImage<void> next_image;
|
||||||
OwnedQImage <sprite_data_t> *current_image;
|
OwnedQImage<void> current_image;
|
||||||
SeparateThreadedRenderer
|
_SeparateThreadedRenderer_Signals *renderer;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void receive_image(OwnedQImage<void> img) {
|
||||||
|
this->sync.lock();
|
||||||
|
std::swap(this->next_image, img);
|
||||||
|
this->sync.unlock();
|
||||||
|
this->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RendererWidget(_SeparateThreadedRenderer_Signals *renderer, QWidget *owner = nullptr) : _RendererWidget_Slots{owner}, sync{}, next_image{}, current_image{}, renderer{renderer} {
|
||||||
|
connect(this->renderer, &_SeparateThreadedRenderer_Signals::frame_rendered, this, &_RendererWidget_Slots::receive_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *event) final {
|
||||||
|
this->sync.lock();
|
||||||
|
this->current_image = std::move(this->next_image);
|
||||||
|
this->sync.unlock();
|
||||||
|
|
||||||
|
QPainter painter;
|
||||||
|
painter.begin(this);
|
||||||
|
painter.setBrush(QApplication::style()->standardPalette().brush(QPalette::Background));
|
||||||
|
painter.drawRect(this->rect());
|
||||||
|
painter.drawImage(this->current_image.rect(), this->current_image);
|
||||||
|
painter.end();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
#include <Qt>
|
#include <Qt>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
@ -9,10 +11,11 @@
|
|||||||
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp>
|
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp>
|
||||||
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
||||||
#include "owned_qimage.hpp"
|
#include "owned_qimage.hpp"
|
||||||
|
#include "_separate_threaded_renderer.hpp"
|
||||||
|
|
||||||
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
||||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
class SeparateThreadedRenderer : public QObject {
|
class SeparateThreadedRenderer : public _SeparateThreadedRenderer_Signals {
|
||||||
private:
|
private:
|
||||||
struct data {
|
struct data {
|
||||||
public:
|
public:
|
||||||
@ -22,10 +25,10 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
|||||||
std::uint_fast64_t ms_per_frame;
|
std::uint_fast64_t ms_per_frame;
|
||||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, height;
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, height;
|
||||||
RendererApi::Projection *projection;
|
RendererApi::Projection *projection;
|
||||||
|
RendererApi::Color bg;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RendererThread : public QThread {
|
class RendererThread : public QThread {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SeparateThreadedRenderer *owner;
|
SeparateThreadedRenderer *owner;
|
||||||
@ -58,14 +61,13 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
|||||||
|
|
||||||
void set_sprites_and_data(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count, sprite_data_t const *data);
|
void set_sprites_and_data(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count, sprite_data_t const *data);
|
||||||
|
|
||||||
signals:
|
void set_background(RendererApi::Color);
|
||||||
|
|
||||||
void frame_rendered(OwnedQImage<sprite_data_t> *img);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
|
||||||
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::SeparateThreadedRenderer(renderer_context_t *renderer_context, QObject *owner):
|
SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::SeparateThreadedRenderer(renderer_context_t *renderer_context, QObject *owner):
|
||||||
QObject{owner},
|
_SeparateThreadedRenderer_Signals{owner},
|
||||||
sync{},
|
sync{},
|
||||||
renderer_context{renderer_context},
|
renderer_context{renderer_context},
|
||||||
sentinel_img{new QImage(0, 0, QImage::Format_ARGB32)},
|
sentinel_img{new QImage(0, 0, QImage::Format_ARGB32)},
|
||||||
@ -81,7 +83,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
|||||||
} {
|
} {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height) {
|
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height) {
|
||||||
this->sync.lock();
|
this->sync.lock();
|
||||||
this->next_data.width = width;
|
this->next_data.width = width;
|
||||||
@ -89,14 +91,14 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
|||||||
this->sync.unlock();
|
this->sync.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_ms_per_frame(std::uint_fast64_t ms) {
|
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_ms_per_frame(std::uint_fast64_t ms) {
|
||||||
this->sync.lock();
|
this->sync.lock();
|
||||||
this->next_data.ms_per_frame = ms;
|
this->next_data.ms_per_frame = ms;
|
||||||
this->sync.unlock();
|
this->sync.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprites(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count) {
|
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprites(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count) {
|
||||||
this->sync.lock();
|
this->sync.lock();
|
||||||
this->next_data.sprites = sprites;
|
this->next_data.sprites = sprites;
|
||||||
@ -104,14 +106,14 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
|||||||
this->sync.unlock();
|
this->sync.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprite_data(sprite_data_t const *data) {
|
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprite_data(sprite_data_t const *data) {
|
||||||
this->sync.lock();
|
this->sync.lock();
|
||||||
this->next_data.sprite_data = data;
|
this->next_data.sprite_data = data;
|
||||||
this->sync.unlock();
|
this->sync.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprites_and_data(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count, sprite_data_t const *data) {
|
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprites_and_data(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count, sprite_data_t const *data) {
|
||||||
this->sync.lock();
|
this->sync.lock();
|
||||||
this->next_data.sprites = sprites;
|
this->next_data.sprites = sprites;
|
||||||
@ -120,20 +122,35 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
|||||||
this->sync.unlock();
|
this->sync.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
|
||||||
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
|
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_background(RendererApi::Color c) {
|
||||||
|
this->sync.lock();
|
||||||
|
this->next_data.bg = c;
|
||||||
|
this->sync.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::RendererThread::run() {
|
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::RendererThread::run() {
|
||||||
try {
|
try {
|
||||||
QElapsedTimer timer;
|
QElapsedTimer timer;
|
||||||
while (true) {
|
while (true) {
|
||||||
timer.start();
|
timer.start();
|
||||||
this->owner->sync.lock();
|
this->owner->sync.lock();
|
||||||
data cached = this->owner->next_data;
|
data cached = *const_cast<data *>(&this->owner->next_data);
|
||||||
this->owner->sync.unlock();
|
this->owner->sync.unlock();
|
||||||
|
|
||||||
auto img = new OwnedQImage<sprite_data_t>(cached.width, cached.height);
|
OwnedQImage<sprite_data_t> img{cached.width, cached.height};
|
||||||
(this->owner->renderer_context->*renderer_procedure)(img, cached.sprite_data, cached.sprites, cached.sprites_count);
|
(this->owner->renderer_context->*renderer_procedure)(
|
||||||
emit this->owner->frame_rendered(img);
|
cached.width, cached.height,
|
||||||
QThread::msleep(std::max(cached.ms_per_frame - timer.elapsed(), 0));
|
&img,
|
||||||
|
cached.bg,
|
||||||
|
cached.projection,
|
||||||
|
cached.sprites, cached.sprites_count,
|
||||||
|
cached.sprite_data
|
||||||
|
);
|
||||||
|
emit this->owner->frame_rendered(std::move(*reinterpret_cast<OwnedQImage<void> *>(&img)));
|
||||||
|
QThread::msleep(std::max<std::uint_fast64_t>(cached.ms_per_frame - static_cast<std::uint_fast64_t>(timer.elapsed()), 0));
|
||||||
}
|
}
|
||||||
} catch (std::exception const &e) {
|
} catch (std::exception const &e) {
|
||||||
qCritical() << typeid(e).name() << ": " << e.what() << "\n" << "Renderer thread died" << "\n";
|
qCritical() << typeid(e).name() << ": " << e.what() << "\n" << "Renderer thread died" << "\n";
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
#include <bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp>
|
|
||||||
#include <bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp>
|
|
||||||
#include <bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp>
|
|
||||||
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
|
|
@ -7,7 +7,7 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
|
|||||||
template<class data_t>
|
template<class data_t>
|
||||||
class Sprite {
|
class Sprite {
|
||||||
public:
|
public:
|
||||||
virtual void draw(VoxelDrawer *frame, Projection *projection, data_t *data) const = 0;
|
virtual void draw(VoxelDrawer *frame, Projection const *projection, data_t const *data) const = 0;
|
||||||
|
|
||||||
virtual void clicked() {};
|
virtual void clicked() {};
|
||||||
};
|
};
|
||||||
|
@ -33,6 +33,7 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
|
|||||||
|
|
||||||
template<class sprite_data_t>
|
template<class sprite_data_t>
|
||||||
class Exporter {
|
class Exporter {
|
||||||
|
public:
|
||||||
virtual void set_pixel(PointI<2>::component_t x, PointI<2>::component_t y, Color c, Sprite<sprite_data_t> const* owner) = 0;
|
virtual void set_pixel(PointI<2>::component_t x, PointI<2>::component_t y, Color c, Sprite<sprite_data_t> const* owner) = 0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
add_library(utilities OBJECT src/shader.cpp src/memory_pages_managment.cpp)
|
add_library(utilities OBJECT src/shader.cpp src/memory_pages_management.cpp src/default_renderer_linear.cpp src/color.asm)
|
||||||
target_include_directories(utilities PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
target_include_directories(utilities PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
target_link_libraries(utilities PUBLIC renderer_api)
|
target_link_libraries(utilities PUBLIC renderer_api)
|
@ -1,13 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
// #include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
|
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||||
RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) {
|
inline RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) {
|
||||||
|
#if defined(__AVX512F__)
|
||||||
|
return _apply_transparent_color_avx512(bg, fg);
|
||||||
|
#elif 0 && defined(__AVX2__)
|
||||||
|
return _apply_transparent_color_avx2(bg, fg);
|
||||||
|
#else
|
||||||
#if 1
|
#if 1
|
||||||
|
return RendererApi::Color{
|
||||||
|
static_cast<RendererApi::Color::component_fast_t>(((static_cast<std::uint_fast16_t>(fg.red) * static_cast<std::uint_fast16_t>(fg.alpha) + static_cast<std::uint_fast16_t>(bg.red) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||||
|
static_cast<RendererApi::Color::component_fast_t>(((static_cast<std::uint_fast16_t>(fg.green) * static_cast<std::uint_fast16_t>(fg.alpha) + static_cast<std::uint_fast16_t>(bg.green) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||||
|
static_cast<RendererApi::Color::component_fast_t>(((static_cast<std::uint_fast16_t>(fg.blue) * static_cast<std::uint_fast16_t>(fg.alpha) + static_cast<std::uint_fast16_t>(bg.blue) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||||
|
};
|
||||||
|
#elif 1
|
||||||
static auto calc = [&](RendererApi::Color::component_fast_t s, RendererApi::Color::component_fast_t o) {
|
static auto calc = [&](RendererApi::Color::component_fast_t s, RendererApi::Color::component_fast_t o) {
|
||||||
auto oo = static_cast<std::uint_fast16_t>(o) * static_cast<std::uint_fast16_t>(fg.alpha);
|
auto oo = static_cast<std::uint_fast16_t>(o) * static_cast<std::uint_fast16_t>(fg.alpha);
|
||||||
auto ss = static_cast<std::uint_fast16_t>(s) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha));
|
auto ss = static_cast<std::uint_fast16_t>(s) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha));
|
||||||
@ -25,14 +36,16 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
|||||||
__m128i vec_alpha = _mm_set_epi16(fg.alpha, fg.alpha, fg.alpha, 0, 0, 0, 0, 0);
|
__m128i vec_alpha = _mm_set_epi16(fg.alpha, fg.alpha, fg.alpha, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
union {
|
union {
|
||||||
std::uint_fast64_t packed = static_cast<std::uint_fast64_t>(_mm_cvtsi128_si64(_mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(vec_fg, vec_alpha), _mm_mullo_epi16(vec_bg, _mm_sub_epi16(vec_256, vec_alpha))), 8)));
|
__m128i packed;
|
||||||
std::uint16_t unpacked[3];
|
std::uint16_t unpacked[3];
|
||||||
} raw;
|
} raw;
|
||||||
|
_mm_storel_epi64(&raw.packed, _mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(vec_fg, vec_alpha), _mm_mullo_epi16(vec_bg, _mm_sub_epi16(vec_256, vec_alpha))), 8));
|
||||||
return RendererApi::Color{
|
return RendererApi::Color{
|
||||||
static_cast<RendererApi::Color::component_compact_t>(raw.unpacked[0]),
|
static_cast<RendererApi::Color::component_compact_t>(raw.unpacked[0]),
|
||||||
static_cast<RendererApi::Color::component_compact_t>(raw.unpacked[1]),
|
static_cast<RendererApi::Color::component_compact_t>(raw.unpacked[1]),
|
||||||
static_cast<RendererApi::Color::component_compact_t>(raw.unpacked[2])
|
static_cast<RendererApi::Color::component_compact_t>(raw.unpacked[2])
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -12,10 +13,11 @@
|
|||||||
#include "color.hpp"
|
#include "color.hpp"
|
||||||
#include "matrix.hpp"
|
#include "matrix.hpp"
|
||||||
|
|
||||||
|
class QObject;
|
||||||
|
|
||||||
namespace BGTU::ComputerGraphicsLabWork {
|
namespace BGTU::ComputerGraphicsLabWork {
|
||||||
namespace Utilities {
|
namespace Utilities {
|
||||||
class DefaultVoxelDrawerLinear : public RendererApi::VoxelDrawer {
|
class DefaultVoxelDrawerCache {
|
||||||
private:
|
private:
|
||||||
class ZElement {
|
class ZElement {
|
||||||
public:
|
public:
|
||||||
@ -53,7 +55,7 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
Cell buffer[0];
|
Cell buffer[0];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Page(Page *next, std::size_t capacity) : next{next}, initialized{0}, capacity{capacity} {};
|
explicit Page(Page *next, std::size_t capacity) : next{next}, initialized{0}, capacity{capacity}, buffer{} {};
|
||||||
|
|
||||||
Cell *try_allocate();
|
Cell *try_allocate();
|
||||||
|
|
||||||
@ -93,70 +95,84 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
~ZElementAllocationBuffer();
|
~ZElementAllocationBuffer();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _width;
|
|
||||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _height;
|
|
||||||
|
|
||||||
struct pixel_trace_metadata {
|
struct pixel_trace_metadata {
|
||||||
public:
|
public:
|
||||||
pixel_trace_metadata() : nearest_z{std::numeric_limits<double>::max()}, voxels{nullptr} {};
|
pixel_trace_metadata() : nearest_z{std::numeric_limits<double>::max()}, voxels{nullptr} {};
|
||||||
|
|
||||||
double nearest_z;
|
double nearest_z;
|
||||||
ZElement *voxels;
|
ZElement *voxels;
|
||||||
} *pixels_metadata;
|
|
||||||
|
|
||||||
ZElementAllocationBuffer allocator;
|
|
||||||
RendererApi::Sprite<void> *current_artist;
|
|
||||||
public:
|
|
||||||
inline DefaultVoxelDrawerLinear(std::uint_fast16_t width, std::uint_fast16_t height);
|
|
||||||
|
|
||||||
~DefaultVoxelDrawerLinear();
|
|
||||||
|
|
||||||
template<class data_t>
|
|
||||||
void set_current_artist(RendererApi::Sprite<data_t> *sprite) {
|
|
||||||
this->current_artist = reinterpret_cast<RendererApi::Sprite<void> *>(sprite);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline std::uint_fast16_t height() const final {
|
|
||||||
return this->_height;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] inline std::uint_fast16_t width() const final {
|
template<class sprite_data_t>
|
||||||
return this->_width;
|
class VoxelDrawerImpl : public RendererApi::VoxelDrawer {
|
||||||
}
|
public:
|
||||||
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _width;
|
||||||
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _height;
|
||||||
|
|
||||||
private:
|
pixel_trace_metadata *pixels_metadata;
|
||||||
|
|
||||||
pixel_trace_metadata *at(std::uint_fast16_t x, std::uint_fast16_t y) {
|
ZElementAllocationBuffer *pixel_trace_elements_allocator;
|
||||||
return &(this->pixels_metadata[y * this->_width + x]);
|
RendererApi::Sprite<sprite_data_t> *current_artist;
|
||||||
}
|
|
||||||
|
VoxelDrawerImpl(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height, pixel_trace_metadata *pixels_metadata, ZElementAllocationBuffer *pixel_trace_elements_allocator);
|
||||||
|
|
||||||
|
[[nodiscard]] RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width() const final {
|
||||||
|
return this->_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height() const final {
|
||||||
|
return this->_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_trace_metadata *at(std::uint_fast16_t x, std::uint_fast16_t y) {
|
||||||
|
return &(this->pixels_metadata[y * this->_width + x]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_voxel(long long x, long long y, double z, RendererApi::Color::Transparent c) final;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct {
|
||||||
|
pixel_trace_metadata *buffer;
|
||||||
|
std::size_t size;
|
||||||
|
} pixel_metadata_cache;
|
||||||
|
std::vector<ZElement *> sorter;
|
||||||
|
ZElementAllocationBuffer pixel_trace_elements_allocator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
DefaultVoxelDrawerCache();
|
||||||
|
|
||||||
void add_voxel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c) final;
|
template<class sprite_data_t>
|
||||||
|
void render(
|
||||||
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w,
|
||||||
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t h,
|
||||||
|
RendererApi::VoxelDrawer::Exporter<sprite_data_t> *frame,
|
||||||
|
RendererApi::Color bg,
|
||||||
|
RendererApi::Projection const *projection,
|
||||||
|
RendererApi::Sprite<sprite_data_t> *const *sprites,
|
||||||
|
std::size_t sprites_count,
|
||||||
|
sprite_data_t const *sprite_data
|
||||||
|
);
|
||||||
|
|
||||||
|
~DefaultVoxelDrawerCache();
|
||||||
private:
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
template<class sdata_t>
|
|
||||||
void export_(RendererApi::Color background, RendererApi::VoxelDrawer::Exporter<sdata_t> *receiver);
|
|
||||||
|
|
||||||
void release_resources();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Cell *DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Page::try_allocate() {
|
template<class sprite_data_t>
|
||||||
if (this->initialized < this->capacity) {
|
DefaultVoxelDrawerCache::VoxelDrawerImpl<sprite_data_t>::VoxelDrawerImpl(
|
||||||
Cell *cell = &(this->buffer[this->initialized++]);
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width,
|
||||||
return cell;
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height,
|
||||||
}
|
DefaultVoxelDrawerCache::pixel_trace_metadata *pixels_metadata,
|
||||||
return nullptr;
|
DefaultVoxelDrawerCache::ZElementAllocationBuffer *pixel_trace_elements_allocator
|
||||||
}
|
): _width{width},
|
||||||
|
_height{height},
|
||||||
|
pixels_metadata{pixels_metadata},
|
||||||
|
pixel_trace_elements_allocator{pixel_trace_elements_allocator},
|
||||||
|
current_artist{nullptr} {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class... args_t>
|
template<class... args_t>
|
||||||
DefaultVoxelDrawerLinear::ZElement *DefaultVoxelDrawerLinear::ZElementAllocationBuffer::alloc_elem(args_t... args) {
|
DefaultVoxelDrawerCache::ZElement *DefaultVoxelDrawerCache::ZElementAllocationBuffer::alloc_elem(args_t... args) {
|
||||||
auto cell = this->next_unallocated;
|
auto cell = this->next_unallocated;
|
||||||
if (cell != nullptr) {
|
if (cell != nullptr) {
|
||||||
this->next_unallocated = cell->empty.next_empty;
|
this->next_unallocated = cell->empty.next_empty;
|
||||||
@ -169,49 +185,8 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
return new(&(cell->allocated)) ZElement{args...};
|
return new(&(cell->allocated)) ZElement{args...};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class sprite_data_t>
|
||||||
void DefaultVoxelDrawerLinear::ZElementAllocationBuffer::free_elem(DefaultVoxelDrawerLinear::ZElement *e) {
|
void DefaultVoxelDrawerCache::VoxelDrawerImpl<sprite_data_t>::add_voxel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c) {
|
||||||
Cell *cell = reinterpret_cast<Cell *>(e);
|
|
||||||
cell->empty.next_empty = this->next_unallocated;
|
|
||||||
this->next_unallocated = cell;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultVoxelDrawerLinear::ZElementAllocationBuffer::release_resources() {
|
|
||||||
Page *p;
|
|
||||||
while (this->last_page != nullptr) {
|
|
||||||
p = this->last_page;
|
|
||||||
this->last_page = p->next;
|
|
||||||
this->_native_free_page(p);
|
|
||||||
}
|
|
||||||
this->next_unallocated = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultVoxelDrawerLinear::ZElementAllocationBuffer::reset_allocations() {
|
|
||||||
Page *p = this->last_page;
|
|
||||||
while (p != nullptr) {
|
|
||||||
p->reset_allocations();
|
|
||||||
p = p->next;
|
|
||||||
}
|
|
||||||
this->next_unallocated = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultVoxelDrawerLinear::ZElementAllocationBuffer::~ZElementAllocationBuffer() {
|
|
||||||
this->release_resources();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DefaultVoxelDrawerLinear::DefaultVoxelDrawerLinear(std::uint_fast16_t width, std::uint_fast16_t height) :
|
|
||||||
_width{width},
|
|
||||||
_height{height},
|
|
||||||
pixels_metadata{new pixel_trace_metadata[sizeof(ZElement) * width * height]{}},
|
|
||||||
allocator{},
|
|
||||||
current_artist{nullptr} {}
|
|
||||||
|
|
||||||
DefaultVoxelDrawerLinear::~DefaultVoxelDrawerLinear() {
|
|
||||||
delete[] this->pixels_metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultVoxelDrawerLinear::add_voxel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c) {
|
|
||||||
if (x < 0 || this->_width <= x) return;
|
if (x < 0 || this->_width <= x) return;
|
||||||
if (y < 0 || this->_height <= y) return;
|
if (y < 0 || this->_height <= y) return;
|
||||||
if (z < 0) return;
|
if (z < 0) return;
|
||||||
@ -224,35 +199,53 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
while (p->voxels != nullptr) {
|
while (p->voxels != nullptr) {
|
||||||
e = p->voxels;
|
e = p->voxels;
|
||||||
p->voxels = e->next;
|
p->voxels = e->next;
|
||||||
this->allocator.free_elem(e);
|
this->pixel_trace_elements_allocator->free_elem(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
p->voxels = this->allocator.alloc_elem(p->voxels, z, c, this->current_artist);
|
p->voxels = this->pixel_trace_elements_allocator->alloc_elem(p->voxels, z, c, this->current_artist);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultVoxelDrawerLinear::release_resources() {
|
template<class sprite_data_t>
|
||||||
this->allocator.release_resources();
|
void DefaultVoxelDrawerCache::render(
|
||||||
}
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w,
|
||||||
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t h,
|
||||||
|
RendererApi::VoxelDrawer::Exporter<sprite_data_t> *frame,
|
||||||
|
RendererApi::Color bg,
|
||||||
|
RendererApi::Projection const *projection,
|
||||||
|
RendererApi::Sprite<sprite_data_t> *const *sprites,
|
||||||
|
std::size_t sprites_count,
|
||||||
|
sprite_data_t const *sprite_data
|
||||||
|
) {
|
||||||
|
if (this->pixel_metadata_cache.buffer == nullptr || this->pixel_metadata_cache.size < w * h) {
|
||||||
|
this->pixel_metadata_cache.buffer = static_cast<pixel_trace_metadata *>(std::realloc(this->pixel_metadata_cache.buffer, w * h * sizeof(pixel_trace_metadata)));
|
||||||
|
this->pixel_metadata_cache.size = w * h;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->pixel_trace_elements_allocator.reset_allocations();
|
||||||
|
VoxelDrawerImpl<sprite_data_t> painter{w, h, this->pixel_metadata_cache.buffer, &this->pixel_trace_elements_allocator};
|
||||||
|
|
||||||
|
for (; sprites_count-- > 0; sprites++) {
|
||||||
|
painter.current_artist = *sprites;
|
||||||
|
(*sprites)->draw(&painter, projection, sprite_data);
|
||||||
|
}
|
||||||
|
|
||||||
template<class sdata_t>
|
|
||||||
void DefaultVoxelDrawerLinear::export_(RendererApi::Color background, RendererApi::VoxelDrawer::Exporter<sdata_t> *receiver) {
|
|
||||||
std::vector<ZElement *> sorter;
|
|
||||||
std::uint_fast16_t y = 0;
|
std::uint_fast16_t y = 0;
|
||||||
std::uint_fast16_t x = 0;
|
std::uint_fast16_t x = 0;
|
||||||
|
|
||||||
for (std::int_fast64_t i = this->_width * this->_height - 1; i >= 0; i--) {
|
for (std::int_fast64_t i = w * h - 1; i >= 0; i--) {
|
||||||
for (ZElement *e = this->pixels_metadata[i].voxels; e != nullptr; e = e->next) {
|
for (ZElement *e = this->pixel_metadata_cache.buffer[i].voxels; e != nullptr; e = e->next) {
|
||||||
sorter.push_back(e);
|
sorter.push_back(e);
|
||||||
}
|
}
|
||||||
std::sort(sorter.rbegin(), sorter.rend(), [](ZElement *l, ZElement *r) { return l->z < r->z; });
|
std::sort(sorter.rbegin(), sorter.rend(), [](ZElement *l, ZElement *r) { return l->z < r->z; });
|
||||||
RendererApi::Color p = background;
|
RendererApi::Color p = bg;
|
||||||
for (auto a: sorter) {
|
for (auto a: sorter) {
|
||||||
p = apply_transparent_color(p, a->color);
|
p = apply_transparent_color(p, a->color);
|
||||||
}
|
}
|
||||||
receiver->export_pixel(x, y, p, sorter[sorter.size() - 1]->owner);
|
frame->set_pixel(x, y, p, sorter[sorter.size() - 1]->owner);
|
||||||
if (++x >= this->_width) {
|
|
||||||
|
if (++x >= w) {
|
||||||
y++;
|
y++;
|
||||||
x = 0;
|
x = 0;
|
||||||
}
|
}
|
||||||
@ -261,40 +254,16 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace QtUtilities {
|
namespace QtUtilities {
|
||||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
|
||||||
class SeparateThreadedRenderer;
|
class SeparateThreadedRenderer;
|
||||||
|
|
||||||
#if 0
|
|
||||||
template<class sprite_data_t, bool _private_param>
|
|
||||||
class _SeparateThreadedDefaultRendererLinear {
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class sprite_data_t>
|
template<class sprite_data_t>
|
||||||
class _SeparateThreadedDefaultRendererLinear<sprite_data_t, false> {
|
class SeparateThreadedDefaultRendererLinear : public SeparateThreadedRenderer<sprite_data_t, Utilities::DefaultVoxelDrawerCache, &Utilities::DefaultVoxelDrawerCache::render<sprite_data_t>> {
|
||||||
template<class, bool>
|
|
||||||
friend
|
|
||||||
class _SeparateThreadedDefaultRendererLinear;
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_SeparateThreadedDefaultRendererLinear() = delete;
|
Utilities::DefaultVoxelDrawerCache context;
|
||||||
|
|
||||||
class Context : public Utilities::DefaultVoxelDrawerLinear<sprite_data_t> {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class _SeparateThreadedDefaultRendererLinear : public SeparateThreadedRenderer<sprite_data_t, SeparateThreadedDefaultRendererLinear < sprite_data_t>, &SeparateThreadedDefaultRendererLinear<sprite_data_t>::render
|
|
||||||
|
|
||||||
> {
|
|
||||||
public:
|
public:
|
||||||
|
explicit SeparateThreadedDefaultRendererLinear(QObject *owner = nullptr) : SeparateThreadedRenderer<sprite_data_t, Utilities::DefaultVoxelDrawerCache, &Utilities::DefaultVoxelDrawerCache::render<sprite_data_t>>{&this->context, owner} {};
|
||||||
void render(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t) {
|
};
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
81
utilities/src/color.asm
Normal file
81
utilities/src/color.asm
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
%define __MMX__ 1
|
||||||
|
%define __SSE__ 2
|
||||||
|
%define __SSE2__ 3
|
||||||
|
%define __SSE3__ 4
|
||||||
|
%define __SSSE3__ 5
|
||||||
|
%define __SSE4_1__ 6
|
||||||
|
%define __SSE4_2__ 7
|
||||||
|
%define __AVX__ 8
|
||||||
|
%define __AVX2__ 9
|
||||||
|
%define __FMA3__ 10
|
||||||
|
%define __AVX512F__ 11
|
||||||
|
%define __AMX__ 12
|
||||||
|
|
||||||
|
|
||||||
|
%macro impl_body 1
|
||||||
|
%ifidn __OUTPUT_FORMAT__, elf64
|
||||||
|
movd xmm0, edi
|
||||||
|
movd xmm1, esi
|
||||||
|
mov r8d, esi
|
||||||
|
%elifidn __OUTPUT_FORMAT__, win64
|
||||||
|
; movzx r9d, WORD [rdx]
|
||||||
|
; movzx r10d, BYTE [rdx+2]
|
||||||
|
; shl r10d, 16
|
||||||
|
; or r9d, r10d
|
||||||
|
movd xmm0, DWORD [rdx]
|
||||||
|
movd xmm1, r8d
|
||||||
|
%else
|
||||||
|
%error "Unsupported output format"
|
||||||
|
%endif
|
||||||
|
|
||||||
|
pmovzxbd xmm0, xmm0 ; 0-extend 8bit->32bit
|
||||||
|
pmovzxbd xmm1, xmm1 ; 0-extend 8bit->32bit
|
||||||
|
shr r8d, 24
|
||||||
|
%if %1 >= __AVX512F__
|
||||||
|
vpbroadcastd xmm2, r8d ; fill vector with 32bit values
|
||||||
|
%elif %1 >= __AVX2__
|
||||||
|
movd xmm2, r8d
|
||||||
|
vpbroadcastd xmm2, xmm2
|
||||||
|
%endif
|
||||||
|
mov r8d, 255
|
||||||
|
%if %1 >= __AVX512F__
|
||||||
|
vpbroadcastd xmm3, r8d ; fill vector with 32bit values
|
||||||
|
%elif %1 >= __AVX2__
|
||||||
|
movd xmm3, r8d
|
||||||
|
vpbroadcastd xmm3, xmm3
|
||||||
|
%endif
|
||||||
|
|
||||||
|
psubd xmm3, xmm2 ; sub 32bit integers
|
||||||
|
pmuludq xmm0, xmm3 ; mul unsigned 32bit integers
|
||||||
|
pmuludq xmm1, xmm2 ; mul unsigned 32bit integers
|
||||||
|
paddd xmm0, xmm1 ; add 32bit integers
|
||||||
|
psrld xmm0, 8 ; 0-shift 32bit integers right
|
||||||
|
|
||||||
|
pextrd r9d, xmm0, 0 ; extracts 32 bit integer
|
||||||
|
pextrd r10d, xmm0, 1 ; extracts 32 bit integer
|
||||||
|
pextrd r11d, xmm0, 2 ; extracts 32 bit integer
|
||||||
|
shl r10d, 8
|
||||||
|
shl r11d, 16
|
||||||
|
or r9d, r10d
|
||||||
|
or r9d, r11d
|
||||||
|
|
||||||
|
%ifidn __OUTPUT_FORMAT__, elf64
|
||||||
|
mov eax, r9d
|
||||||
|
%elifidn __OUTPUT_FORMAT__, win64
|
||||||
|
mov DWORD [rcx], r9d
|
||||||
|
%else
|
||||||
|
%error "Unsupported output format"
|
||||||
|
%endif
|
||||||
|
ret
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
|
||||||
|
section .text
|
||||||
|
|
||||||
|
|
||||||
|
; avx2
|
||||||
|
|
||||||
|
global ?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z ; msvc
|
||||||
|
|
||||||
|
?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z:
|
||||||
|
impl_body __AVX2__
|
53
utilities/src/default_renderer_linear.cpp
Normal file
53
utilities/src/default_renderer_linear.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#include <cstdlib>
|
||||||
|
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
|
||||||
|
|
||||||
|
namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||||
|
|
||||||
|
DefaultVoxelDrawerCache::ZElementAllocationBuffer::Cell *DefaultVoxelDrawerCache::ZElementAllocationBuffer::Page::try_allocate() {
|
||||||
|
if (this->initialized < this->capacity) {
|
||||||
|
Cell *cell = &(this->buffer[this->initialized++]);
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DefaultVoxelDrawerCache::ZElementAllocationBuffer::free_elem(DefaultVoxelDrawerCache::ZElement *e) {
|
||||||
|
Cell *cell = reinterpret_cast<Cell *>(e);
|
||||||
|
cell->empty.next_empty = this->next_unallocated;
|
||||||
|
this->next_unallocated = cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DefaultVoxelDrawerCache::ZElementAllocationBuffer::release_resources() {
|
||||||
|
Page *p;
|
||||||
|
while (this->last_page != nullptr) {
|
||||||
|
p = this->last_page;
|
||||||
|
this->last_page = p->next;
|
||||||
|
this->_native_free_page(p);
|
||||||
|
}
|
||||||
|
this->next_unallocated = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DefaultVoxelDrawerCache::ZElementAllocationBuffer::reset_allocations() {
|
||||||
|
Page *p = this->last_page;
|
||||||
|
while (p != nullptr) {
|
||||||
|
p->reset_allocations();
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
this->next_unallocated = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultVoxelDrawerCache::ZElementAllocationBuffer::~ZElementAllocationBuffer() {
|
||||||
|
this->release_resources();
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultVoxelDrawerCache::DefaultVoxelDrawerCache() : pixel_trace_elements_allocator{}, pixel_metadata_cache{.buffer = nullptr, .size = 0}, sorter{} {}
|
||||||
|
|
||||||
|
DefaultVoxelDrawerCache::~DefaultVoxelDrawerCache() {
|
||||||
|
if (this->pixel_metadata_cache.buffer != nullptr) {
|
||||||
|
std::free(this->pixel_metadata_cache.buffer);
|
||||||
|
this->pixel_metadata_cache.buffer = nullptr;
|
||||||
|
}
|
||||||
|
this->pixel_metadata_cache.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,14 +1,14 @@
|
|||||||
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
|
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||||
DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Page *DefaultVoxelDrawerLinear::ZElementAllocationBuffer::_native_extend() {
|
DefaultVoxelDrawerCache::ZElementAllocationBuffer::Page *DefaultVoxelDrawerCache::ZElementAllocationBuffer::_native_extend() {
|
||||||
SYSTEM_INFO si;
|
SYSTEM_INFO si;
|
||||||
GetSystemInfo(&si);
|
GetSystemInfo(&si);
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DefaultVoxelDrawerLinear::ZElementAllocationBuffer::_native_free_page(DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Page *p) {
|
void DefaultVoxelDrawerCache::ZElementAllocationBuffer::_native_free_page(DefaultVoxelDrawerCache::ZElementAllocationBuffer::Page *p) {
|
||||||
VirtualFree(p, 0, MEM_DECOMMIT | MEM_RELEASE);
|
VirtualFree(p, 0, MEM_DECOMMIT | MEM_RELEASE);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user