diff options
Diffstat (limited to 'src/vk/rectangle.cpp')
-rw-r--r-- | src/vk/rectangle.cpp | 245 |
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(); +} + +} |