summaryrefslogtreecommitdiff
path: root/src/vk/rectangle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vk/rectangle.cpp')
-rw-r--r--src/vk/rectangle.cpp245
1 files changed, 245 insertions, 0 deletions
diff --git a/src/vk/rectangle.cpp b/src/vk/rectangle.cpp
new file mode 100644
index 0000000..b0925f1
--- /dev/null
+++ b/src/vk/rectangle.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2022 Frederico de Oliveira Linhares
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rectangle.hpp"
+
+#include <array>
+
+#include "../core.hpp"
+#include "graphics_pipeline_2d_wired_layout.hpp"
+
+namespace
+{
+
+void
+load_mesh(void *obj)
+{
+ auto self = static_cast<VK::Rectangle*>(obj);
+
+ self->queue_family =
+ cg_core.vk_device_with_swapchain->get_queue_family_with_graphics();
+
+ glm::vec2 rect[4]{
+ glm::vec2{self->x, self->y},
+ glm::vec2{self->x, self->y + self->height},
+ glm::vec2{self->x + self->width, self->y},
+ glm::vec2{self->x + self->width, self->y + self->height}
+ };
+
+ void *vertexes_data{&rect};
+ static const size_t vertexes_size =
+ sizeof(glm::vec2) * VK::Rectangle::vertex_count;
+ self->source_buffers.reserve(cg_core.vk_swapchain->images_count);
+ self->vertex_buffers.reserve(cg_core.vk_swapchain->images_count);
+ for(int i{0}; i < cg_core.vk_swapchain->images_count; i++)
+ {
+ self->source_buffers.emplace_back(
+ self->queue_family->device, vertexes_data, vertexes_size);
+ self->vertex_buffers.emplace_back(
+ self->queue_family, &self->source_buffers[i],
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
+ }
+}
+
+void
+unload_mesh(void *obj)
+{
+ auto self = static_cast<VK::Rectangle*>(obj);
+
+ self->vertex_buffers.clear();
+ self->source_buffers.clear();
+}
+
+void
+load_uniform_buffer(void *obj)
+{
+ auto self = static_cast<VK::Rectangle*>(obj);
+
+ self->ub_rectangle.reserve(cg_core.vk_swapchain->images_count);
+ for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
+ self->ub_rectangle.emplace_back(
+ cg_core.vk_device_with_swapchain, sizeof(VK::UBOModel2D));
+}
+
+void
+unload_uniform_buffer(void *obj)
+{
+ auto self = static_cast<VK::Rectangle*>(obj);
+
+ self->ub_rectangle.clear();
+}
+
+void
+load_descriptor_set_pool(void *obj)
+{
+ auto self = static_cast<VK::Rectangle*>(obj);
+
+ std::array<VkDescriptorPoolSize, 1> descriptor_pool_sizes{};
+ descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ descriptor_pool_sizes[0].descriptorCount = self->ub_rectangle.size();
+
+ VkDescriptorPoolCreateInfo pool_info{};
+ pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ pool_info.pNext = nullptr;
+ pool_info.flags = 0;
+ pool_info.maxSets = self->ub_rectangle.size();
+ pool_info.poolSizeCount = descriptor_pool_sizes.size();
+ pool_info.pPoolSizes = descriptor_pool_sizes.data();
+
+ if(vkCreateDescriptorPool(
+ self->queue_family->device->device, &pool_info, nullptr,
+ &self->descriptor_pool) != VK_SUCCESS)
+ throw CommandError{"Failed to create a Vulkan descriptor pool."};
+}
+
+void
+unload_descriptor_set_pool(void *obj)
+{
+ auto self = static_cast<VK::Rectangle*>(obj);
+
+ vkDestroyDescriptorPool(
+ self->queue_family->device->device, self->descriptor_pool, nullptr);
+}
+
+void
+load_descriptor_sets(void *obj)
+{
+ auto self = static_cast<VK::Rectangle*>(obj);
+
+ std::vector<VkDescriptorSetLayout> layouts(
+ cg_core.vk_swapchain->images_count,
+ cg_core.vk_graphics_pipeline_2d_wired_layout->descriptor_set_instance);
+
+ VkDescriptorSetAllocateInfo alloc_info{};
+ alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ alloc_info.descriptorPool = self->descriptor_pool;
+ alloc_info.descriptorSetCount = layouts.size();
+ alloc_info.pSetLayouts = layouts.data();
+
+ self->descriptor_sets.resize(layouts.size());
+ if(vkAllocateDescriptorSets(
+ self->queue_family->device->device, &alloc_info,
+ self->descriptor_sets.data()) != VK_SUCCESS)
+ CommandError{"Failed to create Vulkan descriptor set."};
+}
+
+void
+load_data_to_descriptor_sets(void *obj)
+{
+ auto self = static_cast<VK::Rectangle*>(obj);
+
+ for(auto i{0}; i < self->ub_rectangle.size(); i++)
+ {
+ VkDescriptorBufferInfo buffer_info{};
+ buffer_info.buffer = self->ub_rectangle[i].buffer;
+ buffer_info.offset = 0;
+ buffer_info.range = sizeof(VK::UBOModel2D);
+
+ std::array<VkWriteDescriptorSet, 1> write_descriptors{};
+ write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ write_descriptors[0].dstSet = self->descriptor_sets[i];
+ write_descriptors[0].dstBinding = 0;
+ write_descriptors[0].dstArrayElement = 0;
+ write_descriptors[0].descriptorCount = 1;
+ write_descriptors[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ write_descriptors[0].pBufferInfo = &buffer_info;
+ write_descriptors[0].pImageInfo = nullptr;
+ write_descriptors[0].pTexelBufferView = nullptr;
+
+ vkUpdateDescriptorSets(
+ cg_core.vk_device_with_swapchain->device, write_descriptors.size(),
+ write_descriptors.data(), 0, nullptr);
+ }
+}
+
+static const CommandChain loader{
+ {&load_mesh, &unload_mesh},
+ {&load_uniform_buffer, &unload_uniform_buffer},
+ {&load_descriptor_set_pool, &unload_descriptor_set_pool},
+ {&load_descriptor_sets, nullptr},
+ {&load_data_to_descriptor_sets, nullptr},
+};
+
+constexpr bool
+_align_vertically(const float a_x, const float a_width,
+ const float b_x, const float b_width)
+{
+ return a_x <= b_x + b_width && a_x + a_width >= b_x;
+}
+
+constexpr bool
+_align_horizontally(const float a_y, const float a_height,
+ const float b_y, const float b_height)
+{
+ return a_y <= b_y + b_height && a_y + a_height >= b_y;
+}
+
+}
+
+namespace VK
+{
+
+Rectangle::Rectangle(float x, float y, float width, float height):
+ x{x},
+ y{y},
+ width{width},
+ height{height}
+{
+ loader.execute(this);
+}
+
+Rectangle::~Rectangle()
+{
+ loader.revert(this);
+}
+
+bool
+Rectangle::align_vertically(const Rectangle &that) const
+{
+ return _align_vertically(this->x, this->width, that.x, that.width);
+}
+
+bool
+Rectangle::align_horizontally(const Rectangle &that) const
+{
+ return _align_horizontally(this->y, this->height, that.y, that.height);
+}
+
+bool
+Rectangle::collide(const Rectangle &that) const
+{
+ return
+ _align_vertically(this->x, this->width, that.x, that.width) &&
+ _align_horizontally(this->y, this->height, that.y, that.height);
+}
+
+void
+Rectangle::update_vertex_buffer()
+{
+ glm::vec2 rect[4]{
+ glm::vec2{this->x, this->y},
+ glm::vec2{this->x, this->y + this->height},
+ glm::vec2{this->x + this->width, this->y},
+ glm::vec2{this->x + this->width, this->y + this->height}
+ };
+
+ void *vertexes_data{&rect};
+ this->source_buffers[cg_core.vk_swapchain->current_frame].copy_data(
+ vertexes_data);
+ this->vertex_buffers[cg_core.vk_swapchain->current_frame].copy_data();
+}
+
+}