summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFrederico Linhares <fred@linhares.blue>2022-08-31 17:43:57 -0300
committerFrederico Linhares <fred@linhares.blue>2022-08-31 17:43:57 -0300
commita646fe175c20d9d95c76d28d7f8de88b203a8b94 (patch)
tree0f42a9c45f514b5cce4469a17999596181fd85b4 /src
parentf1f1576543bb4e0f3b9bc4cd0ba4a12a70546c3c (diff)
feat Add projection to 2D graphics pipeline
Diffstat (limited to 'src')
-rw-r--r--src/vk/graphics_pipeline_2d.cpp187
-rw-r--r--src/vk/graphics_pipeline_2d.hpp9
-rw-r--r--src/vk/sprite.cpp2
-rw-r--r--src/vk/uniform_buffer.hpp5
4 files changed, 189 insertions, 14 deletions
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<VK::GraphicsPipeline2D*>(obj);
+
+ std::array<VkDescriptorSetLayoutBinding, 1> 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<uint32_t>(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<VK::GraphicsPipeline2D*>(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<VK::GraphicsPipeline2D*>(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<VK::GraphicsPipeline2D*>(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<VK::GraphicsPipeline2D*>(obj);
- std::array<VkDescriptorSetLayout, 1> set_layouts{
- self->descriptor_set_layout_sprites
+ std::array<VkDescriptorSetLayout, 2> set_layouts{
+ self->descriptor_set_layout_projection,
+ self->descriptor_set_layout_sprite
};
VkPipelineLayoutCreateInfo pipeline_layout_info{};
@@ -100,6 +138,122 @@ unload_pipeline_layout(void *obj)
}
void
+load_projection_uniform_buffer(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline2D*>(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<VK::GraphicsPipeline2D*>(obj);
+
+ self->ub_projection.clear();
+}
+
+void
+load_descriptor_pool(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline2D*>(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<VK::GraphicsPipeline2D*>(obj);
+
+ vkDestroyDescriptorPool(
+ cg_core.vk_device_with_swapchain->device, self->descriptor_pool, nullptr);
+}
+
+void
+load_projection_descriptor_sets(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline2D*>(obj);
+
+ std::vector<VkDescriptorSetLayout> 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<VK::GraphicsPipeline2D*>(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<VkWriteDescriptorSet, 1> 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<float>(cg_core.game_width),
+ 0.0f, static_cast<float>(cg_core.game_height),
+ 0.0f, 100.0f);
+ self->ub_projection[i].copy_data(&ubo_projection);
+ }
+}
+
+void
load_render_pass(void *obj)
{
auto self = static_cast<VK::GraphicsPipeline2D*>(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<float>(cg_core.screen_width);
@@ -457,12 +617,15 @@ GraphicsPipeline2D::draw(
{
// Commands
{
+ std::array<VkDescriptorSet, 2> 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<UniformBuffer> ub_projection;
+
+ VkDescriptorPool descriptor_pool;
+ std::vector<VkDescriptorSet> projection_descriptor_sets;
+
VkRenderPass render_pass;
std::vector<VkFramebuffer> 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<VkDescriptorSetLayout> 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];