From a646fe175c20d9d95c76d28d7f8de88b203a8b94 Mon Sep 17 00:00:00 2001 From: Frederico Linhares Date: Wed, 31 Aug 2022 17:43:57 -0300 Subject: feat Add projection to 2D graphics pipeline --- src/vk/graphics_pipeline_2d.cpp | 187 +++++++++++++++++++++++++++++++++++++--- src/vk/graphics_pipeline_2d.hpp | 9 +- src/vk/sprite.cpp | 2 +- src/vk/uniform_buffer.hpp | 5 ++ 4 files changed, 189 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/vk/graphics_pipeline_2d.cpp b/src/vk/graphics_pipeline_2d.cpp index e8fd002..bc519d9 100644 --- a/src/vk/graphics_pipeline_2d.cpp +++ b/src/vk/graphics_pipeline_2d.cpp @@ -25,7 +25,44 @@ namespace { void -load_descriptor_set_layout_image_sprites(void *obj) +load_descriptor_set_layout_projection(void *obj) +{ + auto self = static_cast(obj); + + std::array layout_bindings{}; + + layout_bindings[0].binding = 0; + layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + layout_bindings[0].descriptorCount = 1; + layout_bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + layout_bindings[0].pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutCreateInfo layout_info{}; + layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layout_info.pNext = nullptr; + layout_info.flags = 0; + layout_info.bindingCount = static_cast(layout_bindings.size()); + layout_info.pBindings = layout_bindings.data(); + + if(vkCreateDescriptorSetLayout( + cg_core.vk_device_with_swapchain->device, &layout_info, nullptr, + &self->descriptor_set_layout_projection) != VK_SUCCESS) + throw CommandError{ + "Failed to create Vulkan descriptor set layout for projection."}; +} + +void +unload_descriptor_set_layout_projection(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyDescriptorSetLayout( + cg_core.vk_device_with_swapchain->device, + self->descriptor_set_layout_projection, nullptr); +} + +void +load_descriptor_set_layout_sprite(void *obj) { auto self = static_cast(obj); @@ -53,19 +90,19 @@ load_descriptor_set_layout_image_sprites(void *obj) if(vkCreateDescriptorSetLayout( cg_core.vk_device_with_swapchain->device, &layout_info, nullptr, - &self->descriptor_set_layout_sprites) != VK_SUCCESS) + &self->descriptor_set_layout_sprite) != VK_SUCCESS) throw CommandError{ - "Failed to create Vulkan descriptor set layout for model instance."}; + "Failed to create Vulkan descriptor set layout for sprites."}; } void -unload_descriptor_set_layout_image_sprites(void *obj) +unload_descriptor_set_layout_sprite(void *obj) { auto self = static_cast(obj); vkDestroyDescriptorSetLayout( cg_core.vk_device_with_swapchain->device, - self->descriptor_set_layout_sprites, nullptr); + self->descriptor_set_layout_sprite, nullptr); } void @@ -73,8 +110,9 @@ load_pipeline_layout(void *obj) { auto self = static_cast(obj); - std::array set_layouts{ - self->descriptor_set_layout_sprites + std::array set_layouts{ + self->descriptor_set_layout_projection, + self->descriptor_set_layout_sprite }; VkPipelineLayoutCreateInfo pipeline_layout_info{}; @@ -99,6 +137,122 @@ unload_pipeline_layout(void *obj) cg_core.vk_device_with_swapchain->device, self->pipeline_layout, nullptr); } +void +load_projection_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + try + { + self->ub_projection.reserve(cg_core.vk_swapchain->images_count); + for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++) + self->ub_projection.emplace_back( + cg_core.vk_device_with_swapchain, sizeof(VK::UBOProjection)); + } + catch(const std::exception& e) + { + throw CommandError{e.what()}; + } +} + +void +unload_projection_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + self->ub_projection.clear(); +} + +void +load_descriptor_pool(void *obj) +{ + auto self = static_cast(obj); + + VkDescriptorPoolSize descriptor_pool_size{}; + descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptor_pool_size.descriptorCount = self->ub_projection.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_projection.size(); + pool_info.poolSizeCount = 1; + pool_info.pPoolSizes = &descriptor_pool_size; + + if(vkCreateDescriptorPool( + cg_core.vk_device_with_swapchain->device, + &pool_info, nullptr, &self->descriptor_pool) != VK_SUCCESS) + throw CommandError{"Failed to create a Vulkan descriptor pool."}; +} + +void +unload_descriptor_pool(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyDescriptorPool( + cg_core.vk_device_with_swapchain->device, self->descriptor_pool, nullptr); +} + +void +load_projection_descriptor_sets(void *obj) +{ + auto self = static_cast(obj); + + std::vector layouts( + self->ub_projection.size(), + self->descriptor_set_layout_projection); + + 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->projection_descriptor_sets.resize(layouts.size()); + if(vkAllocateDescriptorSets( + cg_core.vk_device_with_swapchain->device, &alloc_info, + self->projection_descriptor_sets.data()) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan projection descriptor sets."}; +} + +void +load_resources_to_descriptor_sets(void *obj) +{ + auto self = static_cast(obj); + + for(auto i{0}; i < self->ub_projection.size(); i++) + { + VkDescriptorBufferInfo projection_info{}; + projection_info.buffer = self->ub_projection[i].buffer; + projection_info.offset = 0; + projection_info.range = sizeof(VK::UBOProjection); + + std::array write_descriptors{}; + write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptors[0].dstSet = self->projection_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 = &projection_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); + + VK::UBOProjection ubo_projection; + ubo_projection.proj = glm::ortho( + 0.0f, static_cast(cg_core.game_width), + 0.0f, static_cast(cg_core.game_height), + 0.0f, 100.0f); + self->ub_projection[i].copy_data(&ubo_projection); + } +} + void load_render_pass(void *obj) { @@ -393,9 +547,15 @@ unload_pipeline(void *obj) } const CommandChain loader{ - {&load_descriptor_set_layout_image_sprites, - &unload_descriptor_set_layout_image_sprites}, + {&load_descriptor_set_layout_projection, + &unload_descriptor_set_layout_projection}, + {&load_descriptor_set_layout_sprite, &unload_descriptor_set_layout_sprite}, {&load_pipeline_layout, &unload_pipeline_layout}, + {&load_projection_uniform_buffer, &unload_projection_uniform_buffer}, + {&load_descriptor_pool, &unload_descriptor_pool}, + // By destroying the pool the sets are also destroyed. + {&load_projection_descriptor_sets, nullptr}, + {&load_resources_to_descriptor_sets, nullptr}, {&load_render_pass, &unload_render_pass}, {&load_framebuffer, &unload_framebuffer}, {&load_pipeline, &unload_pipeline} @@ -436,7 +596,7 @@ GraphicsPipeline2D::draw( render_pass_begin.pClearValues = nullptr; vkCmdBeginRenderPass( - draw_command_buffer, &render_pass_begin,VK_SUBPASS_CONTENTS_INLINE); + draw_command_buffer, &render_pass_begin,VK_SUBPASS_CONTENTS_INLINE); VkViewport vk_viewport{}; vk_viewport.width = static_cast(cg_core.screen_width); @@ -457,12 +617,15 @@ GraphicsPipeline2D::draw( { // Commands { + std::array vk_descriptor_sets{ + this->projection_descriptor_sets[image_index], + sprite->descriptor_sets[image_index]}; VkDeviceSize offsets[]{0}; vkCmdBindDescriptorSets( draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - this->pipeline_layout, 0, 1, &sprite->descriptor_sets[image_index], - 0, nullptr); + this->pipeline_layout, 0, vk_descriptor_sets.size(), + vk_descriptor_sets.data(), 0, nullptr); vkCmdBindPipeline( draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, this->graphic_pipeline); diff --git a/src/vk/graphics_pipeline_2d.hpp b/src/vk/graphics_pipeline_2d.hpp index f6a1b47..dc122be 100644 --- a/src/vk/graphics_pipeline_2d.hpp +++ b/src/vk/graphics_pipeline_2d.hpp @@ -27,9 +27,16 @@ namespace VK struct GraphicsPipeline2D { - VkDescriptorSetLayout descriptor_set_layout_sprites; + VkDescriptorSetLayout descriptor_set_layout_projection; + VkDescriptorSetLayout descriptor_set_layout_sprite; VkPipelineLayout pipeline_layout; + // FIXME: if this vector get resized, it will cause a segmentation fault! + std::vector ub_projection; + + VkDescriptorPool descriptor_pool; + std::vector projection_descriptor_sets; + VkRenderPass render_pass; std::vector swapchain_framebuffers; VkPipeline graphic_pipeline; diff --git a/src/vk/sprite.cpp b/src/vk/sprite.cpp index e00fcbe..a7b65d7 100644 --- a/src/vk/sprite.cpp +++ b/src/vk/sprite.cpp @@ -137,7 +137,7 @@ load_descriptor_sets(void *obj) std::vector layouts( cg_core.vk_swapchain->images_count, - cg_core.vk_graphics_pipeline_2d->descriptor_set_layout_sprites); + cg_core.vk_graphics_pipeline_2d->descriptor_set_layout_sprite); VkDescriptorSetAllocateInfo alloc_info{}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; diff --git a/src/vk/uniform_buffer.hpp b/src/vk/uniform_buffer.hpp index 50759b8..2cee9ff 100644 --- a/src/vk/uniform_buffer.hpp +++ b/src/vk/uniform_buffer.hpp @@ -31,6 +31,11 @@ struct UBOSpritePositions glm::vec4 positions[128]; }; +struct UBOProjection +{ + glm::mat4 proj; +}; + struct UBOModelInstance { glm::mat4 instances[128]; -- cgit v1.2.3