diff options
-rw-r--r-- | glsl/shader_2d.frag.glsl | 2 | ||||
-rw-r--r-- | glsl/shader_2d.vert.glsl | 9 | ||||
-rw-r--r-- | src/vk/graphics_pipeline_2d.cpp | 187 | ||||
-rw-r--r-- | src/vk/graphics_pipeline_2d.hpp | 9 | ||||
-rw-r--r-- | src/vk/sprite.cpp | 2 | ||||
-rw-r--r-- | src/vk/uniform_buffer.hpp | 5 | ||||
-rw-r--r-- | test/src/main.rb | 2 |
7 files changed, 198 insertions, 18 deletions
diff --git a/glsl/shader_2d.frag.glsl b/glsl/shader_2d.frag.glsl index 1edbbbb..54ab1be 100644 --- a/glsl/shader_2d.frag.glsl +++ b/glsl/shader_2d.frag.glsl @@ -21,7 +21,7 @@ layout(location = 0) in vec2 in_texture_coord; layout(location = 0) out vec4 out_color; -layout(set = 0, binding = 1) uniform sampler2D texture_sampler; +layout(set = 1, binding = 1) uniform sampler2D texture_sampler; void main() diff --git a/glsl/shader_2d.vert.glsl b/glsl/shader_2d.vert.glsl index 6e8ac59..b053fec 100644 --- a/glsl/shader_2d.vert.glsl +++ b/glsl/shader_2d.vert.glsl @@ -21,7 +21,12 @@ layout(location = 0) in vec2 in_texture_coord; layout(location = 0) out vec2 out_texture_coord; -layout(set = 0, binding = 0) uniform UBOSpritePositions +layout(set = 0, binding = 0) uniform UBOProjection +{ + mat4 proj; +} ubo_projection; + +layout(set = 1, binding = 0) uniform UBOSpritePositions { vec4 positions[128]; } ubo_sprite_positions; @@ -49,5 +54,5 @@ main() coordinate = vec2(position.z, position.w); break; } - gl_Position = vec4(coordinate, 0.0, 1.0); + gl_Position = ubo_projection.proj * vec4(coordinate, 0.0, 1.0); } diff --git a/src/vk/graphics_pipeline_2d.cpp b/src/vk/graphics_pipeline_2d.cpp index e8fd002..bc519d9 100644 --- a/src/vk/graphics_pipeline_2d.cpp +++ b/src/vk/graphics_pipeline_2d.cpp @@ -25,7 +25,44 @@ namespace { void -load_descriptor_set_layout_image_sprites(void *obj) +load_descriptor_set_layout_projection(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + + std::array<VkDescriptorSetLayoutBinding, 1> layout_bindings{}; + + layout_bindings[0].binding = 0; + layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + layout_bindings[0].descriptorCount = 1; + layout_bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + layout_bindings[0].pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutCreateInfo layout_info{}; + layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layout_info.pNext = nullptr; + layout_info.flags = 0; + layout_info.bindingCount = static_cast<uint32_t>(layout_bindings.size()); + layout_info.pBindings = layout_bindings.data(); + + if(vkCreateDescriptorSetLayout( + cg_core.vk_device_with_swapchain->device, &layout_info, nullptr, + &self->descriptor_set_layout_projection) != VK_SUCCESS) + throw CommandError{ + "Failed to create Vulkan descriptor set layout for projection."}; +} + +void +unload_descriptor_set_layout_projection(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + + vkDestroyDescriptorSetLayout( + cg_core.vk_device_with_swapchain->device, + self->descriptor_set_layout_projection, nullptr); +} + +void +load_descriptor_set_layout_sprite(void *obj) { auto self = static_cast<VK::GraphicsPipeline2D*>(obj); @@ -53,19 +90,19 @@ load_descriptor_set_layout_image_sprites(void *obj) if(vkCreateDescriptorSetLayout( cg_core.vk_device_with_swapchain->device, &layout_info, nullptr, - &self->descriptor_set_layout_sprites) != VK_SUCCESS) + &self->descriptor_set_layout_sprite) != VK_SUCCESS) throw CommandError{ - "Failed to create Vulkan descriptor set layout for model instance."}; + "Failed to create Vulkan descriptor set layout for sprites."}; } void -unload_descriptor_set_layout_image_sprites(void *obj) +unload_descriptor_set_layout_sprite(void *obj) { auto self = static_cast<VK::GraphicsPipeline2D*>(obj); vkDestroyDescriptorSetLayout( cg_core.vk_device_with_swapchain->device, - self->descriptor_set_layout_sprites, nullptr); + self->descriptor_set_layout_sprite, nullptr); } void @@ -73,8 +110,9 @@ load_pipeline_layout(void *obj) { auto self = static_cast<VK::GraphicsPipeline2D*>(obj); - std::array<VkDescriptorSetLayout, 1> set_layouts{ - self->descriptor_set_layout_sprites + std::array<VkDescriptorSetLayout, 2> set_layouts{ + self->descriptor_set_layout_projection, + self->descriptor_set_layout_sprite }; VkPipelineLayoutCreateInfo pipeline_layout_info{}; @@ -100,6 +138,122 @@ unload_pipeline_layout(void *obj) } void +load_projection_uniform_buffer(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + + try + { + self->ub_projection.reserve(cg_core.vk_swapchain->images_count); + for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++) + self->ub_projection.emplace_back( + cg_core.vk_device_with_swapchain, sizeof(VK::UBOProjection)); + } + catch(const std::exception& e) + { + throw CommandError{e.what()}; + } +} + +void +unload_projection_uniform_buffer(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + + self->ub_projection.clear(); +} + +void +load_descriptor_pool(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + + VkDescriptorPoolSize descriptor_pool_size{}; + descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptor_pool_size.descriptorCount = self->ub_projection.size(); + + VkDescriptorPoolCreateInfo pool_info{}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.pNext = nullptr; + pool_info.flags = 0; + pool_info.maxSets = self->ub_projection.size(); + pool_info.poolSizeCount = 1; + pool_info.pPoolSizes = &descriptor_pool_size; + + if(vkCreateDescriptorPool( + cg_core.vk_device_with_swapchain->device, + &pool_info, nullptr, &self->descriptor_pool) != VK_SUCCESS) + throw CommandError{"Failed to create a Vulkan descriptor pool."}; +} + +void +unload_descriptor_pool(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + + vkDestroyDescriptorPool( + cg_core.vk_device_with_swapchain->device, self->descriptor_pool, nullptr); +} + +void +load_projection_descriptor_sets(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + + std::vector<VkDescriptorSetLayout> layouts( + self->ub_projection.size(), + self->descriptor_set_layout_projection); + + VkDescriptorSetAllocateInfo alloc_info{}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = self->descriptor_pool; + alloc_info.descriptorSetCount = layouts.size(); + alloc_info.pSetLayouts = layouts.data(); + + self->projection_descriptor_sets.resize(layouts.size()); + if(vkAllocateDescriptorSets( + cg_core.vk_device_with_swapchain->device, &alloc_info, + self->projection_descriptor_sets.data()) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan projection descriptor sets."}; +} + +void +load_resources_to_descriptor_sets(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + + for(auto i{0}; i < self->ub_projection.size(); i++) + { + VkDescriptorBufferInfo projection_info{}; + projection_info.buffer = self->ub_projection[i].buffer; + projection_info.offset = 0; + projection_info.range = sizeof(VK::UBOProjection); + + std::array<VkWriteDescriptorSet, 1> write_descriptors{}; + write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptors[0].dstSet = self->projection_descriptor_sets[i]; + write_descriptors[0].dstBinding = 0; + write_descriptors[0].dstArrayElement = 0; + write_descriptors[0].descriptorCount = 1; + write_descriptors[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + write_descriptors[0].pBufferInfo = &projection_info; + write_descriptors[0].pImageInfo = nullptr; + write_descriptors[0].pTexelBufferView = nullptr; + + vkUpdateDescriptorSets( + cg_core.vk_device_with_swapchain->device, write_descriptors.size(), + write_descriptors.data(), 0, nullptr); + + VK::UBOProjection ubo_projection; + ubo_projection.proj = glm::ortho( + 0.0f, static_cast<float>(cg_core.game_width), + 0.0f, static_cast<float>(cg_core.game_height), + 0.0f, 100.0f); + self->ub_projection[i].copy_data(&ubo_projection); + } +} + +void load_render_pass(void *obj) { auto self = static_cast<VK::GraphicsPipeline2D*>(obj); @@ -393,9 +547,15 @@ unload_pipeline(void *obj) } const CommandChain loader{ - {&load_descriptor_set_layout_image_sprites, - &unload_descriptor_set_layout_image_sprites}, + {&load_descriptor_set_layout_projection, + &unload_descriptor_set_layout_projection}, + {&load_descriptor_set_layout_sprite, &unload_descriptor_set_layout_sprite}, {&load_pipeline_layout, &unload_pipeline_layout}, + {&load_projection_uniform_buffer, &unload_projection_uniform_buffer}, + {&load_descriptor_pool, &unload_descriptor_pool}, + // By destroying the pool the sets are also destroyed. + {&load_projection_descriptor_sets, nullptr}, + {&load_resources_to_descriptor_sets, nullptr}, {&load_render_pass, &unload_render_pass}, {&load_framebuffer, &unload_framebuffer}, {&load_pipeline, &unload_pipeline} @@ -436,7 +596,7 @@ GraphicsPipeline2D::draw( render_pass_begin.pClearValues = nullptr; vkCmdBeginRenderPass( - draw_command_buffer, &render_pass_begin,VK_SUBPASS_CONTENTS_INLINE); + draw_command_buffer, &render_pass_begin,VK_SUBPASS_CONTENTS_INLINE); VkViewport vk_viewport{}; vk_viewport.width = static_cast<float>(cg_core.screen_width); @@ -457,12 +617,15 @@ GraphicsPipeline2D::draw( { // Commands { + std::array<VkDescriptorSet, 2> vk_descriptor_sets{ + this->projection_descriptor_sets[image_index], + sprite->descriptor_sets[image_index]}; VkDeviceSize offsets[]{0}; vkCmdBindDescriptorSets( draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - this->pipeline_layout, 0, 1, &sprite->descriptor_sets[image_index], - 0, nullptr); + this->pipeline_layout, 0, vk_descriptor_sets.size(), + vk_descriptor_sets.data(), 0, nullptr); vkCmdBindPipeline( draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, this->graphic_pipeline); diff --git a/src/vk/graphics_pipeline_2d.hpp b/src/vk/graphics_pipeline_2d.hpp index f6a1b47..dc122be 100644 --- a/src/vk/graphics_pipeline_2d.hpp +++ b/src/vk/graphics_pipeline_2d.hpp @@ -27,9 +27,16 @@ namespace VK struct GraphicsPipeline2D { - VkDescriptorSetLayout descriptor_set_layout_sprites; + VkDescriptorSetLayout descriptor_set_layout_projection; + VkDescriptorSetLayout descriptor_set_layout_sprite; VkPipelineLayout pipeline_layout; + // FIXME: if this vector get resized, it will cause a segmentation fault! + std::vector<UniformBuffer> ub_projection; + + VkDescriptorPool descriptor_pool; + std::vector<VkDescriptorSet> projection_descriptor_sets; + VkRenderPass render_pass; std::vector<VkFramebuffer> swapchain_framebuffers; VkPipeline graphic_pipeline; diff --git a/src/vk/sprite.cpp b/src/vk/sprite.cpp index e00fcbe..a7b65d7 100644 --- a/src/vk/sprite.cpp +++ b/src/vk/sprite.cpp @@ -137,7 +137,7 @@ load_descriptor_sets(void *obj) std::vector<VkDescriptorSetLayout> layouts( cg_core.vk_swapchain->images_count, - cg_core.vk_graphics_pipeline_2d->descriptor_set_layout_sprites); + cg_core.vk_graphics_pipeline_2d->descriptor_set_layout_sprite); VkDescriptorSetAllocateInfo alloc_info{}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; diff --git a/src/vk/uniform_buffer.hpp b/src/vk/uniform_buffer.hpp index 50759b8..2cee9ff 100644 --- a/src/vk/uniform_buffer.hpp +++ b/src/vk/uniform_buffer.hpp @@ -31,6 +31,11 @@ struct UBOSpritePositions glm::vec4 positions[128]; }; +struct UBOProjection +{ + glm::mat4 proj; +}; + struct UBOModelInstance { glm::mat4 instances[128]; diff --git a/test/src/main.rb b/test/src/main.rb index 6ac0dde..b153a50 100644 --- a/test/src/main.rb +++ b/test/src/main.rb @@ -68,7 +68,7 @@ end def quit() = CandyGear.quit(); def tick() - $sprite.draw(-1.0, -1.0, -0.70, -0.5); + $sprite.draw(1.0, 1.0, 101.0, 101.0); $instances_rotation.rotate(0.0, BOX_ROTATION_SPEED); $instances.each do |i| $model.draw(i, $instances_rotation); |