From 43821b0cffc5aa419c0218992f06f8962ae54a13 Mon Sep 17 00:00:00 2001 From: Frederico Linhares Date: Wed, 8 May 2024 17:56:29 -0300 Subject: refa Rename graphical engine to BluCat --- src/vk/texture.cpp | 559 ----------------------------------------------------- 1 file changed, 559 deletions(-) delete mode 100644 src/vk/texture.cpp (limited to 'src/vk/texture.cpp') diff --git a/src/vk/texture.cpp b/src/vk/texture.cpp deleted file mode 100644 index a4cac40..0000000 --- a/src/vk/texture.cpp +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright 2022-2024 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 "texture.hpp" - -#include "../command.hpp" -#include "../core.hpp" -#include "image.hpp" -#include "qoi.hpp" -#include "source_buffer.hpp" - -namespace -{ - -inline void -create_vulkan_image( - VkImage *image, VkDeviceMemory *device_memory, int width, int height, - uint32_t mip_levels) -{ - VkExtent3D vk_extent3d{}; - vk_extent3d.width = width; - vk_extent3d.height = height; - vk_extent3d.depth = 1; - - VK::Image::create( - cg_core.vk_device_with_swapchain, - image, - device_memory, - VK_FORMAT_R8G8B8A8_UNORM, - vk_extent3d, - mip_levels, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); -} - -struct ImageBuilder -{ - VK::Texture *texture; -}; - -struct ImageTextureBuilder: public ImageBuilder -{ - std::string texture_path; - - ImageTextureBuilder(VK::Texture *t, std::string tp); - ImageTextureBuilder(VK::Texture *t, const char* tp); -}; - -ImageTextureBuilder::ImageTextureBuilder(VK::Texture *t, std::string tp): - texture_path{tp} -{ - this->texture = t; -} - -ImageTextureBuilder::ImageTextureBuilder(VK::Texture *t, const char* tp): - ImageTextureBuilder{t, std::string(tp)} -{ -} - -void -load_image(void *obj) -{ - auto self = static_cast(obj); - - const int num_channels = 4; // all images are converted to RGBA - VK::QOI::Image qoi_image(self->texture_path.c_str(), num_channels); - uint8_t *pixels; - - { // Load file image from file. - self->texture->width = qoi_image.header.width; - self->texture->height = qoi_image.header.height; - self->texture->mip_levels = 1; - - pixels = qoi_image.pixels; - } - - // Load file image into a vulkan buffer. - size_t image_size{static_cast( - qoi_image.header.width * qoi_image.header.height * num_channels)}; - VK::SourceBuffer source_image_buffer{ - cg_core.vk_device_with_swapchain, pixels, image_size}; - - { // Create vulkan image. - try - { - create_vulkan_image( - &self->texture->image, - &self->texture->device_memory, - self->texture->width, - self->texture->height, - self->texture->mip_levels); - } - catch(VK::Image::Error error) - { - throw CommandError{error.what()}; - } - } - - // Copy image from vulkan buffer into vulkan image. - { - auto queue_family = self->texture->queue_family; - auto queue{queue_family->get_queue()}; - VK::CommandPool command_pool{queue_family, 1}; - VkCommandBuffer vk_command_buffer{command_pool.command_buffers[0]}; - - queue.submit_one_time_command(vk_command_buffer, [&](){ - VK::Image::move_image_state( - vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - - VkBufferImageCopy image_copy{}; - image_copy.bufferOffset = 0; - image_copy.bufferRowLength = 0; - image_copy.bufferImageHeight = 0; - image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_copy.imageSubresource.mipLevel = 0; - image_copy.imageSubresource.baseArrayLayer = 0; - image_copy.imageSubresource.layerCount = 1; - image_copy.imageOffset = {0, 0, 0}; - image_copy.imageExtent = { - self->texture->width, self->texture->height, 1}; - - vkCmdCopyBufferToImage( - vk_command_buffer, source_image_buffer.buffer, self->texture->image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); - - VK::Image::move_image_state( - vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - }); - } -} - -void -unload_image(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyImage( - cg_core.vk_device_with_swapchain->device, self->texture->image, nullptr); - vkFreeMemory( - cg_core.vk_device_with_swapchain->device, self->texture->device_memory, - nullptr); -} - -void -load_sampler(void *obj) -{ - auto self = static_cast(obj); - - VkSamplerCreateInfo sampler_info{}; - sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - sampler_info.pNext = nullptr; - sampler_info.flags = 0; - sampler_info.magFilter = VK_FILTER_LINEAR; - sampler_info.minFilter = VK_FILTER_LINEAR; - sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.mipLodBias = 0.0f; - sampler_info.anisotropyEnable = VK_TRUE; - sampler_info.maxAnisotropy = 16; - sampler_info.compareEnable = VK_FALSE; - sampler_info.compareOp = VK_COMPARE_OP_NEVER; - sampler_info.minLod = 0.0f; - sampler_info.maxLod = 0.0f; - sampler_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - sampler_info.unnormalizedCoordinates = VK_FALSE; - - if(vkCreateSampler( - cg_core.vk_device_with_swapchain->device, &sampler_info, nullptr, - &self->texture->sampler) != VK_SUCCESS) - throw CommandError{"Failed to create texture sampler."}; -} - -void -unload_sampler(void *obj) -{ - auto self = static_cast(obj); - - vkDestroySampler( - cg_core.vk_device_with_swapchain->device, self->texture->sampler, nullptr); -} - -void -load_view(void *obj) -{ - auto self = static_cast(obj); - - try - { - VK::Image::create_view( - cg_core.vk_device_with_swapchain, &self->texture->view, - self->texture->image, - VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); - } - catch(VK::Image::Error error) - { - throw CommandError{error.what()}; - } -} - -void -unload_view(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyImageView( - cg_core.vk_device_with_swapchain->device, self->texture->view, nullptr); -} - -const CommandChain image_loader{ - {&load_image, &unload_image}, - {&load_sampler, &unload_sampler}, - {&load_view, &unload_view} -}; - -struct CharacterToDraw -{ - int pos_x; - std::shared_ptr character; - - CharacterToDraw(int x, std::shared_ptr character): - pos_x{x}, - character{character} - {}; -}; - -struct TextTextureBuilder: public ImageBuilder -{ - VK::Font *font; - const char* str; - uint32_t max_bearing_y; - std::vector chars_to_draw; - - TextTextureBuilder(VK::Texture *texture, VK::Font *font, const char* str): - font{font}, - str{str} - { - this->texture = texture; - } -}; - -void -load_text_proportions(void *obj) -{ - auto self = static_cast(obj); - - uint32_t texture_width{0}, texture_descender{0}; - auto unicode_text{VK::Character::str_to_unicode(self->str)}; - - auto first_image{self->font->character(unicode_text[0])}; - if(first_image->bearing_x < 0) texture_width = - first_image->bearing_x; - - self->max_bearing_y = 0; - self->chars_to_draw.reserve(unicode_text.size()); - - // FIXME: I need to test several different fonts to find all bugs in this - // code. - std::shared_ptr char_image{}; - { // Calculate image size - int max_height; - for(auto char_code : unicode_text) - { - char_image = self->font->character(char_code); - uint32_t descender{char_image->height - char_image->bearing_y}; - uint32_t pos_x{texture_width + char_image->bearing_x}; - - if(char_image->image != VK_NULL_HANDLE) - self->chars_to_draw.emplace_back(pos_x, char_image); - - if(char_image->bearing_y > self->max_bearing_y) - self->max_bearing_y = char_image->bearing_y; - if(descender > texture_descender) texture_descender = descender; - - texture_width += char_image->advance; - } - } - - { // Restore image width if last character have a negative bearing. - int bearing_x_pluss_width = char_image->bearing_x + char_image->width; - if(bearing_x_pluss_width > char_image->advance) - texture_width += bearing_x_pluss_width - char_image->advance; - } - - self->texture->width = texture_width; - self->texture->height = self->max_bearing_y + texture_descender; - self->texture->mip_levels = 1; -} - -void -load_text_image(void *obj) -{ - auto self = static_cast(obj); - - const int NumChannels = 4; - - size_t image_size{static_cast( - self->texture->width * self->texture->height * NumChannels)}; - std::vector pixels(image_size); - for(auto x{0}; x < self->texture->width; x++) - { - for(auto y{0}; y < self->texture->height; y++) - { - auto image_coord = y * self->font->face->glyph->bitmap.width + - x * NumChannels; - pixels[image_coord] = 0; // Red - pixels[image_coord + 1] = 0; // Green - pixels[image_coord + 2] = 0; // Blue - pixels[image_coord + 3] = 0; // Alpha - } - } - VK::SourceBuffer source_image_buffer{ - cg_core.vk_device_with_swapchain, pixels.data(), image_size}; - - { // Create vulkan image. - try - { - create_vulkan_image( - &self->texture->image, - &self->texture->device_memory, - self->texture->width, - self->texture->height, - self->texture->mip_levels); - } - catch(VK::Image::Error error) - { - throw CommandError{error.what()}; - } - } - - { // Render text - auto queue_family{ - cg_core.vk_device_with_swapchain->get_queue_family_with_presentation()}; - auto queue{queue_family->get_queue()}; - VK::CommandPool command_pool{queue_family, 1}; - VkCommandBuffer vk_command_buffer{command_pool.command_buffers[0]}; - - queue.submit_one_time_command(vk_command_buffer, [&](){ - VK::Image::move_image_state( - vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - - VkBufferImageCopy image_copy{}; - image_copy.bufferOffset = 0; - image_copy.bufferRowLength = 0; - image_copy.bufferImageHeight = 0; - image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_copy.imageSubresource.mipLevel = 0; - image_copy.imageSubresource.baseArrayLayer = 0; - image_copy.imageSubresource.layerCount = 1; - image_copy.imageOffset = {0, 0, 0}; - image_copy.imageExtent = {self->texture->width, self->texture->height, 1}; - - vkCmdCopyBufferToImage( - vk_command_buffer, source_image_buffer.buffer, self->texture->image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); - - for(auto &to_draw: self->chars_to_draw) - { - VkImageSubresourceLayers - source_subresources{}, destination_subresources{}; - source_subresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - source_subresources.mipLevel = 0; - source_subresources.baseArrayLayer = 0; - source_subresources.layerCount = 1; - - destination_subresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - destination_subresources.mipLevel = 0; - destination_subresources.baseArrayLayer = 0; - destination_subresources.layerCount = 1; - - VkImageCopy image_copy{}; - image_copy.srcSubresource = source_subresources; - image_copy.srcOffset = {0, 0, 0}; - image_copy.dstSubresource = destination_subresources; - image_copy.dstOffset = { - to_draw.pos_x, - (int)(self->max_bearing_y - to_draw.character->bearing_y), - 0}; - image_copy.extent = { - to_draw.character->width, to_draw.character->height, 1}; - - vkCmdCopyImage( - vk_command_buffer, - to_draw.character->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - self->texture->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, &image_copy); - } - - VK::Image::move_image_state( - vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - }); - } -} - -const CommandChain text_loader{ - {&load_text_proportions, nullptr}, - {&load_text_image, &unload_image}, - {&load_sampler, &unload_sampler}, - {&load_view, &unload_view} -}; - -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->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(obj); - - vkDestroyDescriptorPool( - self->queue_family->device->device, self->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_descriptor_set_layout->texture); - - 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(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->view; - image_info.sampler = self->sampler; - - std::array 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_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); - } -} - -const CommandChain descriptor_loader{ - {&load_descriptor_set_pool, &unload_descriptor_set_pool}, - {&load_descriptor_sets, nullptr}, - {&load_data_to_descriptor_sets, nullptr} -}; - -} - -namespace VK -{ - -Texture::Texture(Font *font, const char* str) -{ - this->queue_family = - cg_core.vk_device_with_swapchain->get_queue_family_with_presentation(); - - TextTextureBuilder text_builder(this, font, str); - text_loader.execute(&text_builder); - descriptor_loader.execute(this); -} - -Texture::Texture(std::string texture_path) -{ - this->queue_family = - cg_core.vk_device_with_swapchain->get_queue_family_with_presentation(); - - ImageTextureBuilder texture_builder(this, texture_path); - image_loader.execute(&texture_builder); - descriptor_loader.execute(this); -} - -Texture::Texture(const char* texture_path): - Texture{std::string(texture_path)} -{ -} - -Texture::~Texture() -{ - ImageTextureBuilder texture_builder(this, ""); - image_loader.revert(&texture_builder); - descriptor_loader.revert(this); -} - -} -- cgit v1.2.3