summaryrefslogtreecommitdiff
path: root/src/vk
diff options
context:
space:
mode:
authorFrederico Linhares <fred@linhares.blue>2022-09-21 13:57:31 -0300
committerFrederico Linhares <fred@linhares.blue>2022-09-21 14:33:18 -0300
commit78db82c0dac8db90a3de1004e5428f225947b2b9 (patch)
treef6e6191a7974b2d15b92a9a67fab167bb330ca61 /src/vk
parentdafe4a4335f48ce4098935bdf0333beac2ded2ed (diff)
feat Create View2D
Diffstat (limited to 'src/vk')
-rw-r--r--src/vk/graphics_pipeline_2d.cpp24
-rw-r--r--src/vk/graphics_pipeline_2d.hpp5
-rw-r--r--src/vk/graphics_pipeline_3d.cpp2
-rw-r--r--src/vk/graphics_pipeline_3d.hpp4
-rw-r--r--src/vk/renderer.cpp31
-rw-r--r--src/vk/renderer.hpp12
-rw-r--r--src/vk/view_2d.cpp (renamed from src/vk/view.cpp)122
-rw-r--r--src/vk/view_2d.hpp (renamed from src/vk/view.hpp)24
-rw-r--r--src/vk/view_3d.cpp159
-rw-r--r--src/vk/view_3d.hpp47
10 files changed, 280 insertions, 150 deletions
diff --git a/src/vk/graphics_pipeline_2d.cpp b/src/vk/graphics_pipeline_2d.cpp
index 08bdb6e..1509d2f 100644
--- a/src/vk/graphics_pipeline_2d.cpp
+++ b/src/vk/graphics_pipeline_2d.cpp
@@ -47,8 +47,8 @@ load_framebuffer(void *obj)
framebuffer_info.layers = 1;
if(vkCreateFramebuffer(
- cg_core.vk_device_with_swapchain->device, &framebuffer_info, nullptr,
- &self->swapchain_framebuffers[i])
+ cg_core.vk_device_with_swapchain->device, &framebuffer_info, nullptr,
+ &self->swapchain_framebuffers[i])
!= VK_SUCCESS)
throw CommandError{"Failed to create Vulkan Framebuffer."};
}
@@ -272,7 +272,7 @@ GraphicsPipeline2D::~GraphicsPipeline2D()
void
GraphicsPipeline2D::draw(
- std::shared_ptr<View> view, const VkCommandBuffer draw_command_buffer,
+ std::shared_ptr<View2D> view, const VkCommandBuffer draw_command_buffer,
const size_t current_frame, const size_t next_frame,
const uint32_t image_index)
{
@@ -301,21 +301,21 @@ GraphicsPipeline2D::draw(
// Commands
{
std::array<VkDescriptorSet, 2> vk_descriptor_sets{
- view->descriptor_sets_2d[image_index],
- sprite->descriptor_sets[image_index]};
+ view->descriptor_sets_2d[image_index],
+ sprite->descriptor_sets[image_index]};
VkDeviceSize offsets[]{0};
vkCmdBindDescriptorSets(
- draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
- cg_core.vk_graphics_pipeline_2d_layout->pipeline, 0,
- vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr);
+ draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
+ 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);
+ draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
+ this->graphic_pipeline);
vkCmdBindVertexBuffers(
- draw_command_buffer, 0, 1, &sprite->vertex_buffer->buffer, offsets);
+ draw_command_buffer, 0, 1, &sprite->vertex_buffer->buffer, offsets);
vkCmdDraw(
- draw_command_buffer, Sprite::vertex_count, positions.size(), 0, 0);
+ draw_command_buffer, Sprite::vertex_count, positions.size(), 0, 0);
}
VK::UBOSpritePositions ubo_sprite_positions;
diff --git a/src/vk/graphics_pipeline_2d.hpp b/src/vk/graphics_pipeline_2d.hpp
index dd4bb29..ffa373a 100644
--- a/src/vk/graphics_pipeline_2d.hpp
+++ b/src/vk/graphics_pipeline_2d.hpp
@@ -23,14 +23,13 @@
#include "core.hpp"
#include "sprite.hpp"
-#include "view.hpp"
+#include "view_2d.hpp"
namespace VK
{
struct GraphicsPipeline2D
{
- VkRenderPass render_pass;
std::vector<VkFramebuffer> swapchain_framebuffers;
VkPipeline graphic_pipeline;
@@ -38,7 +37,7 @@ struct GraphicsPipeline2D
~GraphicsPipeline2D();
void
- draw(std::shared_ptr<View> view, const VkCommandBuffer draw_command_buffer,
+ draw(std::shared_ptr<View2D> view, const VkCommandBuffer draw_command_buffer,
const size_t current_frame, const size_t next_frame,
const uint32_t image_index);
};
diff --git a/src/vk/graphics_pipeline_3d.cpp b/src/vk/graphics_pipeline_3d.cpp
index 02fbfd9..fbf5b80 100644
--- a/src/vk/graphics_pipeline_3d.cpp
+++ b/src/vk/graphics_pipeline_3d.cpp
@@ -534,7 +534,7 @@ GraphicsPipeline3D::~GraphicsPipeline3D()
void
GraphicsPipeline3D::draw(
- std::shared_ptr<View> view, const VkCommandBuffer draw_command_buffer,
+ std::shared_ptr<View3D> view, const VkCommandBuffer draw_command_buffer,
const size_t current_frame, const uint32_t image_index)
{
// Set viewport
diff --git a/src/vk/graphics_pipeline_3d.hpp b/src/vk/graphics_pipeline_3d.hpp
index a7cf117..925df77 100644
--- a/src/vk/graphics_pipeline_3d.hpp
+++ b/src/vk/graphics_pipeline_3d.hpp
@@ -26,7 +26,7 @@
#include "model.hpp"
#include "model_instance.hpp"
#include "uniform_buffer.hpp"
-#include "view.hpp"
+#include "view_3d.hpp"
namespace VK
{
@@ -52,7 +52,7 @@ struct GraphicsPipeline3D
~GraphicsPipeline3D();
void
- draw(std::shared_ptr<View> view, const VkCommandBuffer draw_command_buffer,
+ draw(std::shared_ptr<View3D> view, const VkCommandBuffer draw_command_buffer,
const size_t current_frame, const uint32_t image_index);
};
diff --git a/src/vk/renderer.cpp b/src/vk/renderer.cpp
index 7531e19..5ebc271 100644
--- a/src/vk/renderer.cpp
+++ b/src/vk/renderer.cpp
@@ -29,8 +29,10 @@ load_descriptor_pool(void *obj)
auto self = static_cast<VK::Renderer*>(obj);
uint32_t uniform_buffer_count = 0;
- for(auto &view : self->views)
+ for(auto &view : self->views_3d)
uniform_buffer_count += (view->ub_3d.size() + view->ub_2d.size());
+ for(auto &view : self->views_2d)
+ uniform_buffer_count += (view->ub_2d.size());
VkDescriptorPoolSize descriptor_pool_size{};
descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
@@ -49,7 +51,9 @@ load_descriptor_pool(void *obj)
&self->descriptor_pool) != VK_SUCCESS)
throw CommandError{"Failed to create a Vulkan descriptor pool."};
- for(auto &view : self->views)
+ for(auto &view : self->views_3d)
+ view->load_descriptor_sets(self->descriptor_pool);
+ for(auto &view : self->views_2d)
view->load_descriptor_sets(self->descriptor_pool);
}
@@ -58,7 +62,8 @@ unload_descriptor_pool(void *obj)
{
auto self = static_cast<VK::Renderer*>(obj);
- for(auto &view : self->views) view->unload_descriptor_sets();
+ for(auto &view : self->views_3d) view->unload_descriptor_sets();
+ for(auto &view : self->views_2d) view->unload_descriptor_sets();
vkDestroyDescriptorPool(
cg_core.vk_device_with_swapchain->device, self->descriptor_pool,
@@ -136,15 +141,18 @@ const CommandChain loader{
namespace VK
{
-Renderer::Renderer(std::vector<std::shared_ptr<View>> views):
+Renderer::Renderer(std::vector<std::shared_ptr<View2D>> views_2d,
+ std::vector<std::shared_ptr<View3D>> views_3d):
models_to_draw{cg_core.vk_swapchain->images_count},
- views{views}
+ views_2d{views_2d},
+ views_3d{views_3d}
{
loader.execute(this);
}
-Renderer::Renderer(std::initializer_list<std::shared_ptr<View>> views):
- Renderer{std::vector<std::shared_ptr<View>>(views)}
+Renderer::Renderer(std::initializer_list<std::shared_ptr<View2D>> views_2d,
+ std::initializer_list<std::shared_ptr<View3D>> views_3d):
+ Renderer(std::vector(views_2d), std::vector(views_3d))
{
}
@@ -212,7 +220,7 @@ Renderer::draw()
vkCmdBeginRenderPass(
draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
- for(auto &view: this->views)
+ for(auto &view: this->views_3d)
cg_core.vk_graphics_pipeline_3d->draw(
view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
image_index);
@@ -239,7 +247,12 @@ Renderer::draw()
vkCmdBeginRenderPass(
draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
- for(auto &view: this->views)
+ for(auto &view: this->views_2d)
+ cg_core.vk_graphics_pipeline_2d->draw(
+ view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
+ next_frame, image_index);
+
+ for(auto &view: this->views_3d)
cg_core.vk_graphics_pipeline_2d->draw(
view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
next_frame, image_index);
diff --git a/src/vk/renderer.hpp b/src/vk/renderer.hpp
index 2b913fe..551e4e5 100644
--- a/src/vk/renderer.hpp
+++ b/src/vk/renderer.hpp
@@ -25,7 +25,8 @@
#include "model.hpp"
#include "model_instance.hpp"
#include "queue_family.hpp"
-#include "view.hpp"
+#include "view_2d.hpp"
+#include "view_3d.hpp"
namespace VK
{
@@ -37,13 +38,16 @@ struct Renderer
models_to_draw;
VkDescriptorPool descriptor_pool;
- std::vector<std::shared_ptr<View>> views;
+ std::vector<std::shared_ptr<View2D>> views_2d;
+ std::vector<std::shared_ptr<View3D>> views_3d;
QueueFamily *queue_family;
VkCommandPool command_pool;
std::vector<VkCommandBuffer> draw_command_buffers;
- Renderer(std::vector<std::shared_ptr<View>> views);
- Renderer(std::initializer_list<std::shared_ptr<View>> views);
+ Renderer(std::vector<std::shared_ptr<View2D>> views_2d,
+ std::vector<std::shared_ptr<View3D>> views_3d);
+ Renderer(std::initializer_list<std::shared_ptr<View2D>> views_2d,
+ std::initializer_list<std::shared_ptr<View3D>> views_3d);
~Renderer();
void
diff --git a/src/vk/view.cpp b/src/vk/view_2d.cpp
index b4ef722..623aa63 100644
--- a/src/vk/view.cpp
+++ b/src/vk/view_2d.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "view.hpp"
+#include "view_2d.hpp"
#include <array>
@@ -24,35 +24,9 @@ namespace
{
void
-load_3d_uniform_buffer(void *obj)
-{
- auto self = static_cast<VK::View*>(obj);
-
- try
- {
- self->ub_3d.reserve(cg_core.vk_swapchain->images_count);
- for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
- self->ub_3d.emplace_back(
- cg_core.vk_device_with_swapchain, sizeof(VK::UBOView3D));
- }
- catch(const std::exception& e)
- {
- throw CommandError{e.what()};
- }
-}
-
-void
-unload_3d_uniform_buffer(void *obj)
-{
- auto self = static_cast<VK::View*>(obj);
-
- self->ub_3d.clear();
-}
-
-void
load_2d_uniform_buffer(void *obj)
{
- auto self = static_cast<VK::View*>(obj);
+ auto self = static_cast<VK::View2D*>(obj);
try
{
@@ -70,37 +44,15 @@ load_2d_uniform_buffer(void *obj)
void
unload_2d_uniform_buffer(void *obj)
{
- auto self = static_cast<VK::View*>(obj);
+ auto self = static_cast<VK::View2D*>(obj);
self->ub_2d.clear();
}
void
-load_descriptor_sets_3d(void *obj)
-{
- auto self = static_cast<VK::View*>(obj);
-
- std::vector<VkDescriptorSetLayout> layouts(
- cg_core.vk_swapchain->images_count,
- cg_core.vk_graphics_pipeline_3d_layout->descriptor_set_view);
-
- 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_3d.resize(layouts.size());
- if(vkAllocateDescriptorSets(
- cg_core.vk_device_with_swapchain->device, &alloc_info,
- self->descriptor_sets_3d.data()) != VK_SUCCESS)
- throw CommandError{"Failed to create Vulkan descriptor sets for view."};
-}
-
-void
load_descriptor_sets_2d(void *obj)
{
- auto self = static_cast<VK::View*>(obj);
+ auto self = static_cast<VK::View2D*>(obj);
std::vector<VkDescriptorSetLayout> layouts(
cg_core.vk_swapchain->images_count,
@@ -120,45 +72,9 @@ load_descriptor_sets_2d(void *obj)
}
void
-load_resources_to_descriptor_sets_3d(void *obj)
-{
- auto self = static_cast<VK::View*>(obj);
-
- for(auto i{0}; i < self->ub_3d.size(); i++)
- {
- VkDescriptorBufferInfo view_3d_info{};
- view_3d_info.buffer = self->ub_3d[i].buffer;
- view_3d_info.offset = 0;
- view_3d_info.range = sizeof(VK::UBOView3D);
-
- std::array<VkWriteDescriptorSet, 1> write_descriptors{};
- write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- write_descriptors[0].dstSet = self->descriptor_sets_3d[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 = &view_3d_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::UBOView3D ubo_view_3d;
- ubo_view_3d.proj = glm::ortho(
- 0.0f, self->region.z,
- 0.0f, self->region.w,
- 0.0f, 100.0f);
- self->ub_3d[i].copy_data(&ubo_view_3d);
- }
-}
-
-void
load_resources_to_descriptor_sets_2d(void *obj)
{
- auto self = static_cast<VK::View*>(obj);
+ auto self = static_cast<VK::View2D*>(obj);
for(auto i{0}; i < self->ub_2d.size(); i++)
{
@@ -191,41 +107,35 @@ load_resources_to_descriptor_sets_2d(void *obj)
}
}
-const CommandChain loader{
- {&load_3d_uniform_buffer, &unload_3d_uniform_buffer},
+}
+
+namespace VK
+{
+
+const CommandChain View2D::loader{
{&load_2d_uniform_buffer, &unload_2d_uniform_buffer}
- // By destroying the pool the sets are also destroyed.
};
-const CommandChain descriptor_sets_loader{
- {&load_descriptor_sets_3d, nullptr},
+const CommandChain View2D::descriptor_sets_loader{
{&load_descriptor_sets_2d, nullptr},
- {&load_resources_to_descriptor_sets_3d, nullptr},
{&load_resources_to_descriptor_sets_2d, nullptr}
};
-}
-
-namespace VK
-{
-
-View::View(glm::vec4 region):
+View2D::View2D(glm::vec4 region):
region{region},
descriptor_pool{VK_NULL_HANDLE},
- camera_position{std::make_shared<glm::vec3>(0.0f, 0.0f, 0.0f)},
- camera_rotation{std::make_shared<glm::vec3>(0.0f, 0.0f, 0.0f)},
sprites_to_draw{cg_core.vk_swapchain->images_count}
{
loader.execute(this);
}
-View::~View()
+View2D::~View2D()
{
loader.revert(this);
}
void
-View::load_descriptor_sets(VkDescriptorPool descriptor_pool)
+View2D::load_descriptor_sets(VkDescriptorPool descriptor_pool)
{
if(this->descriptor_pool != VK_NULL_HANDLE) return;
@@ -234,7 +144,7 @@ View::load_descriptor_sets(VkDescriptorPool descriptor_pool)
}
void
-View::unload_descriptor_sets()
+View2D::unload_descriptor_sets()
{
if(this->descriptor_pool == VK_NULL_HANDLE) return;
diff --git a/src/vk/view.hpp b/src/vk/view_2d.hpp
index 5d133a9..f6741cc 100644
--- a/src/vk/view.hpp
+++ b/src/vk/view_2d.hpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef CANDY_GEAR_VK_VIEW_H
-#define CANDY_GEAR_VK_VIEW_H 1
+#ifndef CANDY_GEAR_VK_VIEW_2D_H
+#define CANDY_GEAR_VK_VIEW_2D_H 1
#include <memory>
#include <unordered_map>
@@ -27,35 +27,33 @@
namespace VK
{
-struct View
+struct View2D
{
glm::vec4 region;
// FIXME: if these vectors get resized, they can cause a segmentation fault!
- std::vector<UniformBuffer> ub_3d;
std::vector<UniformBuffer> ub_2d;
VkDescriptorPool descriptor_pool;
- std::vector<VkDescriptorSet> descriptor_sets_3d;
std::vector<VkDescriptorSet> descriptor_sets_2d;
- std::shared_ptr<glm::vec3> camera_position;
- std::shared_ptr<glm::vec3> camera_rotation;
-
std::vector<
std::unordered_map<std::shared_ptr<Sprite>, std::vector<glm::vec4>>>
sprites_to_draw;
- View(glm::vec4 region);
- ~View();
+ View2D(glm::vec4 region);
+ virtual ~View2D();
void
- load_descriptor_sets(VkDescriptorPool descriptor_pool);
+ virtual load_descriptor_sets(VkDescriptorPool descriptor_pool);
void
- unload_descriptor_sets();
+ virtual unload_descriptor_sets();
+
+protected:
+ static const CommandChain loader, descriptor_sets_loader;
};
}
-#endif /* CANDY_GEAR_VK_VIEW_H */
+#endif /* CANDY_GEAR_VK_VIEW_2D_H */
diff --git a/src/vk/view_3d.cpp b/src/vk/view_3d.cpp
new file mode 100644
index 0000000..9d124d9
--- /dev/null
+++ b/src/vk/view_3d.cpp
@@ -0,0 +1,159 @@
+/*
+ * 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 "view_3d.hpp"
+
+#include <array>
+
+#include "../core.hpp"
+
+namespace
+{
+
+void
+load_3d_uniform_buffer(void *obj)
+{
+ auto self = static_cast<VK::View3D*>(obj);
+
+ try
+ {
+ self->ub_3d.reserve(cg_core.vk_swapchain->images_count);
+ for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
+ self->ub_3d.emplace_back(
+ cg_core.vk_device_with_swapchain, sizeof(VK::UBOView3D));
+ }
+ catch(const std::exception& e)
+ {
+ throw CommandError{e.what()};
+ }
+}
+
+void
+unload_3d_uniform_buffer(void *obj)
+{
+ auto self = static_cast<VK::View3D*>(obj);
+
+ self->ub_3d.clear();
+}
+
+void
+load_descriptor_sets_3d(void *obj)
+{
+ auto self = static_cast<VK::View3D*>(obj);
+
+ std::vector<VkDescriptorSetLayout> layouts(
+ cg_core.vk_swapchain->images_count,
+ cg_core.vk_graphics_pipeline_3d_layout->descriptor_set_view);
+
+ 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_3d.resize(layouts.size());
+ if(vkAllocateDescriptorSets(
+ cg_core.vk_device_with_swapchain->device, &alloc_info,
+ self->descriptor_sets_3d.data()) != VK_SUCCESS)
+ throw CommandError{"Failed to create Vulkan descriptor sets for view."};
+}
+
+void
+load_resources_to_descriptor_sets_3d(void *obj)
+{
+ auto self = static_cast<VK::View3D*>(obj);
+
+ for(auto i{0}; i < self->ub_3d.size(); i++)
+ {
+ VkDescriptorBufferInfo view_3d_info{};
+ view_3d_info.buffer = self->ub_3d[i].buffer;
+ view_3d_info.offset = 0;
+ view_3d_info.range = sizeof(VK::UBOView3D);
+
+ std::array<VkWriteDescriptorSet, 1> write_descriptors{};
+ write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ write_descriptors[0].dstSet = self->descriptor_sets_3d[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 = &view_3d_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::UBOView3D ubo_view_3d;
+ ubo_view_3d.proj = glm::ortho(
+ 0.0f, self->region.z,
+ 0.0f, self->region.w,
+ 0.0f, 100.0f);
+ self->ub_3d[i].copy_data(&ubo_view_3d);
+ }
+}
+
+const CommandChain loader{
+ {&load_3d_uniform_buffer, &unload_3d_uniform_buffer}
+};
+
+const CommandChain descriptor_sets_loader{
+ {&load_descriptor_sets_3d, nullptr},
+ {&load_resources_to_descriptor_sets_3d, nullptr}
+};
+
+}
+
+namespace VK
+{
+
+View3D::View3D(glm::vec4 region):
+ View2D{region},
+ camera_position{std::make_shared<glm::vec3>(0.0f, 0.0f, 0.0f)},
+ camera_rotation{std::make_shared<glm::vec3>(0.0f, 0.0f, 0.0f)}
+{
+ ::loader.execute(this);
+}
+
+View3D::~View3D()
+{
+ ::loader.revert(this);
+}
+
+void
+View3D::load_descriptor_sets(VkDescriptorPool descriptor_pool)
+{
+ if(this->descriptor_pool != VK_NULL_HANDLE) return;
+
+ auto parent = dynamic_cast<VK::View2D*>(this);
+ this->descriptor_pool = descriptor_pool;
+ View2D::descriptor_sets_loader.execute(parent);
+ ::descriptor_sets_loader.execute(this);
+}
+
+void
+View3D::unload_descriptor_sets()
+{
+ if(this->descriptor_pool == VK_NULL_HANDLE) return;
+
+ auto parent = dynamic_cast<VK::View2D*>(this);
+ this->descriptor_pool = VK_NULL_HANDLE;
+ ::descriptor_sets_loader.revert(this);
+ View2D::descriptor_sets_loader.revert(parent);
+}
+
+}
diff --git a/src/vk/view_3d.hpp b/src/vk/view_3d.hpp
new file mode 100644
index 0000000..ba08957
--- /dev/null
+++ b/src/vk/view_3d.hpp
@@ -0,0 +1,47 @@
+/*
+ * 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_VIEW_3D_H
+#define CANDY_GEAR_VK_VIEW_3D_H 1
+
+#include "view_2d.hpp"
+
+namespace VK
+{
+
+struct View3D: public View2D
+{
+ // FIXME: if this vector get resized, it can cause a segmentation fault!
+ std::vector<UniformBuffer> ub_3d;
+
+ std::vector<VkDescriptorSet> descriptor_sets_3d;
+
+ std::shared_ptr<glm::vec3> camera_position;
+ std::shared_ptr<glm::vec3> camera_rotation;
+
+ View3D(glm::vec4 region);
+ ~View3D();
+
+ void
+ load_descriptor_sets(VkDescriptorPool descriptor_pool);
+
+ void
+ unload_descriptor_sets();
+};
+
+}
+
+#endif /* CANDY_GEAR_VK_VIEW_3D_H */