Voxels sort optimization
This commit is contained in:
parent
003ba2b290
commit
93da247ccc
@ -103,7 +103,6 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
ZElement *voxels;
|
ZElement *voxels;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class sprite_data_t>
|
|
||||||
class VoxelDrawerImpl : public RendererApi::VoxelDrawer {
|
class VoxelDrawerImpl : public RendererApi::VoxelDrawer {
|
||||||
public:
|
public:
|
||||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _width;
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _width;
|
||||||
@ -116,15 +115,15 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
|
|
||||||
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);
|
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 {
|
[[nodiscard]] inline RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width() const final {
|
||||||
return this->_width;
|
return this->_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height() const final {
|
[[nodiscard]] inline RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height() const final {
|
||||||
return this->_height;
|
return this->_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixel_trace_metadata *at(std::uint_fast16_t x, std::uint_fast16_t y) {
|
inline pixel_trace_metadata *at(std::uint_fast16_t x, std::uint_fast16_t y) {
|
||||||
return &(this->pixels_metadata[y * this->_width + x]);
|
return &(this->pixels_metadata[y * this->_width + x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,12 +135,15 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
pixel_trace_metadata *buffer;
|
pixel_trace_metadata *buffer;
|
||||||
std::size_t size;
|
std::size_t size;
|
||||||
} pixel_metadata_cache;
|
} pixel_metadata_cache;
|
||||||
std::vector<ZElement *> sorter;
|
|
||||||
ZElementAllocationBuffer pixel_trace_elements_allocator;
|
ZElementAllocationBuffer pixel_trace_elements_allocator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DefaultVoxelDrawerCache();
|
DefaultVoxelDrawerCache();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static ZElement *sort_zelements_desc(DefaultVoxelDrawerCache::ZElement *start) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
template<class sprite_data_t>
|
template<class sprite_data_t>
|
||||||
void render(
|
void render(
|
||||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w,
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w,
|
||||||
@ -157,19 +159,6 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
~DefaultVoxelDrawerCache();
|
~DefaultVoxelDrawerCache();
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class sprite_data_t>
|
|
||||||
DefaultVoxelDrawerCache::VoxelDrawerImpl<sprite_data_t>::VoxelDrawerImpl(
|
|
||||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width,
|
|
||||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height,
|
|
||||||
DefaultVoxelDrawerCache::pixel_trace_metadata *pixels_metadata,
|
|
||||||
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>
|
||||||
DefaultVoxelDrawerCache::ZElement *DefaultVoxelDrawerCache::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;
|
||||||
@ -184,27 +173,6 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
return new(&(cell->allocated)) ZElement{args...};
|
return new(&(cell->allocated)) ZElement{args...};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class sprite_data_t>
|
|
||||||
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) {
|
|
||||||
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->pixel_trace_elements_allocator->free_elem(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
p->voxels = this->pixel_trace_elements_allocator->alloc_elem(p->voxels, z, c, this->current_artist);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class sprite_data_t>
|
template<class sprite_data_t>
|
||||||
void DefaultVoxelDrawerCache::render(
|
void DefaultVoxelDrawerCache::render(
|
||||||
@ -226,7 +194,7 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->pixel_trace_elements_allocator.reset_allocations();
|
this->pixel_trace_elements_allocator.reset_allocations();
|
||||||
VoxelDrawerImpl<sprite_data_t> painter{w, h, this->pixel_metadata_cache.buffer, &this->pixel_trace_elements_allocator};
|
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--) {
|
for (std::int_fast64_t i = w * h - 1; i >= 0; i--) {
|
||||||
new(&this->pixel_metadata_cache.buffer[i]) pixel_trace_metadata{};
|
new(&this->pixel_metadata_cache.buffer[i]) pixel_trace_metadata{};
|
||||||
@ -241,19 +209,14 @@ namespace BGTU::ComputerGraphicsLabWork {
|
|||||||
std::uint_fast16_t x = 0;
|
std::uint_fast16_t x = 0;
|
||||||
|
|
||||||
for (std::int_fast64_t i = w * h - 1; i >= 0; i--) {
|
for (std::int_fast64_t i = w * h - 1; i >= 0; i--) {
|
||||||
this->sorter.clear();
|
this->pixel_metadata_cache.buffer[i].voxels = sort_zelements_desc(this->pixel_metadata_cache.buffer[i].voxels);
|
||||||
for (ZElement *e = this->pixel_metadata_cache.buffer[i].voxels; e != nullptr; e = e->next) {
|
RendererApi::Color cc = bg;
|
||||||
this->sorter.push_back(e);
|
RendererApi::SpriteMetadata *owner = nullptr;
|
||||||
|
for (auto p = this->pixel_metadata_cache.buffer[i].voxels; p != nullptr; p = p->next) {
|
||||||
|
cc = apply_transparent_color(cc, p->color);
|
||||||
|
owner = p->owner;
|
||||||
}
|
}
|
||||||
std::sort(this->sorter.begin(), this->sorter.end(), [](ZElement *l, ZElement *r) { return l->z > r->z; });
|
frame->set_pixel(x, y, cc, owner);
|
||||||
RendererApi::Color p = bg;
|
|
||||||
for (auto a: this->sorter) {
|
|
||||||
p = apply_transparent_color(p, a->color);
|
|
||||||
}
|
|
||||||
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) {
|
if (++x >= w) {
|
||||||
y++;
|
y++;
|
||||||
|
@ -40,7 +40,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
|||||||
this->release_resources();
|
this->release_resources();
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultVoxelDrawerCache::DefaultVoxelDrawerCache() : pixel_trace_elements_allocator{}, pixel_metadata_cache{.buffer = nullptr, .size = 0}, sorter{} {}
|
DefaultVoxelDrawerCache::DefaultVoxelDrawerCache() : pixel_trace_elements_allocator{}, pixel_metadata_cache{.buffer = nullptr, .size = 0} {}
|
||||||
|
|
||||||
DefaultVoxelDrawerCache::~DefaultVoxelDrawerCache() {
|
DefaultVoxelDrawerCache::~DefaultVoxelDrawerCache() {
|
||||||
if (this->pixel_metadata_cache.buffer != nullptr) {
|
if (this->pixel_metadata_cache.buffer != nullptr) {
|
||||||
@ -50,4 +50,106 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
|||||||
this->pixel_metadata_cache.size = 0;
|
this->pixel_metadata_cache.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DefaultVoxelDrawerCache::ZElement* DefaultVoxelDrawerCache::sort_zelements_desc(DefaultVoxelDrawerCache::ZElement *start) noexcept {
|
||||||
|
for (std::size_t frame_size = 1; 0 < frame_size && frame_size < std::numeric_limits<std::size_t>::max() / 4; frame_size *= 2) {
|
||||||
|
ZElement **before_left = &start;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
ZElement **union_ptr = before_left;
|
||||||
|
ZElement *left_ptr = *before_left;
|
||||||
|
ZElement *right_ptr;
|
||||||
|
std::size_t left_counter = frame_size;
|
||||||
|
std::size_t right_counter = frame_size;
|
||||||
|
|
||||||
|
if (left_ptr == nullptr)
|
||||||
|
goto ROUND_DONE;
|
||||||
|
|
||||||
|
right_ptr = left_ptr;
|
||||||
|
while (left_counter-- > 0) {
|
||||||
|
right_ptr = right_ptr->next;
|
||||||
|
if (right_ptr == nullptr)
|
||||||
|
goto ROUND_DONE;
|
||||||
|
}
|
||||||
|
left_counter = frame_size;
|
||||||
|
|
||||||
|
while (left_counter > 0 && right_counter > 0) {
|
||||||
|
if (left_ptr->z >= right_ptr->z) {
|
||||||
|
*union_ptr = left_ptr;
|
||||||
|
left_ptr = left_ptr->next;
|
||||||
|
union_ptr = &((*union_ptr)->next);
|
||||||
|
if (left_counter-- == 0)
|
||||||
|
goto RIGHT_TAIL;
|
||||||
|
} else {
|
||||||
|
*union_ptr = right_ptr;
|
||||||
|
right_ptr = right_ptr->next;
|
||||||
|
union_ptr = &((*union_ptr)->next);
|
||||||
|
if (right_counter-- == 0)
|
||||||
|
goto LEFT_TAIL;
|
||||||
|
|
||||||
|
if (right_ptr == nullptr) {
|
||||||
|
goto LEFT_TAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (right_counter == 0) {
|
||||||
|
LEFT_TAIL:
|
||||||
|
while (right_counter-- > 1)
|
||||||
|
left_ptr = left_ptr->next;
|
||||||
|
left_ptr->next = right_ptr;
|
||||||
|
before_left = &(left_ptr->next);
|
||||||
|
}
|
||||||
|
if (left_counter == 0) {
|
||||||
|
RIGHT_TAIL:
|
||||||
|
*union_ptr = right_ptr;
|
||||||
|
while (right_counter-- > 1) {
|
||||||
|
right_ptr = right_ptr->next;
|
||||||
|
if (right_ptr == nullptr) {
|
||||||
|
goto ROUND_DONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
before_left = &(right_ptr->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ROUND_DONE:
|
||||||
|
if (before_left == &start)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DefaultVoxelDrawerCache::VoxelDrawerImpl::VoxelDrawerImpl(
|
||||||
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width,
|
||||||
|
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height,
|
||||||
|
DefaultVoxelDrawerCache::pixel_trace_metadata *pixels_metadata,
|
||||||
|
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} {}
|
||||||
|
|
||||||
|
|
||||||
|
void DefaultVoxelDrawerCache::VoxelDrawerImpl::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->pixel_trace_elements_allocator->free_elem(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
p->voxels = this->pixel_trace_elements_allocator->alloc_elem(p->voxels, z, c, this->current_artist);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user