From 62367a0bcca75c45eb3e7d1582c4fff18827ddc7 Mon Sep 17 00:00:00 2001
From: Frederico Linhares <fred@linhares.blue>
Date: Fri, 6 Jan 2023 17:30:12 -0300
Subject: refa Use Push constants for sprites and rectangles

---
 glsl/shader_2d.frag.glsl                     |  30 ----
 glsl/shader_2d.vert.glsl                     |  58 -------
 glsl/shader_2d_solid.frag.glsl               |  30 ++++
 glsl/shader_2d_solid.vert.glsl               |  57 +++++++
 glsl/shader_2d_wired.frag.glsl               |  11 +-
 glsl/shader_2d_wired.vert.glsl               |  19 +--
 src/vk/device.cpp                            |  20 ++-
 src/vk/device.hpp                            |   4 +-
 src/vk/graphics_pipeline_2d_solid.cpp        |  67 ++++----
 src/vk/graphics_pipeline_2d_solid_layout.cpp |  24 +--
 src/vk/graphics_pipeline_2d_wired.cpp        | 233 ++++++---------------------
 src/vk/graphics_pipeline_2d_wired.hpp        |   5 -
 src/vk/graphics_pipeline_2d_wired_layout.cpp |  62 ++-----
 src/vk/graphics_pipeline_2d_wired_layout.hpp |   1 -
 src/vk/graphics_pipeline_3d.cpp              |  18 +--
 src/vk/model.cpp                             |   6 +-
 src/vk/sprite.cpp                            |  61 ++-----
 src/vk/sprite.hpp                            |   2 -
 src/vk/uniform_buffer_object.hpp             |  64 --------
 src/vk/uniform_data_object.hpp               |  64 ++++++++
 src/vk/view_2d.cpp                           |   8 +-
 src/vk/view_3d.cpp                           |   8 +-
 22 files changed, 313 insertions(+), 539 deletions(-)
 delete mode 100644 glsl/shader_2d.frag.glsl
 delete mode 100644 glsl/shader_2d.vert.glsl
 create mode 100644 glsl/shader_2d_solid.frag.glsl
 create mode 100644 glsl/shader_2d_solid.vert.glsl
 delete mode 100644 src/vk/uniform_buffer_object.hpp
 create mode 100644 src/vk/uniform_data_object.hpp

diff --git a/glsl/shader_2d.frag.glsl b/glsl/shader_2d.frag.glsl
deleted file mode 100644
index 54ab1be..0000000
--- a/glsl/shader_2d.frag.glsl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.
- */
-
-#version 450
-#extension GL_ARB_separate_shader_objects : enable
-
-layout(location = 0) in vec2 in_texture_coord;
-
-layout(location = 0) out vec4 out_color;
-
-layout(set = 1, binding = 1) uniform sampler2D texture_sampler;
-
-void
-main()
-{
-  out_color = texture(texture_sampler, in_texture_coord);
-}
diff --git a/glsl/shader_2d.vert.glsl b/glsl/shader_2d.vert.glsl
deleted file mode 100644
index 5c5a243..0000000
--- a/glsl/shader_2d.vert.glsl
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.
- */
-
-#version 450
-#extension GL_ARB_separate_shader_objects : enable
-
-layout(location = 0) in vec2 in_texture_coord;
-
-layout(location = 0) out vec2 out_texture_coord;
-
-layout(set = 0, binding = 0) uniform UBOView2D
-{
-  mat4 proj;
-} ubo_view;
-
-layout(set = 1, binding = 0) uniform UBOSpritePositions
-{
-  vec4 positions[128];
-} ubo_sprite_positions;
-
-void
-main()
-{
-  vec2 coordinate;
-  vec4 position = ubo_sprite_positions.positions[gl_InstanceIndex];
-
-  out_texture_coord = in_texture_coord;
-
-  switch(gl_VertexIndex)
-  {
-  case 0:
-    coordinate = vec2(position.x, position.y);
-    break;
-  case 1:
-    coordinate = vec2(position.x, position.w);
-    break;
-  case 2:
-    coordinate = vec2(position.z, position.y);
-    break;
-  case 3:
-    coordinate = vec2(position.z, position.w);
-    break;
-  }
-  gl_Position = ubo_view.proj * vec4(coordinate, 0.0, 1.0);
-}
diff --git a/glsl/shader_2d_solid.frag.glsl b/glsl/shader_2d_solid.frag.glsl
new file mode 100644
index 0000000..7142979
--- /dev/null
+++ b/glsl/shader_2d_solid.frag.glsl
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) in vec2 in_texture_coord;
+
+layout(location = 0) out vec4 out_color;
+
+layout(set = 1, binding = 0) uniform sampler2D texture_sampler;
+
+void
+main()
+{
+  out_color = texture(texture_sampler, in_texture_coord);
+}
diff --git a/glsl/shader_2d_solid.vert.glsl b/glsl/shader_2d_solid.vert.glsl
new file mode 100644
index 0000000..bf0e237
--- /dev/null
+++ b/glsl/shader_2d_solid.vert.glsl
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) in vec2 in_texture_coord;
+
+layout(location = 0) out vec2 out_texture_coord;
+
+layout(set = 0, binding = 0) uniform UBOView2D
+{
+  mat4 proj;
+} ubo_view;
+
+layout(push_constant) uniform PCSprite
+{
+  vec4 position;
+} sprite;
+
+void
+main()
+{
+  vec2 coordinate;
+
+  out_texture_coord = in_texture_coord;
+
+  switch(gl_VertexIndex)
+  {
+  case 0:
+    coordinate = vec2(sprite.position.x, sprite.position.y);
+    break;
+  case 1:
+    coordinate = vec2(sprite.position.x, sprite.position.w);
+    break;
+  case 2:
+    coordinate = vec2(sprite.position.z, sprite.position.y);
+    break;
+  case 3:
+    coordinate = vec2(sprite.position.z, sprite.position.w);
+    break;
+  }
+  gl_Position = ubo_view.proj * vec4(coordinate, 0.0, 1.0);
+}
diff --git a/glsl/shader_2d_wired.frag.glsl b/glsl/shader_2d_wired.frag.glsl
index 569b950..c7aa3f4 100644
--- a/glsl/shader_2d_wired.frag.glsl
+++ b/glsl/shader_2d_wired.frag.glsl
@@ -17,17 +17,16 @@
 #version 450
 #extension GL_ARB_separate_shader_objects : enable
 
-layout(location = 0) in flat int in_instance_index;
-
 layout(location = 0) out vec4 out_color;
 
-layout(set = 1, binding = 1) uniform UBOColors
+layout(push_constant) uniform PCColor
 {
-  vec3 colors[128];
-} ubo_colors;
+  vec4 offset; //offset
+  vec3 color;
+} sprite;
 
 void
 main()
 {
-  out_color = vec4(ubo_colors.colors[in_instance_index], 1.0);
+  out_color = vec4(sprite.color, 1.0);
 }
diff --git a/glsl/shader_2d_wired.vert.glsl b/glsl/shader_2d_wired.vert.glsl
index 28cc55f..0e9258e 100644
--- a/glsl/shader_2d_wired.vert.glsl
+++ b/glsl/shader_2d_wired.vert.glsl
@@ -17,39 +17,34 @@
 #version 450
 #extension GL_ARB_separate_shader_objects : enable
 
-layout(location = 0) out int out_instance_index;
-
 layout(set = 0, binding = 0) uniform UBOView2D
 {
   mat4 proj;
 } ubo_view;
 
-layout(set = 1, binding = 0) uniform UBORectangles
+layout(push_constant) uniform PCRectangle
 {
-  vec4 positions[128];
-} ubo_sprite_positions;
+  vec4 position;
+} sprite;
 
 void
 main()
 {
   vec2 coordinate;
-  vec4 position = ubo_sprite_positions.positions[gl_InstanceIndex];
-
-  out_instance_index = gl_InstanceIndex;
 
   switch(gl_VertexIndex)
   {
   case 0:
-    coordinate = vec2(position.x, position.y);
+    coordinate = vec2(sprite.position.x, sprite.position.y);
     break;
   case 1:
-    coordinate = vec2(position.x, position.w);
+    coordinate = vec2(sprite.position.x, sprite.position.w);
     break;
   case 2:
-    coordinate = vec2(position.z, position.y);
+    coordinate = vec2(sprite.position.z, sprite.position.y);
     break;
   case 3:
-    coordinate = vec2(position.z, position.w);
+    coordinate = vec2(sprite.position.z, sprite.position.w);
     break;
   }
   gl_Position = ubo_view.proj * vec4(coordinate, 0.0, 1.0);
diff --git a/src/vk/device.cpp b/src/vk/device.cpp
index 957ae6d..ea943c4 100644
--- a/src/vk/device.cpp
+++ b/src/vk/device.cpp
@@ -162,10 +162,10 @@ Device::Device(VkPhysicalDevice vk_physical_device, bool with_swapchain)
       this->device, DATA_DIR "/glsl/shader_3d.vert.spv");
     this->frag3d_shader_module = create_shader_module(
       this->device, DATA_DIR "/glsl/shader_3d.frag.spv");
-    this->vert2d_shader_module = create_shader_module(
-      this->device, DATA_DIR "/glsl/shader_2d.vert.spv");
-    this->frag2d_shader_module = create_shader_module(
-      this->device, DATA_DIR "/glsl/shader_2d.frag.spv");
+    this->vert2d_solid_shader_module = create_shader_module(
+      this->device, DATA_DIR "/glsl/shader_2d_solid.vert.spv");
+    this->frag2d_solid_shader_module = create_shader_module(
+      this->device, DATA_DIR "/glsl/shader_2d_solid.frag.spv");
     this->vert2d_wired_shader_module = create_shader_module(
       this->device, DATA_DIR "/glsl/shader_2d_wired.vert.spv");
     this->frag2d_wired_shader_module = create_shader_module(
@@ -205,10 +205,14 @@ Device::~Device()
   // Destroy shaders
   vkDestroyShaderModule(this->device, this->vert3d_shader_module, nullptr);
   vkDestroyShaderModule(this->device, this->frag3d_shader_module, nullptr);
-  vkDestroyShaderModule(this->device, this->vert2d_shader_module, nullptr);
-  vkDestroyShaderModule(this->device, this->frag2d_shader_module, nullptr);
-  vkDestroyShaderModule(this->device, this->vert2d_wired_shader_module, nullptr);
-  vkDestroyShaderModule(this->device, this->frag2d_wired_shader_module, nullptr);
+  vkDestroyShaderModule(
+    this->device, this->vert2d_solid_shader_module, nullptr);
+  vkDestroyShaderModule(
+    this->device, this->frag2d_solid_shader_module, nullptr);
+  vkDestroyShaderModule(
+    this->device, this->vert2d_wired_shader_module, nullptr);
+  vkDestroyShaderModule(
+    this->device, this->frag2d_wired_shader_module, nullptr);
 
   vkDeviceWaitIdle(this->device);
   vkDestroyDevice(this->device, nullptr);
diff --git a/src/vk/device.hpp b/src/vk/device.hpp
index 9f5a776..9fcec20 100644
--- a/src/vk/device.hpp
+++ b/src/vk/device.hpp
@@ -39,8 +39,8 @@ public:
 
   VkShaderModule vert3d_shader_module;
   VkShaderModule frag3d_shader_module;
-  VkShaderModule vert2d_shader_module;
-  VkShaderModule frag2d_shader_module;
+  VkShaderModule vert2d_solid_shader_module;
+  VkShaderModule frag2d_solid_shader_module;
   VkShaderModule vert2d_wired_shader_module;
   VkShaderModule frag2d_wired_shader_module;
 
diff --git a/src/vk/graphics_pipeline_2d_solid.cpp b/src/vk/graphics_pipeline_2d_solid.cpp
index b7caaa7..5d210be 100644
--- a/src/vk/graphics_pipeline_2d_solid.cpp
+++ b/src/vk/graphics_pipeline_2d_solid.cpp
@@ -20,7 +20,7 @@
 
 #include "../core.hpp"
 #include "sprite.hpp"
-#include "uniform_buffer_object.hpp"
+#include "uniform_data_object.hpp"
 
 namespace
 {
@@ -77,7 +77,7 @@ load_pipeline(void *obj)
   vert_shader_stage_info.flags = 0;
   vert_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT;
   vert_shader_stage_info.module =
-    cg_core.vk_device_with_swapchain->vert2d_shader_module;
+    cg_core.vk_device_with_swapchain->vert2d_solid_shader_module;
   vert_shader_stage_info.pName = "main";
   vert_shader_stage_info.pSpecializationInfo = nullptr;
 
@@ -88,7 +88,7 @@ load_pipeline(void *obj)
   frag_shader_stage_info.flags = 0;
   frag_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
   frag_shader_stage_info.module =
-    cg_core.vk_device_with_swapchain->frag2d_shader_module;
+    cg_core.vk_device_with_swapchain->frag2d_solid_shader_module;
   frag_shader_stage_info.pName = "main";
   frag_shader_stage_info.pSpecializationInfo = nullptr;
 
@@ -177,9 +177,10 @@ load_pipeline(void *obj)
   multisampling.alphaToOneEnable = VK_FALSE;
 
   VkPipelineColorBlendAttachmentState color_blend_attachment = {};
-  color_blend_attachment.blendEnable = VK_FALSE;
-  color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
-  color_blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
+  color_blend_attachment.blendEnable = VK_TRUE;
+  color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
+  color_blend_attachment.dstColorBlendFactor =
+    VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
   color_blend_attachment.colorBlendOp = VK_BLEND_OP_ADD;
   color_blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
   color_blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
@@ -202,16 +203,17 @@ load_pipeline(void *obj)
   color_blending.blendConstants[2] = 0.0f;
   color_blending.blendConstants[3] = 0.0f;
 
-  VkDynamicState dynamic_states[] = {
+  std::array<VkDynamicState, 3> dynamic_states{
     VK_DYNAMIC_STATE_VIEWPORT,
-    VK_DYNAMIC_STATE_LINE_WIDTH
+    VK_DYNAMIC_STATE_LINE_WIDTH,
+    VK_DYNAMIC_STATE_BLEND_CONSTANTS
   };
 
   VkPipelineDynamicStateCreateInfo dynamic_state_info = {};
   dynamic_state_info.sType =
       VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
-  dynamic_state_info.dynamicStateCount = 2;
-  dynamic_state_info.pDynamicStates = dynamic_states;
+  dynamic_state_info.dynamicStateCount = dynamic_states.size();
+  dynamic_state_info.pDynamicStates = dynamic_states.data();
 
   VkGraphicsPipelineCreateInfo pipeline_info{};
   pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
@@ -300,31 +302,30 @@ GraphicsPipeline2DSolid::draw(
   // Draw sprites
   for(auto& [sprite, positions]: view->sprites_to_draw[current_frame])
   {
-    // Commands
-    {
-      std::array<VkDescriptorSet, 2> vk_descriptor_sets{
-        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_solid_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);
-      vkCmdBindVertexBuffers(
-        draw_command_buffer, 0, 1, &sprite->vertex_buffer->buffer, offsets);
-      vkCmdDraw(
-        draw_command_buffer, Sprite::vertex_count, positions.size(), 0, 0);
-    }
+    std::array<VkDescriptorSet, 2> vk_descriptor_sets{
+      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_solid_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);
+    vkCmdBindVertexBuffers(
+      draw_command_buffer, 0, 1, &sprite->vertex_buffer->buffer, offsets);
 
-    UBOVectors4D ubo_sprite_positions;
     for(auto i{0}; i < positions.size(); i++)
-      ubo_sprite_positions.vectors[i] = positions[i];
-    sprite->ub_sprite_positions[image_index].copy_data(
-      &ubo_sprite_positions);
+    {
+      ODOVector4D position{positions[i]};
+      vkCmdPushConstants(
+        draw_command_buffer,
+        cg_core.vk_graphics_pipeline_2d_solid_layout->pipeline,
+        VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(ODOVector4D), &position);
+      vkCmdDraw(draw_command_buffer, Sprite::vertex_count, 1, 0, 0);
+    }
   }
 
   // Prepare for the next frame.
diff --git a/src/vk/graphics_pipeline_2d_solid_layout.cpp b/src/vk/graphics_pipeline_2d_solid_layout.cpp
index 6f0da0e..0ed41d0 100644
--- a/src/vk/graphics_pipeline_2d_solid_layout.cpp
+++ b/src/vk/graphics_pipeline_2d_solid_layout.cpp
@@ -19,6 +19,7 @@
 #include <array>
 
 #include "../core.hpp"
+#include "uniform_data_object.hpp"
 
 namespace
 {
@@ -65,21 +66,15 @@ load_descriptor_set_sprite(void *obj)
 {
   auto self = static_cast<VK::GraphicsPipeline2DSolidLayout*>(obj);
 
-  std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings{};
+  std::array<VkDescriptorSetLayoutBinding, 1> layout_bindings{};
 
   layout_bindings[0].binding = 0;
-  layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+  layout_bindings[0].descriptorType =
+    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
   layout_bindings[0].descriptorCount = 1;
-  layout_bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+  layout_bindings[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_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;
@@ -113,12 +108,17 @@ load_pipeline(void *obj)
     self->descriptor_set_view, self->descriptor_set_sprite
   };
 
+  std::array<VkPushConstantRange, 1> push_constants;
+  push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+  push_constants[0].offset = 0;
+  push_constants[0].size = sizeof(VK::ODOVector4D);
+
   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;
+  pipeline_layout_info.pushConstantRangeCount = push_constants.size();
+  pipeline_layout_info.pPushConstantRanges = push_constants.data();
 
   if(vkCreatePipelineLayout(
        cg_core.vk_device_with_swapchain->device, &pipeline_layout_info,
diff --git a/src/vk/graphics_pipeline_2d_wired.cpp b/src/vk/graphics_pipeline_2d_wired.cpp
index 34b6a1b..3247b78 100644
--- a/src/vk/graphics_pipeline_2d_wired.cpp
+++ b/src/vk/graphics_pipeline_2d_wired.cpp
@@ -21,11 +21,37 @@
 #include "../core.hpp"
 #include "rectangle.hpp"
 #include "sprite.hpp"
-#include "uniform_buffer_object.hpp"
+#include "uniform_data_object.hpp"
 
 namespace
 {
 
+void
+load_indexes(void *obj)
+{
+  auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj);
+
+  self->queue_family =
+    cg_core.vk_device_with_swapchain->get_queue_family_with_graphics();
+
+  std::array<uint32_t, 4> indexes{0, 1, 2, 3};
+  void *indexes_data{indexes.data()};
+  size_t indexes_size{sizeof(indexes[0]) * indexes.size()};
+  VK::SourceBuffer source_index_buffer{
+    self->queue_family->device, indexes_data, indexes_size};
+  self->index_buffer = new VK::DestinationBuffer{
+    self->queue_family, &source_index_buffer,
+    VK_BUFFER_USAGE_INDEX_BUFFER_BIT};
+}
+
+void
+unload_indexes(void *obj)
+{
+  auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj);
+
+  delete self->index_buffer;
+}
+
 void
 load_framebuffer(void *obj)
 {
@@ -239,182 +265,10 @@ unload_pipeline(void *obj)
     cg_core.vk_device_with_swapchain->device, self->graphic_pipeline, nullptr);
 }
 
-void
-load_indexes(void *obj)
-{
-  auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj);
-
-  self->queue_family =
-    cg_core.vk_device_with_swapchain->get_queue_family_with_graphics();
-
-  std::array<uint32_t, 4> indexes{0, 1, 2, 3};
-  void *indexes_data{indexes.data()};
-  size_t indexes_size{sizeof(indexes[0]) * indexes.size()};
-  VK::SourceBuffer source_index_buffer{
-    self->queue_family->device, indexes_data, indexes_size};
-  self->index_buffer = new VK::DestinationBuffer{
-    self->queue_family, &source_index_buffer,
-    VK_BUFFER_USAGE_INDEX_BUFFER_BIT};
-}
-
-void
-unload_indexes(void *obj)
-{
-  auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj);
-
-  delete self->index_buffer;
-}
-
-void
-load_uniform_rectangles_buffers(void *obj)
-{
-  auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj);
-
-  self->ub_rectangles.reserve(
-    cg_core.vk_swapchain->images_count);
-  for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
-    self->ub_rectangles.emplace_back(
-      cg_core.vk_device_with_swapchain, sizeof(VK::UBOVectors4D));
-}
-
-void
-unload_uniform_rectangles_buffers(void *obj)
-{
-  auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj);
-
-  self->ub_rectangles.clear();
-}
-
-void
-load_uniform_rectangle_colors_buffers(void *obj)
-{
-  auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj);
-
-  self->ub_rectangle_colors.reserve(
-    cg_core.vk_swapchain->images_count);
-  for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
-    self->ub_rectangle_colors.emplace_back(
-      cg_core.vk_device_with_swapchain, sizeof(VK::UBOVectors3D));
-}
-
-void
-unload_uniform_rectangle_colors_buffers(void *obj)
-{
-  auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj);
-
-  self->ub_rectangle_colors.clear();
-}
-
-void
-load_descriptor_set_pool(void *obj)
-{
-  auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj);
-
-  std::array<VkDescriptorPoolSize, 1> descriptor_pool_sizes{};
-  descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
-  descriptor_pool_sizes[0].descriptorCount =
-    self->ub_rectangles.size() + self->ub_rectangle_colors.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_rectangles.size() + self->ub_rectangle_colors.size();
-  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<VK::GraphicsPipeline2DWired*>(obj);
-
-  vkDestroyDescriptorPool(
-    self->queue_family->device->device, self->descriptor_pool, nullptr);
-}
-
-void
-load_descriptor_sets(void *obj)
-{
-  auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj);
-
-  std::vector<VkDescriptorSetLayout> layouts(
-    cg_core.vk_swapchain->images_count,
-    cg_core.vk_graphics_pipeline_2d_wired_layout->descriptor_set_instance);
-
-  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<VK::GraphicsPipeline2DWired*>(obj);
-
-  for(auto i{0}; i < self->ub_rectangles.size(); i++)
-  {
-    VkDescriptorBufferInfo rectangles_buffer_info{};
-    rectangles_buffer_info.buffer = self->ub_rectangles[i].buffer;
-    rectangles_buffer_info.offset = 0;
-    rectangles_buffer_info.range = sizeof(VK::UBOVectors4D);
-
-    VkDescriptorBufferInfo colors_buffer_info{};
-    colors_buffer_info.buffer = self->ub_rectangle_colors[i].buffer;
-    colors_buffer_info.offset = 0;
-    colors_buffer_info.range = sizeof(VK::UBOVectors3D);
-
-    std::array<VkWriteDescriptorSet, 2> 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_UNIFORM_BUFFER;
-    write_descriptors[0].pBufferInfo = &rectangles_buffer_info;
-    write_descriptors[0].pImageInfo = nullptr;
-    write_descriptors[0].pTexelBufferView = nullptr;
-
-    write_descriptors[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-    write_descriptors[1].dstSet = self->descriptor_sets[i];
-    write_descriptors[1].dstBinding = 1;
-    write_descriptors[1].dstArrayElement = 0;
-    write_descriptors[1].descriptorCount = 1;
-    write_descriptors[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
-    write_descriptors[1].pBufferInfo = &colors_buffer_info;
-    write_descriptors[1].pImageInfo = nullptr;
-    write_descriptors[1].pTexelBufferView = nullptr;
-
-    vkUpdateDescriptorSets(
-      cg_core.vk_device_with_swapchain->device, write_descriptors.size(),
-      write_descriptors.data(), 0, nullptr);
-  }
-}
-
 const CommandChain loader{
   {&load_indexes, &unload_indexes},
   {&load_framebuffer, &unload_framebuffer},
-  {&load_pipeline, &unload_pipeline},
-  {&load_uniform_rectangles_buffers, &unload_uniform_rectangles_buffers},
-  {&load_uniform_rectangle_colors_buffers,
-   &unload_uniform_rectangle_colors_buffers},
-  {&load_descriptor_set_pool, &unload_descriptor_set_pool},
-  {&load_descriptor_sets, nullptr},
-  {&load_data_to_descriptor_sets, nullptr}
+  {&load_pipeline, &unload_pipeline}
 };
 
 }
@@ -459,9 +313,8 @@ GraphicsPipeline2DWired::draw(
 
   // Draw rectangles
   {
-    std::array<VkDescriptorSet, 2> vk_descriptor_sets{
-      view->descriptor_sets_2d[image_index],
-      this->descriptor_sets[image_index]};
+    std::array<VkDescriptorSet, 1> vk_descriptor_sets{
+      view->descriptor_sets_2d[image_index]};
     VkDeviceSize offsets[]{0};
 
     vkCmdBindDescriptorSets(
@@ -474,21 +327,25 @@ GraphicsPipeline2DWired::draw(
     vkCmdBindIndexBuffer(
       draw_command_buffer, this->index_buffer->buffer, 0,
       VK_INDEX_TYPE_UINT32);
-    vkCmdDrawIndexed(
-      draw_command_buffer, Rectangle::VertexCount,
-      view->rectangles_to_draw[current_frame].size(),
-      0, 0, 0);
 
-    UBOVectors4D ubo_rectangle_positions;
-    UBOVectors3D ubo_rectangle_colors;
     for(auto i{0}; i < view->rectangles_to_draw[current_frame].size(); i++)
     {
-      auto &rect = view->rectangles_to_draw[current_frame][i];
-      ubo_rectangle_positions.vectors[i] = rect.position;
-      ubo_rectangle_colors.vectors[i] = rect.color;
+      auto &rect{view->rectangles_to_draw[current_frame][i]};
+
+      ODOVector4D position{rect.position};
+      ODOVector3D color{rect.color};
+      vkCmdPushConstants(
+        draw_command_buffer,
+        cg_core.vk_graphics_pipeline_2d_wired_layout->pipeline,
+        VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(ODOVector4D), &position);
+      vkCmdPushConstants(
+        draw_command_buffer,
+        cg_core.vk_graphics_pipeline_2d_wired_layout->pipeline,
+        VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(ODOVector4D), sizeof(ODOVector3D),
+        &color);
+      vkCmdDrawIndexed(
+        draw_command_buffer, Rectangle::VertexCount, 1, 0, 0, 0);
     }
-    this->ub_rectangles[image_index].copy_data(&ubo_rectangle_positions);
-    this->ub_rectangle_colors[image_index].copy_data(&ubo_rectangle_colors);
   }
 
   // Prepare for the next frame.
diff --git a/src/vk/graphics_pipeline_2d_wired.hpp b/src/vk/graphics_pipeline_2d_wired.hpp
index aa975a8..8c7765d 100644
--- a/src/vk/graphics_pipeline_2d_wired.hpp
+++ b/src/vk/graphics_pipeline_2d_wired.hpp
@@ -35,11 +35,6 @@ struct GraphicsPipeline2DWired
   VkPipeline graphic_pipeline;
 
   DestinationBuffer *index_buffer;
-  std::vector<UniformBuffer> ub_rectangles;
-  std::vector<UniformBuffer> ub_rectangle_colors;
-
-  VkDescriptorPool descriptor_pool;
-  std::vector<VkDescriptorSet> descriptor_sets;
 
   GraphicsPipeline2DWired();
   ~GraphicsPipeline2DWired();
diff --git a/src/vk/graphics_pipeline_2d_wired_layout.cpp b/src/vk/graphics_pipeline_2d_wired_layout.cpp
index ae58a2f..8e06641 100644
--- a/src/vk/graphics_pipeline_2d_wired_layout.cpp
+++ b/src/vk/graphics_pipeline_2d_wired_layout.cpp
@@ -20,6 +20,7 @@
 
 #include "../core.hpp"
 #include "graphics_pipeline_2d_solid_layout.hpp"
+#include "uniform_data_object.hpp"
 
 namespace
 {
@@ -61,64 +62,30 @@ unload_descriptor_set_view(void *obj)
     nullptr);
 }
 
-void
-load_descriptor_set_instance(void *obj)
-{
-  auto self = static_cast<VK::GraphicsPipeline2DWiredLayout*>(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_UNIFORM_BUFFER;
-  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_instance) != VK_SUCCESS)
-    throw CommandError{
-      "Failed to create Vulkan descriptor set layout for rectangles."};
-}
-
-void
-unload_descriptor_set_instance(void *obj)
-{
-  auto self = static_cast<VK::GraphicsPipeline2DWiredLayout*>(obj);
-
-  vkDestroyDescriptorSetLayout(
-    cg_core.vk_device_with_swapchain->device, self->descriptor_set_instance,
-    nullptr);
-}
-
 void
 load_pipeline(void *obj)
 {
   auto self = static_cast<VK::GraphicsPipeline2DWiredLayout*>(obj);
 
-  std::array<VkDescriptorSetLayout, 2> set_layouts{
-    self->descriptor_set_view, self->descriptor_set_instance
+  std::array<VkDescriptorSetLayout, 1> set_layouts{
+    self->descriptor_set_view
   };
 
+  std::array<VkPushConstantRange, 2> push_constants;
+  push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+  push_constants[0].offset = 0;
+  push_constants[0].size = sizeof(VK::ODOVector4D);
+
+  push_constants[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+  push_constants[1].offset = sizeof(VK::ODOVector4D);
+  push_constants[1].size = sizeof(VK::ODOVector3D);
+
   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;
+  pipeline_layout_info.pushConstantRangeCount = push_constants.size();
+  pipeline_layout_info.pPushConstantRanges = push_constants.data();
 
   if(vkCreatePipelineLayout(
        cg_core.vk_device_with_swapchain->device, &pipeline_layout_info,
@@ -208,7 +175,6 @@ unload_render_pass(void *obj)
 
 const CommandChain loader{
   {&load_descriptor_set_view, &unload_descriptor_set_view},
-  {&load_descriptor_set_instance, &unload_descriptor_set_instance},
   {&load_pipeline, &unload_pipeline},
   {&load_render_pass, &unload_render_pass}
 };
diff --git a/src/vk/graphics_pipeline_2d_wired_layout.hpp b/src/vk/graphics_pipeline_2d_wired_layout.hpp
index 3d0268e..339aebe 100644
--- a/src/vk/graphics_pipeline_2d_wired_layout.hpp
+++ b/src/vk/graphics_pipeline_2d_wired_layout.hpp
@@ -30,7 +30,6 @@ struct UBOModel2D
 struct GraphicsPipeline2DWiredLayout
 {
   VkDescriptorSetLayout descriptor_set_view;
-  VkDescriptorSetLayout descriptor_set_instance;
   VkPipelineLayout pipeline;
   VkRenderPass render_pass;
 
diff --git a/src/vk/graphics_pipeline_3d.cpp b/src/vk/graphics_pipeline_3d.cpp
index 790cad7..f915c00 100644
--- a/src/vk/graphics_pipeline_3d.cpp
+++ b/src/vk/graphics_pipeline_3d.cpp
@@ -23,7 +23,7 @@
 #include "core.hpp"
 #include "image.hpp"
 #include "vertex_3d.hpp"
-#include "uniform_buffer_object.hpp"
+#include "uniform_data_object.hpp"
 
 namespace
 {
@@ -38,7 +38,7 @@ load_world_vert_uniform_buffer(void *obj)
     self->ub_world_vert.reserve(cg_core.vk_swapchain->images_count);
     for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
       self->ub_world_vert.emplace_back(
-	cg_core.vk_device_with_swapchain, sizeof(VK::UBOWorld3D_Vert));
+	cg_core.vk_device_with_swapchain, sizeof(VK::ODOWorld3D_Vert));
   }
   catch(const std::exception& e)
   {
@@ -64,7 +64,7 @@ load_world_frag_uniform_buffer(void *obj)
     self->ub_world_frag.reserve(cg_core.vk_swapchain->images_count);
     for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
       self->ub_world_frag.emplace_back(
-	cg_core.vk_device_with_swapchain, sizeof(VK::UBOWorld3D_Frag));
+	cg_core.vk_device_with_swapchain, sizeof(VK::ODOWorld3D_Frag));
   }
   catch(const std::exception& e)
   {
@@ -148,12 +148,12 @@ load_resources_to_descriptor_sets(void *obj)
     VkDescriptorBufferInfo world_vert_info{};
     world_vert_info.buffer = self->ub_world_vert[i].buffer;
     world_vert_info.offset = 0;
-    world_vert_info.range = sizeof(VK::UBOWorld3D_Vert);
+    world_vert_info.range = sizeof(VK::ODOWorld3D_Vert);
 
     VkDescriptorBufferInfo world_frag_info{};
     world_frag_info.buffer = self->ub_world_frag[i].buffer;
     world_frag_info.offset = 0;
-    world_frag_info.range = sizeof(VK::UBOWorld3D_Frag);
+    world_frag_info.range = sizeof(VK::ODOWorld3D_Frag);
 
     std::array<VkWriteDescriptorSet, 2> write_descriptors{};
     write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
@@ -587,7 +587,7 @@ GraphicsPipeline3D::draw(
         0, 0, 0);
     }
 
-    VK::UBOModelInstance ubo_model_instance;
+    VK::ODOModelInstance ubo_model_instance;
 
     for(int i{0}; i < instances.size(); i++)
     {
@@ -610,7 +610,7 @@ GraphicsPipeline3D::draw(
 
   // Update view uniform buffers
   {
-    VK::UBOView3D ubo_view_3d{};
+    VK::ODOView3D ubo_view_3d{};
 
     // View matrix.
     ubo_view_3d.view = glm::mat4{1.0f};
@@ -635,11 +635,11 @@ GraphicsPipeline3D::draw(
 
   // Update world uniform buffer
   {
-    UBOWorld3D_Vert ubo_world_3d_vert{};
+    ODOWorld3D_Vert ubo_world_3d_vert{};
     ubo_world_3d_vert.ambient_light_color = glm::vec4{0.25, 0.25, 0.25, 1.0};
     this->ub_world_vert[image_index].copy_data(&ubo_world_3d_vert);
 
-    UBOWorld3D_Frag ubo_world_3d_frag{};
+    ODOWorld3D_Frag ubo_world_3d_frag{};
     ubo_world_3d_frag.directional_light_direction =
       glm::vec3{-0.57735, 0.57735, -0.57735};
     ubo_world_3d_frag.directional_light_color = glm::vec4{0.8, 0.8, 0.8, 1.0};
diff --git a/src/vk/model.cpp b/src/vk/model.cpp
index 2aca963..9f3b373 100644
--- a/src/vk/model.cpp
+++ b/src/vk/model.cpp
@@ -19,7 +19,7 @@
 #include <array>
 
 #include "../core.hpp"
-#include "uniform_buffer_object.hpp"
+#include "uniform_data_object.hpp"
 
 namespace
 {
@@ -32,7 +32,7 @@ load_uniform_buffers(void *obj)
   self->ub_model_instance.reserve(cg_core.vk_swapchain->images_count);
   for(int i{0}; i < cg_core.vk_swapchain->images_count; i++)
     self->ub_model_instance.emplace_back(
-      cg_core.vk_device_with_swapchain, sizeof(VK::UBOModelInstance));
+      cg_core.vk_device_with_swapchain, sizeof(VK::ODOModelInstance));
 }
 
 void
@@ -111,7 +111,7 @@ load_buffers_to_descriptor_sets(void *obj)
     VkDescriptorBufferInfo buffer_info{};
     buffer_info.buffer = self->ub_model_instance[i].buffer;
     buffer_info.offset = 0;
-    buffer_info.range = sizeof(VK::UBOModelInstance);
+    buffer_info.range = sizeof(VK::ODOModelInstance);
 
     VkDescriptorImageInfo image_info{};
     image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
diff --git a/src/vk/sprite.cpp b/src/vk/sprite.cpp
index c2761f3..bc9cb57 100644
--- a/src/vk/sprite.cpp
+++ b/src/vk/sprite.cpp
@@ -20,7 +20,7 @@
 
 #include "../core.hpp"
 #include "sprite.hpp"
-#include "uniform_buffer_object.hpp"
+#include "uniform_data_object.hpp"
 
 namespace
 {
@@ -73,44 +73,21 @@ unload_mesh(void *obj)
   delete self->sprite->source_buffer;
 }
 
-void
-load_uniform_buffers(void *obj)
-{
-  auto self = static_cast<SpriteBuilder*>(obj);
-
-  self->sprite->ub_sprite_positions.reserve(
-    cg_core.vk_swapchain->images_count);
-  for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
-    self->sprite->ub_sprite_positions.emplace_back(
-      cg_core.vk_device_with_swapchain, sizeof(VK::UBOVectors4D));
-}
-
-void
-unload_uniform_buffers(void *obj)
-{
-  auto self = static_cast<SpriteBuilder*>(obj);
-
-  self->sprite->ub_sprite_positions.clear();
-}
-
 void
 load_descriptor_set_pool(void *obj)
 {
   auto self = static_cast<SpriteBuilder*>(obj);
 
-  std::array<VkDescriptorPoolSize, 2> descriptor_pool_sizes{};
-  descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+  std::array<VkDescriptorPoolSize, 1> descriptor_pool_sizes{};
+  descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
   descriptor_pool_sizes[0].descriptorCount =
-    self->sprite->ub_sprite_positions.size();
-  descriptor_pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-  descriptor_pool_sizes[1].descriptorCount =
-    self->sprite->ub_sprite_positions.size();
+    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 = self->sprite->ub_sprite_positions.size();
+  pool_info.maxSets = cg_core.vk_swapchain->images_count;
   pool_info.poolSizeCount = descriptor_pool_sizes.size();
   pool_info.pPoolSizes = descriptor_pool_sizes.data();
 
@@ -158,39 +135,24 @@ load_buffers_to_descriptor_sets(void *obj)
 {
   auto self = static_cast<SpriteBuilder*>(obj);
 
-  for(auto i{0}; i < self->sprite->ub_sprite_positions.size(); i++)
+  for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
   {
-    VkDescriptorBufferInfo buffer_info{};
-    buffer_info.buffer = self->sprite->ub_sprite_positions[i].buffer;
-    buffer_info.offset = 0;
-    buffer_info.range = sizeof(VK::UBOVectors4D);
-
     VkDescriptorImageInfo image_info{};
     image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
     image_info.imageView = self->sprite->texture->view;
     image_info.sampler = self->sprite->texture->sampler;
 
-    std::array<VkWriteDescriptorSet, 2> write_descriptors{};
+    std::array<VkWriteDescriptorSet, 1> write_descriptors{};
     write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
     write_descriptors[0].dstSet = self->sprite->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 = &buffer_info;
-    write_descriptors[0].pImageInfo = nullptr;
-    write_descriptors[0].pTexelBufferView = nullptr;
-
-    write_descriptors[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-    write_descriptors[1].dstSet = self->sprite->descriptor_sets[i];
-    write_descriptors[1].dstBinding = 1;
-    write_descriptors[1].dstArrayElement = 0;
-    write_descriptors[1].descriptorCount = 1;
-    write_descriptors[1].descriptorType =
+    write_descriptors[0].descriptorType =
       VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-    write_descriptors[1].pBufferInfo = nullptr;
-    write_descriptors[1].pImageInfo = &image_info;
-    write_descriptors[1].pTexelBufferView = nullptr;
+    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(),
@@ -200,7 +162,6 @@ load_buffers_to_descriptor_sets(void *obj)
 
 static const CommandChain loader{
   {&load_mesh, &unload_mesh},
-  {&load_uniform_buffers, &unload_uniform_buffers},
   {&load_descriptor_set_pool, &unload_descriptor_set_pool},
   {&load_descriptor_sets, nullptr},
   {&load_buffers_to_descriptor_sets, nullptr},
diff --git a/src/vk/sprite.hpp b/src/vk/sprite.hpp
index b0c0183..e053bba 100644
--- a/src/vk/sprite.hpp
+++ b/src/vk/sprite.hpp
@@ -39,8 +39,6 @@ struct Sprite
   SourceBuffer *source_buffer;
   DestinationBuffer *vertex_buffer;
 
-  std::vector<UniformBuffer> ub_sprite_positions;
-
   VkDescriptorPool descriptor_pool;
   std::vector<VkDescriptorSet> descriptor_sets;
 
diff --git a/src/vk/uniform_buffer_object.hpp b/src/vk/uniform_buffer_object.hpp
deleted file mode 100644
index fa598ab..0000000
--- a/src/vk/uniform_buffer_object.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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_UNIFORM_BUFFER_OBJECT_H
-#define CANDY_GEAR_VK_UNIFORM_BUFFER_OBJECT_H 1
-
-#include "core.hpp"
-
-namespace VK
-{
-
-struct UBOView2D
-{
-  glm::mat4 proj;
-};
-
-struct UBOView3D
-{
-  glm::mat4 view;
-  glm::mat4 proj;
-};
-
-struct UBOWorld3D_Vert
-{
-  glm::vec4 ambient_light_color;
-};
-
-struct UBOWorld3D_Frag
-{
-  glm::vec3 directional_light_direction;
-  glm::vec4 directional_light_color;
-};
-
-struct UBOModelInstance
-{
-  glm::mat4 instances[128];
-};
-
-struct UBOVectors4D
-{
-  glm::vec4 vectors[128];
-};
-
-struct UBOVectors3D
-{
-  glm::vec3 vectors[128];
-};
-
-}
-
-#endif /* CANDY_GEAR_VK_UNIFORM_BUFFER_OBJECT_H */
diff --git a/src/vk/uniform_data_object.hpp b/src/vk/uniform_data_object.hpp
new file mode 100644
index 0000000..d040e4e
--- /dev/null
+++ b/src/vk/uniform_data_object.hpp
@@ -0,0 +1,64 @@
+/*
+ * 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_UNIFORM_DATA_OBJECT_H
+#define CANDY_GEAR_VK_UNIFORM_DATA_OBJECT_H 1
+
+#include "core.hpp"
+
+namespace VK
+{
+
+struct ODOView2D
+{
+  glm::mat4 proj;
+};
+
+struct ODOView3D
+{
+  glm::mat4 view;
+  glm::mat4 proj;
+};
+
+struct ODOWorld3D_Vert
+{
+  glm::vec4 ambient_light_color;
+};
+
+struct ODOWorld3D_Frag
+{
+  glm::vec3 directional_light_direction;
+  glm::vec4 directional_light_color;
+};
+
+struct ODOModelInstance
+{
+  glm::mat4 instances[128];
+};
+
+struct ODOVector4D
+{
+  glm::vec4 vector;
+};
+
+struct ODOVector3D
+{
+  glm::vec3 vectors;
+};
+
+}
+
+#endif /* CANDY_GEAR_VK_UNIFORM_DATA_OBJECT_H */
diff --git a/src/vk/view_2d.cpp b/src/vk/view_2d.cpp
index b6f208c..eb19d9c 100644
--- a/src/vk/view_2d.cpp
+++ b/src/vk/view_2d.cpp
@@ -19,7 +19,7 @@
 #include <array>
 
 #include "../core.hpp"
-#include "uniform_buffer_object.hpp"
+#include "uniform_data_object.hpp"
 
 namespace
 {
@@ -34,7 +34,7 @@ load_2d_uniform_buffer(void *obj)
     self->ub_2d.reserve(cg_core.vk_swapchain->images_count);
     for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
       self->ub_2d.emplace_back(
-	cg_core.vk_device_with_swapchain, sizeof(VK::UBOView2D));
+	cg_core.vk_device_with_swapchain, sizeof(VK::ODOView2D));
   }
   catch(const std::exception& e)
   {
@@ -82,7 +82,7 @@ load_resources_to_descriptor_sets_2d(void *obj)
     VkDescriptorBufferInfo view_2d_info{};
     view_2d_info.buffer = self->ub_2d[i].buffer;
     view_2d_info.offset = 0;
-    view_2d_info.range = sizeof(VK::UBOView2D);
+    view_2d_info.range = sizeof(VK::ODOView2D);
 
     std::array<VkWriteDescriptorSet, 1> write_descriptors{};
     write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
@@ -99,7 +99,7 @@ load_resources_to_descriptor_sets_2d(void *obj)
       cg_core.vk_device_with_swapchain->device, write_descriptors.size(),
       write_descriptors.data(), 0, nullptr);
 
-    VK::UBOView2D ubo_view_2d;
+    VK::ODOView2D ubo_view_2d;
     ubo_view_2d.proj = glm::ortho(
       0.0f, self->projection_width,
       0.0f, self->projection_height,
diff --git a/src/vk/view_3d.cpp b/src/vk/view_3d.cpp
index d9e9844..66e1d34 100644
--- a/src/vk/view_3d.cpp
+++ b/src/vk/view_3d.cpp
@@ -19,7 +19,7 @@
 #include <array>
 
 #include "../core.hpp"
-#include "uniform_buffer_object.hpp"
+#include "uniform_data_object.hpp"
 
 namespace
 {
@@ -34,7 +34,7 @@ load_3d_uniform_buffer(void *obj)
     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));
+	cg_core.vk_device_with_swapchain, sizeof(VK::ODOView3D));
   }
   catch(const std::exception& e)
   {
@@ -82,7 +82,7 @@ load_resources_to_descriptor_sets_3d(void *obj)
     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);
+    view_3d_info.range = sizeof(VK::ODOView3D);
 
     std::array<VkWriteDescriptorSet, 1> write_descriptors{};
     write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
@@ -99,7 +99,7 @@ load_resources_to_descriptor_sets_3d(void *obj)
       cg_core.vk_device_with_swapchain->device, write_descriptors.size(),
       write_descriptors.data(), 0, nullptr);
 
-    VK::UBOView3D ubo_view_3d;
+    VK::ODOView3D ubo_view_3d;
     ubo_view_3d.proj = glm::ortho(
       0.0f, self->region.z,
       0.0f, self->region.w,
-- 
cgit v1.2.3