/* * 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 "sprite.hpp" #include #include "../core.hpp" #include "sprite.hpp" #include "uniform_data_object.hpp" namespace { struct SpriteBuilder { VK::Sprite *sprite; glm::vec4 rect; SpriteBuilder(VK::Sprite *sprite, glm::vec4 rect); }; SpriteBuilder::SpriteBuilder(VK::Sprite *sprite, glm::vec4 rect): sprite{sprite}, rect{rect} { } void load_mesh(void *obj) { auto self = static_cast(obj); self->sprite->queue_family = cg_core.vk_device_with_swapchain->get_queue_family_with_graphics(); glm::vec2 rect[VK::Sprite::vertex_count]{ glm::vec2{self->rect.x, self->rect.y}, glm::vec2{self->rect.x, self->rect.w}, glm::vec2{self->rect.z, self->rect.y}, glm::vec2{self->rect.z, self->rect.w} }; void *vertexes_data{&rect}; static const size_t vertexes_size = sizeof(glm::vec2) * VK::Sprite::vertex_count; self->sprite->source_buffer = new VK::SourceBuffer{ self->sprite->queue_family->device, vertexes_data, vertexes_size}; self->sprite->vertex_buffer = new VK::DestinationBuffer{ self->sprite->queue_family, self->sprite->source_buffer, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT}; } void unload_mesh(void *obj) { auto self = static_cast(obj); delete self->sprite->vertex_buffer; delete self->sprite->source_buffer; } void load_descriptor_set_pool(void *obj) { auto self = static_cast(obj); std::array descriptor_pool_sizes{}; descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; descriptor_pool_sizes[0].descriptorCount = cg_core.vk_swapchain->images_count; VkDescriptorPoolCreateInfo pool_info{}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.pNext = nullptr; pool_info.flags = 0; pool_info.maxSets = cg_core.vk_swapchain->images_count; pool_info.poolSizeCount = descriptor_pool_sizes.size(); pool_info.pPoolSizes = descriptor_pool_sizes.data(); if(vkCreateDescriptorPool( self->sprite->queue_family->device->device, &pool_info, nullptr, &self->sprite->descriptor_pool) != VK_SUCCESS) throw CommandError{"Failed to create a Vulkan descriptor pool."}; } void unload_descriptor_set_pool(void *obj) { auto self = static_cast(obj); vkDestroyDescriptorPool( self->sprite->queue_family->device->device, self->sprite->descriptor_pool, nullptr); } void load_descriptor_sets(void *obj) { auto self = static_cast(obj); std::vector layouts( cg_core.vk_swapchain->images_count, cg_core.vk_graphics_pipeline_2d_solid_layout->descriptor_set_sprite); VkDescriptorSetAllocateInfo alloc_info{}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; alloc_info.descriptorPool = self->sprite->descriptor_pool; alloc_info.descriptorSetCount = layouts.size(); alloc_info.pSetLayouts = layouts.data(); self->sprite->descriptor_sets.resize(layouts.size()); if(vkAllocateDescriptorSets( self->sprite->queue_family->device->device, &alloc_info, self->sprite->descriptor_sets.data()) != VK_SUCCESS) CommandError{"Failed to create Vulkan descriptor set."}; } void load_buffers_to_descriptor_sets(void *obj) { auto self = static_cast(obj); for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++) { VkDescriptorImageInfo image_info{}; image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; image_info.imageView = self->sprite->texture->view; image_info.sampler = self->sprite->texture->sampler; std::array write_descriptors{}; write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write_descriptors[0].dstSet = self->sprite->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_COMBINED_IMAGE_SAMPLER; write_descriptors[0].pBufferInfo = nullptr; write_descriptors[0].pImageInfo = &image_info; 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_descriptor_set_pool, &unload_descriptor_set_pool}, {&load_descriptor_sets, nullptr}, {&load_buffers_to_descriptor_sets, nullptr}, }; } namespace VK { Sprite::Sprite(std::shared_ptr texture, glm::vec4 rect): texture{texture} { SpriteBuilder sprite_builder(this, rect); loader.execute(&sprite_builder); } Sprite::~Sprite() { SpriteBuilder sprite_builder(this, glm::vec4()); loader.revert(&sprite_builder); } }