summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederico Linhares <fred@linhares.blue>2022-09-08 13:59:17 -0300
committerFrederico Linhares <fred@linhares.blue>2022-09-08 13:59:17 -0300
commite386b9fd4ebc13a6a04def65585e795f4d39335d (patch)
tree76b37c85cba4730fefa3f14c8fcb72d1625175b2
parent2c60f5d4e44fec3b74d78dffe074416aec8a169f (diff)
refa Move layouts away from graphics pipelines
-rw-r--r--src/core.cpp193
-rw-r--r--src/core.hpp8
-rw-r--r--src/vk/graphics_pipeline_2d.cpp147
-rw-r--r--src/vk/graphics_pipeline_2d.hpp4
-rw-r--r--src/vk/graphics_pipeline_2d_layout.cpp232
-rw-r--r--src/vk/graphics_pipeline_2d_layout.hpp38
-rw-r--r--src/vk/graphics_pipeline_3d.cpp160
-rw-r--r--src/vk/graphics_pipeline_3d.hpp4
-rw-r--r--src/vk/graphics_pipeline_3d_layout.cpp252
-rw-r--r--src/vk/graphics_pipeline_3d_layout.hpp38
-rw-r--r--src/vk/model.cpp2
-rw-r--r--src/vk/sprite.cpp2
12 files changed, 651 insertions, 429 deletions
diff --git a/src/core.cpp b/src/core.cpp
index 2ad14bd..46fb6eb 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -452,154 +452,43 @@ unload_vk_swapchain(void *obj)
}
static void
-load_vk_render_pass_3d(void *obj)
-{
- std::array<VkAttachmentDescription, 2> attachments{};
- // Color attachment.
- attachments[0].flags = 0;
- attachments[0].format = cg_core.vk_swapchain->image_format;
- attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
- attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- // Depth attachment.
- attachments[1].flags = 0;
- attachments[1].format = VK_FORMAT_D32_SFLOAT;
- attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
- attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- attachments[1].finalLayout =
- VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
-
- VkAttachmentReference color_attachment_ref{};
- color_attachment_ref.attachment = 0;
- color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- VkAttachmentReference depth_attachment_ref{};
- depth_attachment_ref.attachment = 1;
- depth_attachment_ref.layout =
- VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
-
- VkSubpassDescription subpass = {};
- subpass.flags = 0;
- subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass.inputAttachmentCount = 0;
- subpass.pInputAttachments = nullptr;
- subpass.colorAttachmentCount = 1;
- subpass.pColorAttachments = &color_attachment_ref;
- subpass.pResolveAttachments = nullptr;
- subpass.pDepthStencilAttachment = &depth_attachment_ref;
- subpass.preserveAttachmentCount = 0;
- subpass.pPreserveAttachments = nullptr;
-
- VkSubpassDependency dependency = {};
- dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
- dependency.dstSubpass = 0;
- dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
- VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
- dependency.srcAccessMask = 0;
- dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
- VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
- dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
-
- VkRenderPassCreateInfo render_pass_info{};
- render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- render_pass_info.pNext = nullptr;
- render_pass_info.flags = 0;
- render_pass_info.attachmentCount = attachments.size();
- render_pass_info.pAttachments = attachments.data();
- render_pass_info.subpassCount = 1;
- render_pass_info.pSubpasses = &subpass;
- render_pass_info.dependencyCount = 1;
- render_pass_info.pDependencies = &dependency;
-
- if(vkCreateRenderPass(
- cg_core.vk_device_with_swapchain->device, &render_pass_info,
- nullptr, &cg_core.vk_render_pass_3d) != VK_SUCCESS)
- throw CommandError{"Failed to create Vulkan Render Pass 3D."};
-}
-
-static void
-unload_vk_render_pass_3d(void *obj)
-{
- vkDestroyRenderPass(
- cg_core.vk_device_with_swapchain->device, cg_core.vk_render_pass_3d,
- nullptr);
-}
-
-static void
-load_vk_render_pass_2d(void *obj)
-{
- std::array<VkAttachmentDescription, 1> attachments{};
- // Color attachment.
- attachments[0].flags = 0;
- attachments[0].format = cg_core.vk_swapchain->image_format;
- attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
- attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
-
- VkAttachmentReference color_attachment_ref{};
- color_attachment_ref.attachment = 0;
- color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
-
- VkSubpassDescription subpass{};
- subpass.flags = 0;
- subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass.inputAttachmentCount = 0;
- subpass.pInputAttachments = nullptr;
- subpass.colorAttachmentCount = 1;
- subpass.pColorAttachments = &color_attachment_ref;
- subpass.pResolveAttachments = nullptr;
- subpass.pDepthStencilAttachment = nullptr;
- subpass.preserveAttachmentCount = 0;
- subpass.pPreserveAttachments = nullptr;
-
- VkSubpassDependency dependency{};
- dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
- dependency.dstSubpass = 0;
- dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
- VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
- dependency.srcAccessMask = 0;
- dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
- VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
- dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
-
- VkRenderPassCreateInfo render_pass_info{};
- render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- render_pass_info.pNext = nullptr;
- render_pass_info.flags = 0;
- render_pass_info.attachmentCount = attachments.size();
- render_pass_info.pAttachments = attachments.data();
- render_pass_info.subpassCount = 1;
- render_pass_info.pSubpasses = &subpass;
- render_pass_info.dependencyCount = 1;
- render_pass_info.pDependencies = &dependency;
-
- if(vkCreateRenderPass(
- cg_core.vk_device_with_swapchain->device, &render_pass_info,
- nullptr, &cg_core.vk_render_pass_2d) != VK_SUCCESS)
- throw CommandError{"Failed to create Vulkan Render Pass 2D."};
-}
-
-static void
-unload_vk_render_pass_2d(void *obj)
-{
- vkDestroyRenderPass(
- cg_core.vk_device_with_swapchain->device, cg_core.vk_render_pass_2d,
- nullptr);
+load_vk_graphics_pipeline_3d_layout(void *obj)
+{
+ try
+ {
+ cg_core.vk_graphics_pipeline_3d_layout =
+ new VK::GraphicsPipeline3DLayout();
+ }
+ catch(const CommandError &e)
+ {
+ throw CommandError{"Failed to create 3d graphics pipeline."};
+ }
+}
+
+static void
+unload_vk_graphics_pipeline_3d_layout(void *obj)
+{
+ delete cg_core.vk_graphics_pipeline_3d_layout;
+}
+
+static void
+load_vk_graphics_pipeline_2d_layout(void *obj)
+{
+ try
+ {
+ cg_core.vk_graphics_pipeline_2d_layout =
+ new VK::GraphicsPipeline2DLayout();
+ }
+ catch(const CommandError &e)
+ {
+ throw CommandError{"Failed to create 2d graphics pipeline."};
+ }
+}
+
+static void
+unload_vk_graphics_pipeline_2d_layout(void *obj)
+{
+ delete cg_core.vk_graphics_pipeline_2d_layout;
}
static void
@@ -697,10 +586,14 @@ const CommandChain cg_sCore::loader{
#endif
{&load_vk_devices, &unload_vk_devices},
{&load_vk_swapchain, &unload_vk_swapchain},
- {&load_vk_render_pass_3d, &unload_vk_render_pass_3d},
- {&load_vk_render_pass_2d, &unload_vk_render_pass_2d},
+
+ {&load_vk_graphics_pipeline_3d_layout,
+ &unload_vk_graphics_pipeline_3d_layout},
+ {&load_vk_graphics_pipeline_2d_layout,
+ &unload_vk_graphics_pipeline_2d_layout},
{&load_vk_graphics_pipeline_3d, &unload_vk_graphics_pipeline_3d},
{&load_vk_graphics_pipeline_2d, &unload_vk_graphics_pipeline_2d},
+
{&load_vk_renderer, &unload_vk_renderer},
{&load_mruby, &unload_mruby},
{&load_mruby_symbols, nullptr}
diff --git a/src/core.hpp b/src/core.hpp
index 414173e..c7dbceb 100644
--- a/src/core.hpp
+++ b/src/core.hpp
@@ -42,6 +42,8 @@
#include "log.hpp"
#include "vk/device.hpp"
+#include "vk/graphics_pipeline_3d_layout.hpp"
+#include "vk/graphics_pipeline_2d_layout.hpp"
#include "vk/graphics_pipeline_3d.hpp"
#include "vk/graphics_pipeline_2d.hpp"
#include "vk/renderer.hpp"
@@ -105,10 +107,12 @@ struct cg_sCore
std::vector<VK::Device> vk_devices;
VK::Device *vk_device_with_swapchain;
VK::Swapchain *vk_swapchain;
- VkRenderPass vk_render_pass_3d;
- VkRenderPass vk_render_pass_2d;
+
+ VK::GraphicsPipeline3DLayout *vk_graphics_pipeline_3d_layout;
+ VK::GraphicsPipeline2DLayout *vk_graphics_pipeline_2d_layout;
VK::GraphicsPipeline3D *vk_graphics_pipeline_3d;
VK::GraphicsPipeline2D *vk_graphics_pipeline_2d;
+
VK::Renderer *vk_renderer;
bool quit_game;
diff --git a/src/vk/graphics_pipeline_2d.cpp b/src/vk/graphics_pipeline_2d.cpp
index bc1eca1..61cfe3f 100644
--- a/src/vk/graphics_pipeline_2d.cpp
+++ b/src/vk/graphics_pipeline_2d.cpp
@@ -25,119 +25,6 @@ namespace
{
void
-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);
-
- std::array<VkDescriptorSetLayoutBinding, 2> 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;
-
- layout_bindings[1].binding = 1;
- layout_bindings[1].descriptorType =
- VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- layout_bindings[1].descriptorCount = 1;
- layout_bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
- layout_bindings[1].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_sprite) != VK_SUCCESS)
- throw CommandError{
- "Failed to create Vulkan descriptor set layout for sprites."};
-}
-
-void
-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_sprite, nullptr);
-}
-
-void
-load_pipeline_layout(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline2D*>(obj);
-
- std::array<VkDescriptorSetLayout, 2> set_layouts{
- self->descriptor_set_layout_projection,
- self->descriptor_set_layout_sprite
- };
-
- VkPipelineLayoutCreateInfo pipeline_layout_info{};
- pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
- pipeline_layout_info.setLayoutCount = set_layouts.size();
- pipeline_layout_info.pSetLayouts = set_layouts.data();
- pipeline_layout_info.pushConstantRangeCount = 0;
- pipeline_layout_info.pPushConstantRanges = nullptr;
-
- if(vkCreatePipelineLayout(
- cg_core.vk_device_with_swapchain->device,
- &pipeline_layout_info, nullptr, &self->pipeline_layout) != VK_SUCCESS)
- throw CommandError{"Failed to create Vulkan pipeline layout."};
-}
-
-void
-unload_pipeline_layout(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline2D*>(obj);
-
- vkDestroyPipelineLayout(
- cg_core.vk_device_with_swapchain->device, self->pipeline_layout, nullptr);
-}
-
-void
load_projection_uniform_buffer(void *obj)
{
auto self = static_cast<VK::GraphicsPipeline2D*>(obj);
@@ -181,8 +68,8 @@ load_descriptor_pool(void *obj)
pool_info.pPoolSizes = &descriptor_pool_size;
if(vkCreateDescriptorPool(
- cg_core.vk_device_with_swapchain->device,
- &pool_info, nullptr, &self->descriptor_pool) != VK_SUCCESS)
+ cg_core.vk_device_with_swapchain->device, &pool_info, nullptr,
+ &self->descriptor_pool) != VK_SUCCESS)
throw CommandError{"Failed to create a Vulkan descriptor pool."};
}
@@ -192,7 +79,8 @@ unload_descriptor_pool(void *obj)
auto self = static_cast<VK::GraphicsPipeline2D*>(obj);
vkDestroyDescriptorPool(
- cg_core.vk_device_with_swapchain->device, self->descriptor_pool, nullptr);
+ cg_core.vk_device_with_swapchain->device, self->descriptor_pool,
+ nullptr);
}
void
@@ -202,7 +90,7 @@ load_projection_descriptor_sets(void *obj)
std::vector<VkDescriptorSetLayout> layouts(
self->ub_projection.size(),
- self->descriptor_set_layout_projection);
+ cg_core.vk_graphics_pipeline_2d_layout->descriptor_set_projection);
VkDescriptorSetAllocateInfo alloc_info{};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
@@ -267,7 +155,8 @@ load_framebuffer(void *obj)
VkFramebufferCreateInfo framebuffer_info{};
framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- framebuffer_info.renderPass = cg_core.vk_render_pass_2d;
+ framebuffer_info.renderPass =
+ cg_core.vk_graphics_pipeline_2d_layout->render_pass;
framebuffer_info.attachmentCount = attachments.size();
framebuffer_info.pAttachments = attachments.data();
framebuffer_info.width = cg_core.screen_width;
@@ -276,7 +165,8 @@ load_framebuffer(void *obj)
if(vkCreateFramebuffer(
cg_core.vk_device_with_swapchain->device, &framebuffer_info, nullptr,
- &self->swapchain_framebuffers[i]) != VK_SUCCESS)
+ &self->swapchain_framebuffers[i])
+ != VK_SUCCESS)
throw CommandError{"Failed to create Vulkan Framebuffer."};
}
}
@@ -454,15 +344,17 @@ load_pipeline(void *obj)
pipeline_info.pDepthStencilState = nullptr;
pipeline_info.pColorBlendState = &color_blending;
pipeline_info.pDynamicState = &dynamic_state_info;
- pipeline_info.layout = self->pipeline_layout;
- pipeline_info.renderPass = cg_core.vk_render_pass_2d;
+ pipeline_info.layout = cg_core.vk_graphics_pipeline_2d_layout->pipeline;
+ pipeline_info.renderPass =
+ cg_core.vk_graphics_pipeline_2d_layout->render_pass;
pipeline_info.subpass = 0;
pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
pipeline_info.basePipelineIndex = -1;
if(vkCreateGraphicsPipelines(
cg_core.vk_device_with_swapchain->device, VK_NULL_HANDLE, 1,
- &pipeline_info, nullptr, &self->graphic_pipeline) != VK_SUCCESS)
+ &pipeline_info, nullptr, &self->graphic_pipeline)
+ != VK_SUCCESS)
throw CommandError{"Failed to create graphics pipeline."};
}
@@ -476,10 +368,6 @@ unload_pipeline(void *obj)
}
const CommandChain loader{
- {&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.
@@ -515,7 +403,8 @@ GraphicsPipeline2D::draw(
VkRenderPassBeginInfo render_pass_begin{};
render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_begin.pNext = nullptr;
- render_pass_begin.renderPass = cg_core.vk_render_pass_2d;
+ render_pass_begin.renderPass =
+ cg_core.vk_graphics_pipeline_2d_layout->render_pass;
render_pass_begin.framebuffer = this->swapchain_framebuffers[image_index];
render_pass_begin.renderArea.offset = {0, 0};
render_pass_begin.renderArea.extent = {
@@ -552,8 +441,8 @@ GraphicsPipeline2D::draw(
vkCmdBindDescriptorSets(
draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
- this->pipeline_layout, 0, vk_descriptor_sets.size(),
- vk_descriptor_sets.data(), 0, nullptr);
+ cg_core.vk_graphics_pipeline_2d_layout->pipeline, 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 dc122be..193c06d 100644
--- a/src/vk/graphics_pipeline_2d.hpp
+++ b/src/vk/graphics_pipeline_2d.hpp
@@ -27,10 +27,6 @@ namespace VK
struct GraphicsPipeline2D
{
- 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;
diff --git a/src/vk/graphics_pipeline_2d_layout.cpp b/src/vk/graphics_pipeline_2d_layout.cpp
new file mode 100644
index 0000000..f8822b9
--- /dev/null
+++ b/src/vk/graphics_pipeline_2d_layout.cpp
@@ -0,0 +1,232 @@
+/*
+ * 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 "graphics_pipeline_2d_layout.hpp"
+
+#include <array>
+
+#include "../core.hpp"
+
+namespace
+{
+
+void
+load_descriptor_set_layout_projection(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline2DLayout*>(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_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::GraphicsPipeline2DLayout*>(obj);
+
+ vkDestroyDescriptorSetLayout(
+ cg_core.vk_device_with_swapchain->device, self->descriptor_set_projection,
+ nullptr);
+}
+
+void
+load_descriptor_set_layout_sprite(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj);
+
+ std::array<VkDescriptorSetLayoutBinding, 2> 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;
+
+ layout_bindings[1].binding = 1;
+ layout_bindings[1].descriptorType =
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ layout_bindings[1].descriptorCount = 1;
+ layout_bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+ layout_bindings[1].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_sprite) != VK_SUCCESS)
+ throw CommandError{
+ "Failed to create Vulkan descriptor set layout for sprites."};
+}
+
+void
+unload_descriptor_set_layout_sprite(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj);
+
+ vkDestroyDescriptorSetLayout(
+ cg_core.vk_device_with_swapchain->device,
+ self->descriptor_set_sprite, nullptr);
+}
+
+void
+load_pipeline_layout(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj);
+
+ std::array<VkDescriptorSetLayout, 2> set_layouts{
+ self->descriptor_set_projection, self->descriptor_set_sprite
+ };
+
+ VkPipelineLayoutCreateInfo pipeline_layout_info{};
+ pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipeline_layout_info.setLayoutCount = set_layouts.size();
+ pipeline_layout_info.pSetLayouts = set_layouts.data();
+ pipeline_layout_info.pushConstantRangeCount = 0;
+ pipeline_layout_info.pPushConstantRanges = nullptr;
+
+ if(vkCreatePipelineLayout(
+ cg_core.vk_device_with_swapchain->device, &pipeline_layout_info,
+ nullptr, &self->pipeline) != VK_SUCCESS)
+ throw CommandError{"Failed to create Vulkan pipeline layout."};
+}
+
+void
+unload_pipeline_layout(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj);
+
+ vkDestroyPipelineLayout(
+ cg_core.vk_device_with_swapchain->device, self->pipeline, nullptr);
+}
+
+void
+load_render_pass(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj);
+
+ std::array<VkAttachmentDescription, 1> attachments{};
+ // Color attachment.
+ attachments[0].flags = 0;
+ attachments[0].format = cg_core.vk_swapchain->image_format;
+ attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
+ attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+ VkAttachmentReference color_attachment_ref{};
+ color_attachment_ref.attachment = 0;
+ color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription subpass{};
+ subpass.flags = 0;
+ subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass.inputAttachmentCount = 0;
+ subpass.pInputAttachments = nullptr;
+ subpass.colorAttachmentCount = 1;
+ subpass.pColorAttachments = &color_attachment_ref;
+ subpass.pResolveAttachments = nullptr;
+ subpass.pDepthStencilAttachment = nullptr;
+ subpass.preserveAttachmentCount = 0;
+ subpass.pPreserveAttachments = nullptr;
+
+ VkSubpassDependency dependency{};
+ dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
+ dependency.dstSubpass = 0;
+ dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
+ VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
+ dependency.srcAccessMask = 0;
+ dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
+ VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
+ dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ VkRenderPassCreateInfo render_pass_info{};
+ render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ render_pass_info.pNext = nullptr;
+ render_pass_info.flags = 0;
+ render_pass_info.attachmentCount = attachments.size();
+ render_pass_info.pAttachments = attachments.data();
+ render_pass_info.subpassCount = 1;
+ render_pass_info.pSubpasses = &subpass;
+ render_pass_info.dependencyCount = 1;
+ render_pass_info.pDependencies = &dependency;
+
+ if(vkCreateRenderPass(
+ cg_core.vk_device_with_swapchain->device, &render_pass_info,
+ nullptr, &self->render_pass) != VK_SUCCESS)
+ throw CommandError{"Failed to create Vulkan Render Pass 2D."};
+}
+
+static void
+unload_render_pass(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj);
+
+ vkDestroyRenderPass(
+ cg_core.vk_device_with_swapchain->device, self->render_pass, nullptr);
+}
+
+const CommandChain loader{
+ {&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_render_pass, &unload_render_pass}
+};
+
+}
+
+namespace VK
+{
+
+GraphicsPipeline2DLayout::GraphicsPipeline2DLayout()
+{
+ loader.execute(this);
+}
+
+GraphicsPipeline2DLayout::~GraphicsPipeline2DLayout()
+{
+ loader.revert(this);
+}
+
+}
diff --git a/src/vk/graphics_pipeline_2d_layout.hpp b/src/vk/graphics_pipeline_2d_layout.hpp
new file mode 100644
index 0000000..520bbc1
--- /dev/null
+++ b/src/vk/graphics_pipeline_2d_layout.hpp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_LAYOUT_H
+#define CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_LAYOUT_H 1
+
+#include "core.hpp"
+
+namespace VK
+{
+
+struct GraphicsPipeline2DLayout
+{
+ VkDescriptorSetLayout descriptor_set_projection;
+ VkDescriptorSetLayout descriptor_set_sprite;
+ VkPipelineLayout pipeline;
+ VkRenderPass render_pass;
+
+ GraphicsPipeline2DLayout();
+ ~GraphicsPipeline2DLayout();
+};
+
+}
+
+#endif /* CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_LAYOUT_H */
diff --git a/src/vk/graphics_pipeline_3d.cpp b/src/vk/graphics_pipeline_3d.cpp
index de5adde..31e9365 100644
--- a/src/vk/graphics_pipeline_3d.cpp
+++ b/src/vk/graphics_pipeline_3d.cpp
@@ -28,123 +28,6 @@ namespace
{
void
-load_descriptor_set_layout_model_instance(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline3D*>(obj);
-
- std::array<VkDescriptorSetLayoutBinding, 2> 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;
-
- layout_bindings[1].binding = 1;
- layout_bindings[1].descriptorType =
- VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- layout_bindings[1].descriptorCount = 1;
- layout_bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
- layout_bindings[1].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_model_instance) != VK_SUCCESS)
- throw CommandError{
- "Failed to create Vulkan descriptor set layout for model instance."};
-}
-
-void
-unload_descriptor_set_layout_model_instance(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline3D*>(obj);
-
- vkDestroyDescriptorSetLayout(
- cg_core.vk_device_with_swapchain->device,
- self->descriptor_set_layout_model_instance, nullptr);
-}
-
-void
-load_descriptor_set_layout_world_view(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline3D*>(obj);
-
- std::array<VkDescriptorSetLayoutBinding, 2> set_layouts{};
- set_layouts[0].binding = 0;
- set_layouts[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- set_layouts[0].descriptorCount = 1;
- set_layouts[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
- set_layouts[0].pImmutableSamplers = nullptr;
-
- set_layouts[1].binding = 1;
- set_layouts[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- set_layouts[1].descriptorCount = 1;
- set_layouts[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
- set_layouts[1].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 = set_layouts.size();
- layout_info.pBindings = set_layouts.data();
-
- if(vkCreateDescriptorSetLayout(
- cg_core.vk_device_with_swapchain->device, &layout_info, nullptr,
- &self->descriptor_set_layout_world_view) != VK_SUCCESS)
- throw CommandError{
- "Failed to create Vulkan descriptor set layout for world view."};
-}
-
-void
-unload_descriptor_set_layout_world_view(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline3D*>(obj);
-
- vkDestroyDescriptorSetLayout(
- cg_core.vk_device_with_swapchain->device,
- self->descriptor_set_layout_world_view, nullptr);
-}
-
-void
-load_pipeline_layout(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline3D*>(obj);
-
- std::array<VkDescriptorSetLayout, 2> set_layouts{
- self->descriptor_set_layout_world_view,
- self->descriptor_set_layout_model_instance};
-
- VkPipelineLayoutCreateInfo pipeline_layout_info{};
- pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
- pipeline_layout_info.setLayoutCount = set_layouts.size();
- pipeline_layout_info.pSetLayouts = set_layouts.data();
- pipeline_layout_info.pushConstantRangeCount = 0;
- pipeline_layout_info.pPushConstantRanges = nullptr;
-
- if(vkCreatePipelineLayout(
- cg_core.vk_device_with_swapchain->device,
- &pipeline_layout_info, nullptr, &self->pipeline_layout) != VK_SUCCESS)
- throw CommandError{"Failed to create Vulkan pipeline layout."};
-}
-
-void
-unload_pipeline_layout(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline3D*>(obj);
-
- vkDestroyPipelineLayout(
- cg_core.vk_device_with_swapchain->device, self->pipeline_layout, nullptr);
-}
-
-void
load_view_projection_uniform_buffer(void *obj)
{
auto self = static_cast<VK::GraphicsPipeline3D*>(obj);
@@ -210,14 +93,14 @@ load_descriptor_pool(void *obj)
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.pNext = nullptr;
pool_info.flags = 0;
- pool_info.maxSets =
- self->ub_view_projection.size() + self->ub_directional_light.size();
+ pool_info.maxSets = self->ub_view_projection.size() +
+ self->ub_directional_light.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)
+ cg_core.vk_device_with_swapchain->device, &pool_info, nullptr,
+ &self->descriptor_pool) != VK_SUCCESS)
throw CommandError{"Failed to create a Vulkan descriptor pool."};
}
@@ -227,7 +110,8 @@ unload_descriptor_pool(void *obj)
auto self = static_cast<VK::GraphicsPipeline3D*>(obj);
vkDestroyDescriptorPool(
- cg_core.vk_device_with_swapchain->device, self->descriptor_pool, nullptr);
+ cg_core.vk_device_with_swapchain->device, self->descriptor_pool,
+ nullptr);
}
void
@@ -237,7 +121,7 @@ load_world_view_descriptor_sets(void *obj)
std::vector<VkDescriptorSetLayout> layouts(
cg_core.vk_swapchain->images_count,
- self->descriptor_set_layout_world_view);
+ cg_core.vk_graphics_pipeline_3d_layout->descriptor_set_world_view);
VkDescriptorSetAllocateInfo alloc_info{};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
@@ -334,10 +218,11 @@ unload_depth_image(void *obj)
auto self = static_cast<VK::GraphicsPipeline3D*>(obj);
vkDestroyImage(
- cg_core.vk_device_with_swapchain->device, self->depth_image, nullptr);
- vkFreeMemory(
- cg_core.vk_device_with_swapchain->device, self->depth_image_memory,
+ cg_core.vk_device_with_swapchain->device, self->depth_image,
nullptr);
+ vkFreeMemory(
+ cg_core.vk_device_with_swapchain->device,
+ self->depth_image_memory, nullptr);
}
void
@@ -384,7 +269,8 @@ load_framebuffer(void *obj)
VkFramebufferCreateInfo framebuffer_info{};
framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- framebuffer_info.renderPass = cg_core.vk_render_pass_3d;
+ framebuffer_info.renderPass =
+ cg_core.vk_graphics_pipeline_3d_layout->render_pass;
framebuffer_info.attachmentCount = attachments.size();
framebuffer_info.pAttachments = attachments.data();
framebuffer_info.width = cg_core.screen_width;
@@ -595,15 +481,17 @@ load_pipeline(void *obj)
pipeline_info.pDepthStencilState = &depth_stencil;
pipeline_info.pColorBlendState = &color_blending;
pipeline_info.pDynamicState = &dynamic_state_info;
- pipeline_info.layout = self->pipeline_layout;
- pipeline_info.renderPass = cg_core.vk_render_pass_3d;
+ pipeline_info.layout = cg_core.vk_graphics_pipeline_3d_layout->pipeline;
+ pipeline_info.renderPass =
+ cg_core.vk_graphics_pipeline_3d_layout->render_pass;
pipeline_info.subpass = 0;
pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
pipeline_info.basePipelineIndex = -1;
if(vkCreateGraphicsPipelines(
cg_core.vk_device_with_swapchain->device, VK_NULL_HANDLE, 1,
- &pipeline_info, nullptr, &self->graphic_pipeline) != VK_SUCCESS)
+ &pipeline_info, nullptr, &self->graphic_pipeline)
+ != VK_SUCCESS)
throw CommandError{"Failed to create graphics pipeline."};
}
@@ -617,11 +505,6 @@ unload_pipeline(void *obj)
}
const CommandChain loader{
- {&load_descriptor_set_layout_model_instance,
- &unload_descriptor_set_layout_model_instance},
- {&load_descriptor_set_layout_world_view,
- &unload_descriptor_set_layout_world_view},
- {&load_pipeline_layout, &unload_pipeline_layout},
{&load_view_projection_uniform_buffer,
&unload_view_projection_uniform_buffer},
{&load_directional_light_uniform_buffer,
@@ -669,7 +552,8 @@ GraphicsPipeline3D::draw(
VkRenderPassBeginInfo render_pass_begin{};
render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_begin.pNext = nullptr;
- render_pass_begin.renderPass = cg_core.vk_render_pass_3d;
+ render_pass_begin.renderPass =
+ cg_core.vk_graphics_pipeline_3d_layout->render_pass;
render_pass_begin.framebuffer = this->swapchain_framebuffers[image_index];
render_pass_begin.renderArea.offset = {0, 0};
render_pass_begin.renderArea.extent = {
@@ -707,8 +591,8 @@ GraphicsPipeline3D::draw(
vkCmdBindDescriptorSets(
draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
- this->pipeline_layout, 0, vk_descriptor_sets.size(),
- vk_descriptor_sets.data(), 0, nullptr);
+ cg_core.vk_graphics_pipeline_3d_layout->pipeline, 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_3d.hpp b/src/vk/graphics_pipeline_3d.hpp
index d14479f..97ca63c 100644
--- a/src/vk/graphics_pipeline_3d.hpp
+++ b/src/vk/graphics_pipeline_3d.hpp
@@ -32,10 +32,6 @@ namespace VK
struct GraphicsPipeline3D
{
- VkDescriptorSetLayout descriptor_set_layout_model_instance;
- VkDescriptorSetLayout descriptor_set_layout_world_view;
- VkPipelineLayout pipeline_layout;
-
// Depth image.
VkImage depth_image;
VkDeviceMemory depth_image_memory;
diff --git a/src/vk/graphics_pipeline_3d_layout.cpp b/src/vk/graphics_pipeline_3d_layout.cpp
new file mode 100644
index 0000000..62c894c
--- /dev/null
+++ b/src/vk/graphics_pipeline_3d_layout.cpp
@@ -0,0 +1,252 @@
+/*
+ * 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 "graphics_pipeline_3d_layout.hpp"
+
+#include <array>
+
+#include "../core.hpp"
+
+namespace
+{
+void
+load_descriptor_set_layout_world_view(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline3DLayout*>(obj);
+
+ std::array<VkDescriptorSetLayoutBinding, 2> set_layouts{};
+ set_layouts[0].binding = 0;
+ set_layouts[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ set_layouts[0].descriptorCount = 1;
+ set_layouts[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+ set_layouts[0].pImmutableSamplers = nullptr;
+
+ set_layouts[1].binding = 1;
+ set_layouts[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ set_layouts[1].descriptorCount = 1;
+ set_layouts[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+ set_layouts[1].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 = set_layouts.size();
+ layout_info.pBindings = set_layouts.data();
+
+ if(vkCreateDescriptorSetLayout(
+ cg_core.vk_device_with_swapchain->device, &layout_info, nullptr,
+ &self->descriptor_set_world_view) != VK_SUCCESS)
+ throw CommandError{
+ "Failed to create Vulkan descriptor set layout for world view."};
+}
+
+void
+unload_descriptor_set_layout_world_view(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline3DLayout*>(obj);
+
+ vkDestroyDescriptorSetLayout(
+ cg_core.vk_device_with_swapchain->device,
+ self->descriptor_set_world_view, nullptr);
+}
+
+void
+load_descriptor_set_layout_model_instance(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline3DLayout*>(obj);
+
+ std::array<VkDescriptorSetLayoutBinding, 2> 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;
+
+ layout_bindings[1].binding = 1;
+ layout_bindings[1].descriptorType =
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ layout_bindings[1].descriptorCount = 1;
+ layout_bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+ layout_bindings[1].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_model_instance) != VK_SUCCESS)
+ throw CommandError{
+ "Failed to create Vulkan descriptor set layout for model instance."};
+}
+
+void
+unload_descriptor_set_layout_model_instance(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline3DLayout*>(obj);
+
+ vkDestroyDescriptorSetLayout(
+ cg_core.vk_device_with_swapchain->device,
+ self->descriptor_set_model_instance, nullptr);
+}
+
+void
+load_pipeline_layout(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline3DLayout*>(obj);
+
+ std::array<VkDescriptorSetLayout, 2> set_layouts{
+ self->descriptor_set_world_view,
+ self->descriptor_set_model_instance};
+
+ VkPipelineLayoutCreateInfo pipeline_layout_info{};
+ pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipeline_layout_info.setLayoutCount = set_layouts.size();
+ pipeline_layout_info.pSetLayouts = set_layouts.data();
+ pipeline_layout_info.pushConstantRangeCount = 0;
+ pipeline_layout_info.pPushConstantRanges = nullptr;
+
+ if(vkCreatePipelineLayout(
+ cg_core.vk_device_with_swapchain->device,
+ &pipeline_layout_info, nullptr, &self->pipeline) != VK_SUCCESS)
+ throw CommandError{"Failed to create Vulkan pipeline layout."};
+}
+
+void
+unload_pipeline_layout(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline3DLayout*>(obj);
+
+ vkDestroyPipelineLayout(
+ cg_core.vk_device_with_swapchain->device, self->pipeline, nullptr);
+}
+
+void
+load_render_pass(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline3DLayout*>(obj);
+
+ std::array<VkAttachmentDescription, 2> attachments{};
+ // Color attachment.
+ attachments[0].flags = 0;
+ attachments[0].format = cg_core.vk_swapchain->image_format;
+ attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
+ attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ // Depth attachment.
+ attachments[1].flags = 0;
+ attachments[1].format = VK_FORMAT_D32_SFLOAT;
+ attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
+ attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attachments[1].finalLayout =
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference color_attachment_ref{};
+ color_attachment_ref.attachment = 0;
+ color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ VkAttachmentReference depth_attachment_ref{};
+ depth_attachment_ref.attachment = 1;
+ depth_attachment_ref.layout =
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription subpass = {};
+ subpass.flags = 0;
+ subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass.inputAttachmentCount = 0;
+ subpass.pInputAttachments = nullptr;
+ subpass.colorAttachmentCount = 1;
+ subpass.pColorAttachments = &color_attachment_ref;
+ subpass.pResolveAttachments = nullptr;
+ subpass.pDepthStencilAttachment = &depth_attachment_ref;
+ subpass.preserveAttachmentCount = 0;
+ subpass.pPreserveAttachments = nullptr;
+
+ VkSubpassDependency dependency = {};
+ dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
+ dependency.dstSubpass = 0;
+ dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
+ VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
+ dependency.srcAccessMask = 0;
+ dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
+ VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
+ dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ VkRenderPassCreateInfo render_pass_info{};
+ render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ render_pass_info.pNext = nullptr;
+ render_pass_info.flags = 0;
+ render_pass_info.attachmentCount = attachments.size();
+ render_pass_info.pAttachments = attachments.data();
+ render_pass_info.subpassCount = 1;
+ render_pass_info.pSubpasses = &subpass;
+ render_pass_info.dependencyCount = 1;
+ render_pass_info.pDependencies = &dependency;
+
+ if(vkCreateRenderPass(
+ cg_core.vk_device_with_swapchain->device, &render_pass_info, nullptr,
+ &self->render_pass) != VK_SUCCESS)
+ throw CommandError{"Failed to create Vulkan Render Pass 3D."};
+}
+
+void
+unload_render_pass(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline3DLayout*>(obj);
+
+ vkDestroyRenderPass(
+ cg_core.vk_device_with_swapchain->device, self->render_pass, nullptr);
+}
+
+const CommandChain loader{
+ {&load_descriptor_set_layout_world_view,
+ &unload_descriptor_set_layout_world_view},
+ {&load_descriptor_set_layout_model_instance,
+ &unload_descriptor_set_layout_model_instance},
+ {&load_pipeline_layout, &unload_pipeline_layout},
+ {&load_render_pass, &unload_render_pass}
+};
+
+}
+
+namespace VK
+{
+
+GraphicsPipeline3DLayout::GraphicsPipeline3DLayout()
+{
+ loader.execute(this);
+}
+
+GraphicsPipeline3DLayout::~GraphicsPipeline3DLayout()
+{
+ loader.revert(this);
+}
+
+}
diff --git a/src/vk/graphics_pipeline_3d_layout.hpp b/src/vk/graphics_pipeline_3d_layout.hpp
new file mode 100644
index 0000000..296bdb2
--- /dev/null
+++ b/src/vk/graphics_pipeline_3d_layout.hpp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef CANDY_GEAR_VK_GRAPHICS_PIPELINE_3D_LAYOUT_H
+#define CANDY_GEAR_VK_GRAPHICS_PIPELINE_3D_LAYOUT_H 1
+
+#include "core.hpp"
+
+namespace VK
+{
+
+struct GraphicsPipeline3DLayout
+{
+ VkDescriptorSetLayout descriptor_set_world_view;
+ VkDescriptorSetLayout descriptor_set_model_instance;
+ VkPipelineLayout pipeline;
+ VkRenderPass render_pass;
+
+ GraphicsPipeline3DLayout();
+ ~GraphicsPipeline3DLayout();
+};
+
+}
+
+#endif /* CANDY_GEAR_VK_GRAPHICS_PIPELINE_3D_LAYOUT_H */
diff --git a/src/vk/model.cpp b/src/vk/model.cpp
index 240ad13..b92ec91 100644
--- a/src/vk/model.cpp
+++ b/src/vk/model.cpp
@@ -195,7 +195,7 @@ load_descriptor_sets(void *obj)
std::vector<VkDescriptorSetLayout> layouts(
cg_core.vk_swapchain->images_count,
- cg_core.vk_graphics_pipeline_3d->descriptor_set_layout_model_instance);
+ cg_core.vk_graphics_pipeline_3d_layout->descriptor_set_model_instance);
VkDescriptorSetAllocateInfo alloc_info{};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
diff --git a/src/vk/sprite.cpp b/src/vk/sprite.cpp
index a7b65d7..9a718d7 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_sprite);
+ cg_core.vk_graphics_pipeline_2d_layout->descriptor_set_sprite);
VkDescriptorSetAllocateInfo alloc_info{};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;