diff --git a/CMakeLists.txt b/CMakeLists.txt index 9eb2612..890d8e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ -cmake_minimum_required(VERSION 3.29) +cmake_minimum_required(VERSION 3.25) project(cg1) set(CMAKE_CXX_STANDARD 20) -find_package(Qt5Widgets REQUIRED) +find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui) set(CMAKE_AUTOMOC ON) add_executable( @@ -26,4 +26,5 @@ add_executable( qt5_use_modules(cg1 Widgets) add_subdirectory(renderer-api) -add_subdirectory(utilities) \ No newline at end of file +add_subdirectory(utilities) +add_subdirectory(qt-utilities) \ No newline at end of file diff --git a/qt-utilities/CMakeLists.txt b/qt-utilities/CMakeLists.txt new file mode 100644 index 0000000..f805a15 --- /dev/null +++ b/qt-utilities/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(qt_utilities OBJECT src/separate_threaded_renderer.cpp) +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) \ 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 new file mode 100644 index 0000000..c9a7af0 --- /dev/null +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace BGTU::ComputerGraphicsLabWork::QtUtilities { + template + class OwnedQImage : public QImage, public RendererApi::VoxelDrawer::Exporter { + private: + RendererApi::Sprite const *owners; + + public: + OwnedQImage(unsigned width, unsigned height) : QImage(width, height, QImage::Format_ARGB32), owners{new RendererApi::Sprite const *[width * height]} { + for (RendererApi::Sprite const *&e: this->owners) { + e = nullptr; + } + } + + void setPixelOwner(unsigned x, unsigned y, RendererApi::Sprite const *o) { + assert(x < this->width()); + assert(y < this->height()); + + this->owners[y * this->width() + x] = o; + } + + RendererApi::Sprite const *getPixelOwner(unsigned x, unsigned y) const { + assert(x < this->width()); + assert(y < this->height()); + + return this->owners[y * this->width() + x]; + } + }; +} \ 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 new file mode 100644 index 0000000..30c6f5b --- /dev/null +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include +#include +#include "owned_qimage.hpp" +#include "separate_threaded_renderer.hpp" + + +namespace BGTU::ComputerGraphicsLabWork::QtUtilities { + template + class RendererWidget : public QWidget { + Q_OBJECT + + private: + QMutex sync; + OwnedQImage *next_image; + OwnedQImage *current_image; + SeparateThreadedRenderer + }; +} \ 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 new file mode 100644 index 0000000..42d5b61 --- /dev/null +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp @@ -0,0 +1,143 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include "owned_qimage.hpp" + +namespace BGTU::ComputerGraphicsLabWork::QtUtilities { + template *, sprite_data_t *, RendererApi::Sprite *const *, std::size_t)> + class SeparateThreadedRenderer : public QObject { + private: + struct data { + public: + RendererApi::Sprite *const *sprites; + std::size_t sprites_count; + sprite_data_t const *sprite_data; + std::uint_fast64_t ms_per_frame; + RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, height; + RendererApi::Projection *projection; + }; + + class RendererThread : public QThread { + Q_OBJECT + + private: + SeparateThreadedRenderer *owner; + + public: + explicit inline RendererThread(SeparateThreadedRenderer *owner) : QThread{owner}, owner{owner} {}; + + protected: + void run() final; + }; + + + volatile data next_data; + QMutex sync; + RendererThread *thread; + QImage *sentinel_img; + renderer_context_t *renderer_context; + public: + explicit SeparateThreadedRenderer(renderer_context_t *renderer_context, QObject *owner = nullptr); + + public slots: + + void set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height); + + void set_ms_per_frame(std::uint_fast64_t ms); + + void set_sprites(RendererApi::Sprite *const *sprites, std::size_t sprites_count); + + void set_sprite_data(sprite_data_t const *data); + + void set_sprites_and_data(RendererApi::Sprite *const *sprites, std::size_t sprites_count, sprite_data_t const *data); + + signals: + + void frame_rendered(OwnedQImage *img); + }; + + template *, sprite_data_t *, RendererApi::Sprite *const *, std::size_t)> + SeparateThreadedRenderer::SeparateThreadedRenderer(renderer_context_t *renderer_context, QObject *owner): + QObject{owner}, + sync{}, + renderer_context{renderer_context}, + sentinel_img{new QImage(0, 0, QImage::Format_ARGB32)}, + thread{new RendererThread(this)}, + next_data{ + .sprites = nullptr, + .sprites_count = 0, + .sprite_data = nullptr, + .ms_per_frame = 1000 / 60, + .width = 0, + .height = 0, + .projection = nullptr + } { + } + + template *, sprite_data_t *, RendererApi::Sprite *const *, std::size_t)> + void SeparateThreadedRenderer::set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height) { + this->sync.lock(); + this->next_data.width = width; + this->next_data.height = height; + this->sync.unlock(); + } + + template *, sprite_data_t *, RendererApi::Sprite *const *, std::size_t)> + void SeparateThreadedRenderer::set_ms_per_frame(std::uint_fast64_t ms) { + this->sync.lock(); + this->next_data.ms_per_frame = ms; + this->sync.unlock(); + } + + template *, sprite_data_t *, RendererApi::Sprite *const *, std::size_t)> + void SeparateThreadedRenderer::set_sprites(RendererApi::Sprite *const *sprites, std::size_t sprites_count) { + this->sync.lock(); + this->next_data.sprites = sprites; + this->next_data.sprites_count = sprites_count; + this->sync.unlock(); + } + + template *, sprite_data_t *, RendererApi::Sprite *const *, std::size_t)> + void SeparateThreadedRenderer::set_sprite_data(sprite_data_t const *data) { + this->sync.lock(); + this->next_data.sprite_data = data; + this->sync.unlock(); + } + + template *, sprite_data_t *, RendererApi::Sprite *const *, std::size_t)> + void SeparateThreadedRenderer::set_sprites_and_data(RendererApi::Sprite *const *sprites, std::size_t sprites_count, sprite_data_t const *data) { + this->sync.lock(); + this->next_data.sprites = sprites; + this->next_data.sprites_count = sprites_count; + this->next_data.sprite_data = data; + this->sync.unlock(); + } + + template *, sprite_data_t *, RendererApi::Sprite *const *, std::size_t)> + void SeparateThreadedRenderer::RendererThread::run() { + try { + QElapsedTimer timer; + while (true) { + timer.start(); + this->owner->sync.lock(); + data cached = this->owner->next_data; + this->owner->sync.unlock(); + + auto img = new OwnedQImage(cached.width, cached.height); + (this->owner->renderer_context->*renderer_procedure)(img, cached.sprite_data, cached.sprites, cached.sprites_count); + emit this->owner->frame_rendered(img); + QThread::msleep(std::max(cached.ms_per_frame - timer.elapsed(), 0)); + } + } catch (std::exception const &e) { + qCritical() << typeid(e).name() << ": " << e.what() << "\n" << "Renderer thread died" << "\n"; + } + } + +} \ No newline at end of file diff --git a/qt-utilities/src/separate_threaded_renderer.cpp b/qt-utilities/src/separate_threaded_renderer.cpp new file mode 100644 index 0000000..77ce9d9 --- /dev/null +++ b/qt-utilities/src/separate_threaded_renderer.cpp @@ -0,0 +1,4 @@ +#include +#include +#include +#include diff --git a/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp b/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp index 9aa453c..65ed5d5 100644 --- a/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp +++ b/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp @@ -7,6 +7,9 @@ #include "point.hpp" namespace BGTU::ComputerGraphicsLabWork::RendererApi { + template + class Sprite; + class VoxelDrawer { public: using visible_pixel_coordinate_fast_t = std::uint_fast16_t; @@ -22,10 +25,15 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi { [[nodiscard]] virtual visible_pixel_coordinate_fast_t height() const = 0; - virtual void update_pixel(PointI<2>::component_t x, PointI<2>::component_t y, double z, Color::Transparent c) = 0; + virtual void add_voxel(PointI<2>::component_t x, PointI<2>::component_t y, double z, Color::Transparent c) = 0; - inline void update_pixel(PointI<2> p, double z, Color::Transparent c) { - return this->update_pixel(p.x, p.y, z, c); + inline void add_voxel(PointI<2> p, double z, Color::Transparent c) { + return this->add_voxel(p.x, p.y, z, c); } + + template + class Exporter { + virtual void set_pixel(PointI<2>::component_t x, PointI<2>::component_t y, Color c, Sprite const* owner) = 0; + }; }; } \ No newline at end of file diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt index c4e6e18..8a34f63 100644 --- a/utilities/CMakeLists.txt +++ b/utilities/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(utilities OBJECT src/shader.cpp) +add_library(utilities OBJECT src/shader.cpp src/memory_pages_managment.cpp) target_include_directories(utilities PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_link_libraries(utilities PUBLIC renderer_api) \ No newline at end of file diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/color.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/color.hpp new file mode 100644 index 0000000..f8c2371 --- /dev/null +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/color.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +// #include +#include + + +namespace BGTU::ComputerGraphicsLabWork::Utilities { + RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) { +#if 1 + static auto calc = [&](RendererApi::Color::component_fast_t s, RendererApi::Color::component_fast_t o) { + auto oo = static_cast(o) * static_cast(fg.alpha); + auto ss = static_cast(s) * (static_cast(255) - static_cast(fg.alpha)); + return static_cast((oo + ss) / 256); + }; + return RendererApi::Color{ + calc(bg.red, fg.red), + calc(bg.green, fg.green), + calc(bg.blue, fg.blue) + }; +#else + static __m128i vec_256 = _mm_set_epi16(256, 256, 256, 0, 0, 0, 0, 0); + __m128i vec_bg = _mm_set_epi16(bg.red, bg.green, bg.blue, 0, 0, 0, 0, 0); + __m128i vec_fg = _mm_set_epi16(fg.red, fg.green, fg.blue, 0, 0, 0, 0, 0); + __m128i vec_alpha = _mm_set_epi16(fg.alpha, fg.alpha, fg.alpha, 0, 0, 0, 0, 0); + + union { + std::uint_fast64_t packed = static_cast(_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))); + std::uint16_t unpacked[3]; + } raw; + return RendererApi::Color{ + static_cast(raw.unpacked[0]), + static_cast(raw.unpacked[1]), + static_cast(raw.unpacked[2]) + }; +#endif + } +} \ No newline at end of file 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 new file mode 100644 index 0000000..7ad53e5 --- /dev/null +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp @@ -0,0 +1,300 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "color.hpp" +#include "matrix.hpp" + + +namespace BGTU::ComputerGraphicsLabWork { + namespace Utilities { + class DefaultVoxelDrawerLinear : public RendererApi::VoxelDrawer { + private: + class ZElement { + public: + ZElement *next; + double const z; + RendererApi::Color::Transparent const color; + RendererApi::Sprite *const owner; + + ZElement(ZElement *next, double z, RendererApi::Color::Transparent color, RendererApi::Sprite *owner) : next{next}, z{z}, color{color}, owner{owner} {} + + void link_after(ZElement *new_next) { + new_next->next = this->next; + this->next = new_next; + } + }; + + class ZElementAllocationBuffer { + private: + union Cell { + ZElement allocated; + struct Empty { + Cell *next_empty; + } empty; + }; + + + class Page { + public: + Page *next; + private: + + std::size_t initialized; + std::size_t capacity; + + Cell buffer[0]; + + public: + explicit Page(Page *next, std::size_t capacity) : next{next}, initialized{0}, capacity{capacity} {}; + + Cell *try_allocate(); + + static std::size_t calc_capacity(std::size_t bytes) { + return (bytes - offsetof(Page, buffer)) / sizeof(Cell); + }; + + void reset_allocations() { + this->initialized = 0; + } + }; + + Cell *next_unallocated; + Page *last_page; + Page sentinel; + + public: + ZElementAllocationBuffer() : next_unallocated{nullptr}, sentinel{nullptr, 0}, last_page{&this->sentinel} {}; + + private: + Page *_native_extend(); + + public: + template + ZElement *alloc_elem(args_t...args); + + void free_elem(ZElement *e); + + private: + void _native_free_page(Page *p); + + public: + void release_resources(); + + void reset_allocations(); + + ~ZElementAllocationBuffer(); + }; + + + RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _width; + RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _height; + + struct pixel_trace_metadata { + public: + pixel_trace_metadata() : nearest_z{std::numeric_limits::max()}, voxels{nullptr} {}; + + double nearest_z; + ZElement *voxels; + } *pixels_metadata; + + ZElementAllocationBuffer allocator; + RendererApi::Sprite *current_artist; + public: + inline DefaultVoxelDrawerLinear(std::uint_fast16_t width, std::uint_fast16_t height); + + ~DefaultVoxelDrawerLinear(); + + template + void set_current_artist(RendererApi::Sprite *sprite) { + this->current_artist = reinterpret_cast *>(sprite); + } + + [[nodiscard]] inline std::uint_fast16_t height() const final { + return this->_height; + }; + + [[nodiscard]] inline std::uint_fast16_t width() const final { + return this->_width; + } + + private: + + pixel_trace_metadata *at(std::uint_fast16_t x, std::uint_fast16_t y) { + return &(this->pixels_metadata[y * this->_width + x]); + } + + public: + + void add_voxel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c) final; + + + private: + + + public: + + template + void export_(RendererApi::Color background, RendererApi::VoxelDrawer::Exporter *receiver); + + void release_resources(); + }; + + DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Cell *DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Page::try_allocate() { + if (this->initialized < this->capacity) { + Cell *cell = &(this->buffer[this->initialized++]); + return cell; + } + return nullptr; + } + + template + DefaultVoxelDrawerLinear::ZElement *DefaultVoxelDrawerLinear::ZElementAllocationBuffer::alloc_elem(args_t... args) { + auto cell = this->next_unallocated; + if (cell != nullptr) { + this->next_unallocated = cell->empty.next_empty; + return &(cell->allocated); + } + + while ((cell = this->last_page->try_allocate()) == nullptr) + this->_native_extend(); + + return new(&(cell->allocated)) ZElement{args...}; + } + + + void DefaultVoxelDrawerLinear::ZElementAllocationBuffer::free_elem(DefaultVoxelDrawerLinear::ZElement *e) { + Cell *cell = reinterpret_cast(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 (y < 0 || this->_height <= y) return; + if (z < 0) return; + auto p = this->at(x, y); + if (z <= p->nearest_z) { + p->nearest_z = z; +#if 1 + if (c.alpha == 255) { + ZElement *e; + while (p->voxels != nullptr) { + e = p->voxels; + p->voxels = e->next; + this->allocator.free_elem(e); + } + } +#endif + } + p->voxels = this->allocator.alloc_elem(p->voxels, z, c, this->current_artist); + } + + void DefaultVoxelDrawerLinear::release_resources() { + this->allocator.release_resources(); + } + + template + void DefaultVoxelDrawerLinear::export_(RendererApi::Color background, RendererApi::VoxelDrawer::Exporter *receiver) { + std::vector sorter; + std::uint_fast16_t y = 0; + std::uint_fast16_t x = 0; + + for (std::int_fast64_t i = this->_width * this->_height - 1; i >= 0; i--) { + for (ZElement *e = this->pixels_metadata[i].voxels; e != nullptr; e = e->next) { + sorter.push_back(e); + } + std::sort(sorter.rbegin(), sorter.rend(), [](ZElement *l, ZElement *r) { return l->z < r->z; }); + RendererApi::Color p = background; + for (auto a: sorter) { + p = apply_transparent_color(p, a->color); + } + receiver->export_pixel(x, y, p, sorter[sorter.size() - 1]->owner); + if (++x >= this->_width) { + y++; + x = 0; + } + } + } + } + + namespace QtUtilities { + template *, sprite_data_t *, RendererApi::Sprite *const *, std::size_t)> + class SeparateThreadedRenderer; + +#if 0 + template + class _SeparateThreadedDefaultRendererLinear { + }; + + template + class _SeparateThreadedDefaultRendererLinear { + template + friend + class _SeparateThreadedDefaultRendererLinear; + + + private: + _SeparateThreadedDefaultRendererLinear() = delete; + + class Context : public Utilities::DefaultVoxelDrawerLinear { + + }; + + }; + + + class _SeparateThreadedDefaultRendererLinear : public SeparateThreadedRenderer, &SeparateThreadedDefaultRendererLinear::render + + > { + public: + + void render(RendererApi::VoxelDrawer::Exporter *, sprite_data_t *, RendererApi::Sprite *const *, std::size_t) { + + } + }; +#endif + } +} \ No newline at end of file diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp index bf911c7..7ae510b 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp @@ -17,11 +17,9 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { elem_t e20, elem_t e21, elem_t e22 ) : data{e00, e01, e02, e10, e11, e12, e20, e21, e22} {} - static inline const Matrix3 I{1, 0, 0, - 0, 1, 0, - 0, 0, 1}; + static const Matrix3 I; private: - static inline const Matrix3 _tmp{}; + static const Matrix3 _tmp; template @@ -143,17 +141,14 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { elem_t e30, elem_t e31, elem_t e32, elem_t e33 ) : data{e00, e01, e02, e03, e10, e11, e12, e13, e20, e21, e22, e23, e30, e31, e32, e33} {} - static inline const Matrix4 I{1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1}; + static const Matrix4 I; private: - static inline const Matrix4 _tmp{}; + static const Matrix4 _tmp; template Matrix4 _zipmap_matrix(Matrix4 const *other, operator_t op) const { - Matrix4 dst; + Matrix4 < elem_t > dst; auto _map_row = [&](std::size_t row_index) { dst.data[row_index][0] = op(row_index, 0, this->data[row_index][0], other->data[row_index][0]); dst.data[row_index][1] = op(row_index, 1, this->data[row_index][1], other->data[row_index][1]); @@ -216,10 +211,10 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { } static Matrix4 scale(elem_t x, elem_t y, elem_t z) { - return Matrix4{x, 0, 0, 0, - 0, y, 0, 0, - 0, 0, z, 0, - 0, 0, 0, 1}; + return Matrix4 < elem_t > {x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1}; } @@ -266,6 +261,24 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { } }; + template + const Matrix3 Matrix3::I{1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + template + const Matrix3 Matrix3::_tmp{}; + + template + const Matrix4 Matrix4::I{1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + template + const Matrix4 Matrix4::_tmp{}; + using Matrix4i = Matrix4; using Matrix4l = Matrix4; using Matrix4f = Matrix4; diff --git a/utilities/src/memory_pages_managment.cpp b/utilities/src/memory_pages_managment.cpp new file mode 100644 index 0000000..d929a60 --- /dev/null +++ b/utilities/src/memory_pages_managment.cpp @@ -0,0 +1,29 @@ +#include + +#if defined(_WIN32) + +#include +#include +#include +#include + +namespace BGTU::ComputerGraphicsLabWork::Utilities { + DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Page *DefaultVoxelDrawerLinear::ZElementAllocationBuffer::_native_extend() { + SYSTEM_INFO si; + GetSystemInfo(&si); + + std::size_t size = max(si.dwPageSize, si.dwAllocationGranularity); + + void *raw = VirtualAlloc(nullptr, max(si.dwPageSize, si.dwAllocationGranularity), MEM_COMMIT, PAGE_READWRITE); + if (raw != nullptr) throw std::bad_alloc{}; + return this->last_page = new(raw)Page(this->last_page, Page::calc_capacity(size)); + } + + + void DefaultVoxelDrawerLinear::ZElementAllocationBuffer::_native_free_page(DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Page *p) { + VirtualFree(p, 0, MEM_DECOMMIT | MEM_RELEASE); + } +} +#else +# error "" +#endif \ No newline at end of file