summaryrefslogtreecommitdiff
path: root/src/vk/graphics_pipeline.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vk/graphics_pipeline.cpp')
-rw-r--r--src/vk/graphics_pipeline.cpp1064
1 files changed, 0 insertions, 1064 deletions
diff --git a/src/vk/graphics_pipeline.cpp b/src/vk/graphics_pipeline.cpp
deleted file mode 100644
index 3956a99..0000000
--- a/src/vk/graphics_pipeline.cpp
+++ /dev/null
@@ -1,1064 +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.
- */
-
-#include "graphics_pipeline.hpp"
-
-#include <array>
-#include <stdexcept>
-
-#include "../core.hpp"
-#include "core.hpp"
-#include "image.hpp"
-#include "uniform_buffer.hpp"
-#include "vertex.hpp"
-
-namespace
-{
-
-void
-load_descriptor_set_layout_model_instance(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(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::GraphicsPipeline*>(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::GraphicsPipeline*>(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::GraphicsPipeline*>(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::GraphicsPipeline*>(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::GraphicsPipeline*>(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::GraphicsPipeline*>(obj);
-
- try
- {
- self->ub_view_projection.reserve(cg_core.vk_swapchain->images_count);
- for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
- self->ub_view_projection.emplace_back(
- cg_core.vk_device_with_swapchain, sizeof(VK::UBOViewProjection));
- }
- catch(const std::exception& e)
- {
- throw CommandError{e.what()};
- }
-}
-
-void
-unload_view_projection_uniform_buffer(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- self->ub_view_projection.clear();
-}
-
-void
-load_directional_light_uniform_buffer(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- try
- {
- self->ub_view_projection.reserve(cg_core.vk_swapchain->images_count);
- for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
- self->ub_directional_light.emplace_back(
- cg_core.vk_device_with_swapchain, sizeof(VK::UBODirectionalLight));
- }
- catch(const std::exception& e)
- {
- throw CommandError{e.what()};
- }
-}
-
-void
-unload_directional_light_uniform_buffer(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- self->ub_directional_light.clear();
-}
-
-void
-load_descriptor_pool(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- VkDescriptorPoolSize descriptor_pool_size{};
- descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- descriptor_pool_size.descriptorCount =
- self->ub_view_projection.size() + self->ub_directional_light.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_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)
- throw CommandError{"Failed to create a Vulkan descriptor pool."};
-}
-
-void
-unload_descriptor_pool(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- vkDestroyDescriptorPool(
- cg_core.vk_device_with_swapchain->device, self->descriptor_pool, nullptr);
-}
-
-void
-load_world_view_descriptor_sets(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- std::vector<VkDescriptorSetLayout> layouts(
- cg_core.vk_swapchain->images_count,
- self->descriptor_set_layout_world_view);
-
- VkDescriptorSetAllocateInfo alloc_info{};
- alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
- alloc_info.descriptorPool = self->descriptor_pool;
- alloc_info.descriptorSetCount = self->ub_view_projection.size();
- alloc_info.pSetLayouts = layouts.data();
-
- self->world_view_descriptor_sets.resize(
- cg_core.vk_swapchain->images_count);
- if(vkAllocateDescriptorSets(
- cg_core.vk_device_with_swapchain->device, &alloc_info,
- self->world_view_descriptor_sets.data()) != VK_SUCCESS)
- throw CommandError{"Failed to create Vulkan world view descriptor set."};
-}
-
-void
-load_resources_to_descriptor_sets(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- for(auto i{0}; i < self->ub_view_projection.size(); i++)
- {
- VkDescriptorBufferInfo view_projection_info{};
- view_projection_info.buffer = self->ub_view_projection[i].buffer;
- view_projection_info.offset = 0;
- view_projection_info.range = sizeof(VK::UBOViewProjection);
-
- VkDescriptorBufferInfo directional_light_info{};
- directional_light_info.buffer = self->ub_directional_light[i].buffer;
- directional_light_info.offset = 0;
- directional_light_info.range = sizeof(VK::UBODirectionalLight);
-
- std::array<VkWriteDescriptorSet, 2> write_descriptors{};
- write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- write_descriptors[0].dstSet = self->world_view_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 = &view_projection_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->world_view_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 = &directional_light_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);
- }
-}
-
-void
-load_depth_image(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- VkExtent3D extent3d{};
- extent3d.width = cg_core.screen_width;
- extent3d.height = cg_core.screen_height;
- extent3d.depth = 1;
-
- try
- {
- VK::Image::create(
- cg_core.vk_device_with_swapchain,
- &self->depth_image,
- &self->depth_image_memory,
- VK_FORMAT_D32_SFLOAT,
- extent3d,
- 1,
- VK_IMAGE_TILING_OPTIMAL,
- VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
- );
- }
- catch(VK::Image::Error error)
- {
- std::string error_message{"Failed to create depth image → "};
- error_message += error.what();
- throw CommandError{error_message};
- }
-}
-
-void
-unload_depth_image(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(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,
- nullptr);
-}
-
-void
-load_depth_image_view(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- try
- {
- VK::Image::create_view(
- cg_core.vk_device_with_swapchain, &self->depth_image_view,
- self->depth_image,
- VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT);
- }
- catch(VK::Image::Error error)
- {
- std::string error_message{"Failed to create depth image view → "};
- error_message += error.what();
- throw CommandError{error_message};
- }
-}
-
-void
-unload_depth_image_view(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- vkDestroyImageView(
- cg_core.vk_device_with_swapchain->device, self->depth_image_view, nullptr);
-}
-
-void
-load_render_pass(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(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_PRESENT_SRC_KHR;
- // 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."};
-}
-
-void
-unload_render_pass(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- vkDestroyRenderPass(
- cg_core.vk_device_with_swapchain->device, self->render_pass, nullptr);
-}
-
-void
-load_framebuffer(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- self->swapchain_framebuffers.resize(cg_core.vk_swapchain->images_count);
- for (auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
- {
- std::array<VkImageView, 2> attachments = {
- cg_core.vk_swapchain->image_views[i],
- self->depth_image_view
- };
-
- VkFramebufferCreateInfo framebuffer_info{};
- framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- framebuffer_info.renderPass = self->render_pass;
- framebuffer_info.attachmentCount = attachments.size();
- framebuffer_info.pAttachments = attachments.data();
- framebuffer_info.width = cg_core.screen_width;
- framebuffer_info.height = cg_core.screen_height;
-
- framebuffer_info.layers = 1;
-
- if(vkCreateFramebuffer(
- cg_core.vk_device_with_swapchain->device, &framebuffer_info, nullptr,
- &self->swapchain_framebuffers[i]) != VK_SUCCESS)
- throw CommandError{"Failed to create Vulkan Framebuffer."};
- }
-}
-
-void
-unload_framebuffer(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- for(auto framebuffer: self->swapchain_framebuffers)
- vkDestroyFramebuffer(
- cg_core.vk_device_with_swapchain->device, framebuffer, nullptr);
-}
-
-void
-load_pipeline(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- VkPipelineShaderStageCreateInfo vert_shader_stage_info = {};
- vert_shader_stage_info.sType =
- VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- vert_shader_stage_info.pNext = nullptr;
- 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->vert_shader_module;
- vert_shader_stage_info.pName = "main";
- vert_shader_stage_info.pSpecializationInfo = nullptr;
-
- VkPipelineShaderStageCreateInfo frag_shader_stage_info = {};
- frag_shader_stage_info.sType =
- VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- frag_shader_stage_info.pNext = nullptr;
- 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->frag_shader_module;
- frag_shader_stage_info.pName = "main";
- frag_shader_stage_info.pSpecializationInfo = nullptr;
-
- VkPipelineShaderStageCreateInfo shader_stages[] = {
- vert_shader_stage_info,
- frag_shader_stage_info
- };
-
- VkVertexInputBindingDescription vertex_input_binding{};
- vertex_input_binding.binding = 0;
- vertex_input_binding.stride = sizeof(VK::Vertex);
- vertex_input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
-
- std::array<VkVertexInputAttributeDescription, 3> vertex_attribute{};
- // Position.
- vertex_attribute[0].location = 0;
- vertex_attribute[0].binding = 0;
- vertex_attribute[0].format = VK_FORMAT_R32G32B32_SFLOAT;
- vertex_attribute[0].offset = offsetof(VK::Vertex, position);
- // Normal.
- vertex_attribute[1].location = 1;
- vertex_attribute[1].binding = 0;
- vertex_attribute[1].format = VK_FORMAT_R32G32B32_SFLOAT;
- vertex_attribute[1].offset = offsetof(VK::Vertex, normal);
- // Texture coordinate.
- vertex_attribute[2].location = 2;
- vertex_attribute[2].binding = 0;
- vertex_attribute[2].format = VK_FORMAT_R32G32_SFLOAT;
- vertex_attribute[2].offset = offsetof(VK::Vertex, texture_coord);
-
- VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
- vertex_input_info.sType =
- VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
- vertex_input_info.pNext = nullptr;
- vertex_input_info.flags = 0;
- vertex_input_info.vertexBindingDescriptionCount = 1;
- vertex_input_info.pVertexBindingDescriptions = &vertex_input_binding;
- vertex_input_info.vertexAttributeDescriptionCount =
- static_cast<uint32_t>(vertex_attribute.size());
- vertex_input_info.pVertexAttributeDescriptions = vertex_attribute.data();
-
- VkPipelineInputAssemblyStateCreateInfo input_assembly = {};
- input_assembly.sType =
- VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
- input_assembly.pNext = nullptr;
- input_assembly.flags = 0;
- input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
- input_assembly.primitiveRestartEnable = VK_FALSE;
-
- VkViewport viewport = {};
- viewport.x = 0.0f;
- viewport.y = 0.0f;
- viewport.width = static_cast<float>(cg_core.screen_width);
- viewport.height = static_cast<float>(cg_core.screen_height);
- viewport.minDepth = 0.0f;
- viewport.maxDepth = 1.0f;
-
- VkRect2D scissor = {};
- scissor.offset = {0, 0};
- scissor.extent = {cg_core.screen_width, cg_core.screen_height};
-
- VkPipelineViewportStateCreateInfo viewport_state = {};
- viewport_state.sType =
- VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
- viewport_state.pNext = nullptr;
- viewport_state.flags = 0;
- viewport_state.viewportCount = 1;
- viewport_state.pViewports = &viewport;
- viewport_state.scissorCount = 1;
- viewport_state.pScissors = &scissor;
-
- VkPipelineRasterizationStateCreateInfo rasterizer = {};
- rasterizer.sType =
- VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
- rasterizer.pNext = nullptr;
- rasterizer.flags = 0;
- rasterizer.depthClampEnable = VK_FALSE;
- rasterizer.rasterizerDiscardEnable = VK_FALSE;
- rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
- rasterizer.cullMode = VK_CULL_MODE_NONE;
- rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
- rasterizer.depthBiasEnable = VK_FALSE;
- rasterizer.depthBiasConstantFactor = 0.0f;
- rasterizer.depthBiasClamp = 0.0f;
- rasterizer.depthBiasSlopeFactor = 0.0f;
- rasterizer.lineWidth = 1.0f;
-
- VkPipelineMultisampleStateCreateInfo multisampling = {};
- multisampling.sType =
- VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
- multisampling.sampleShadingEnable = VK_FALSE;
- multisampling.minSampleShading = 1.0f;
- multisampling.pSampleMask = nullptr;
- multisampling.alphaToCoverageEnable = VK_FALSE;
- multisampling.alphaToOneEnable = VK_FALSE;
-
- VkPipelineDepthStencilStateCreateInfo depth_stencil = {};
- depth_stencil.sType =
- VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
- depth_stencil.depthTestEnable = VK_TRUE;
- depth_stencil.depthWriteEnable = VK_TRUE;
- depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS;
- depth_stencil.depthBoundsTestEnable = VK_FALSE;
- depth_stencil.minDepthBounds = 0.0f;
- depth_stencil.maxDepthBounds = 1.0f;
- depth_stencil.stencilTestEnable = VK_FALSE;
- depth_stencil.front = {};
- depth_stencil.back = {};
-
- 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.colorBlendOp = VK_BLEND_OP_ADD;
- color_blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
- color_blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
- color_blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD;
- color_blend_attachment.colorWriteMask =
- VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
- VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
-
- VkPipelineColorBlendStateCreateInfo color_blending = {};
- color_blending.sType =
- VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
- color_blending.pNext = nullptr;
- color_blending.flags = 0;
- color_blending.logicOpEnable = VK_FALSE;
- color_blending.logicOp = VK_LOGIC_OP_COPY;
- color_blending.attachmentCount = 1;
- color_blending.pAttachments = &color_blend_attachment;
- color_blending.blendConstants[0] = 0.0f;
- color_blending.blendConstants[1] = 0.0f;
- color_blending.blendConstants[2] = 0.0f;
- color_blending.blendConstants[3] = 0.0f;
-
- VkDynamicState dynamic_states[] = {
- VK_DYNAMIC_STATE_VIEWPORT,
- VK_DYNAMIC_STATE_LINE_WIDTH
- };
-
- 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;
-
- VkGraphicsPipelineCreateInfo pipeline_info{};
- pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- pipeline_info.pNext = nullptr;
- pipeline_info.flags = 0;
- pipeline_info.stageCount = 2;
- pipeline_info.pStages = shader_stages;
- pipeline_info.pVertexInputState = &vertex_input_info;
- pipeline_info.pInputAssemblyState = &input_assembly;
- pipeline_info.pTessellationState = nullptr;
- pipeline_info.pViewportState = &viewport_state;
- pipeline_info.pRasterizationState = &rasterizer;
- pipeline_info.pMultisampleState = &multisampling;
- 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 = self->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)
- throw CommandError{"Failed to create graphics pipeline."};
-}
-
-void
-unload_pipeline(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- vkDestroyPipeline(
- cg_core.vk_device_with_swapchain->device, self->graphic_pipeline, nullptr);
-}
-
-void
-load_frame_sync(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- self->image_available_semaphores.resize(self->max_frames_in_flight);
- self->render_finished_semaphores.resize(self->max_frames_in_flight);
- self->in_flight_fences.resize(self->max_frames_in_flight);
-
- VkSemaphoreCreateInfo semaphore_info = {};
- semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- semaphore_info.pNext = nullptr;
- semaphore_info.flags = 0;
-
- VkFenceCreateInfo fence_info = {};
- fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fence_info.pNext = nullptr;
- fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
-
- // FIXME: if this loop fails, it will not destroy the semaphores.
- for(auto i{0}; i < self->max_frames_in_flight; i++)
- {
- if(vkCreateSemaphore(
- cg_core.vk_device_with_swapchain->device, &semaphore_info,
- nullptr, &self->image_available_semaphores[i]) != VK_SUCCESS ||
- vkCreateSemaphore(
- cg_core.vk_device_with_swapchain->device, &semaphore_info,
- nullptr, &self->render_finished_semaphores[i]) != VK_SUCCESS ||
- vkCreateFence(cg_core.vk_device_with_swapchain->device, &fence_info,
- nullptr, &self->in_flight_fences[i]) != VK_SUCCESS)
- throw CommandError{"Failed to create semaphores."};
- }
-}
-
-void
-unload_frame_sync(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- vkDeviceWaitIdle(cg_core.vk_device_with_swapchain->device);
-
- for(auto i{0}; i < self->max_frames_in_flight; i++)
- {
- vkDestroySemaphore(cg_core.vk_device_with_swapchain->device,
- self->render_finished_semaphores[i], nullptr);
- vkDestroySemaphore(cg_core.vk_device_with_swapchain->device,
- self->image_available_semaphores[i], nullptr);
- vkDestroyFence(cg_core.vk_device_with_swapchain->device,
- self->in_flight_fences[i], nullptr);
- }
-}
-
-void
-load_queue_family(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- self->queue_family =
- cg_core.vk_device_with_swapchain->get_queue_family_with_presentation();
-}
-
-void
-load_command_pool(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- VkCommandPoolCreateInfo create_info{};
- create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- create_info.pNext = nullptr;
- create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- create_info.queueFamilyIndex = self->queue_family->family_index;
-
- vkCreateCommandPool(
- self->queue_family->device->device, &create_info, nullptr,
- &self->command_pool);
-}
-
-void
-unload_command_pool(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- vkWaitForFences(cg_core.vk_device_with_swapchain->device, 2,
- self->in_flight_fences.data(), VK_TRUE,
- std::numeric_limits<uint64_t>::max());
- vkDestroyCommandPool(
- self->queue_family->device->device, self->command_pool, nullptr);
-}
-
-void
-load_draw_command_buffer(void *obj)
-{
- auto self = static_cast<VK::GraphicsPipeline*>(obj);
-
- // FIXME: 3 is a magical number, triple buffering.
- self->draw_command_buffers.resize(3);
-
- VkCommandBufferAllocateInfo allocate_info{};
- allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- allocate_info.pNext = nullptr;
- allocate_info.commandPool = self->command_pool;
- allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- allocate_info.commandBufferCount = self->draw_command_buffers.size();
-
- if(vkAllocateCommandBuffers(
- self->queue_family->device->device, &allocate_info,
- self->draw_command_buffers.data()) != VK_SUCCESS)
- throw CommandError{"Vulkan draw command buffers could not be allocated."};
-}
-
-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,
- &unload_directional_light_uniform_buffer},
- {&load_descriptor_pool, &unload_descriptor_pool},
- // By destroying the pool the sets are also destroyed.
- {&load_world_view_descriptor_sets, nullptr},
- {&load_resources_to_descriptor_sets, nullptr},
- {&load_depth_image, &unload_depth_image},
- {&load_depth_image_view, &unload_depth_image_view},
- {&load_render_pass, &unload_render_pass},
- {&load_framebuffer, &unload_framebuffer},
- {&load_pipeline, &unload_pipeline},
- {&load_frame_sync, &unload_frame_sync},
- {&load_queue_family, nullptr},
- {&load_command_pool, &unload_command_pool},
- {&load_draw_command_buffer, nullptr}
-};
-
-}
-
-namespace VK
-{
-
-GraphicsPipeline::GraphicsPipeline():
- current_frame{0},
- 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)},
- models_to_draw{cg_core.vk_swapchain->images_count}
-{
- loader.execute(this);
-}
-
-GraphicsPipeline::~GraphicsPipeline()
-{
- loader.revert(this);
-}
-
-void
-GraphicsPipeline::draw()
-{
- vkWaitForFences(cg_core.vk_device_with_swapchain->device, 1,
- &this->in_flight_fences[this->current_frame], VK_TRUE,
- std::numeric_limits<uint64_t>::max());
- vkResetFences(cg_core.vk_device_with_swapchain->device, 1,
- &this->in_flight_fences[this->current_frame]);
-
- uint32_t image_index;
- vkAcquireNextImageKHR(
- cg_core.vk_device_with_swapchain->device, cg_core.vk_swapchain->swapchain,
- std::numeric_limits<uint64_t>::max(),
- this->image_available_semaphores[this->current_frame],
- VK_NULL_HANDLE, &image_index);
-
- auto &draw_command_buffer = this->draw_command_buffers[this->current_frame];
- vkResetCommandBuffer(draw_command_buffer, 0);
-
- // Load command.
- {
- VkCommandBufferBeginInfo begin_info{};
- begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- begin_info.flags = 0;
- begin_info.pInheritanceInfo = nullptr;
- if (vkBeginCommandBuffer(draw_command_buffer, &begin_info) != VK_SUCCESS)
- {
- throw std::runtime_error{"Failed to beggin draw command buffer."};
- }
-
- // Dark gray blue.
- std::array<VkClearValue, 2> clear_values{};
- clear_values[0].color = {0.12f, 0.12f, 0.18f, 1.0f};
- clear_values[1].depthStencil = {1.0f, 0};
-
- VkRenderPassBeginInfo render_pass_begin{};
- render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- render_pass_begin.pNext = nullptr;
- render_pass_begin.renderPass = this->render_pass;
- render_pass_begin.framebuffer = this->swapchain_framebuffers[image_index];
- render_pass_begin.renderArea.offset = {0, 0};
- render_pass_begin.renderArea.extent = {
- cg_core.screen_width, cg_core.screen_height};
- render_pass_begin.clearValueCount = clear_values.size();
- render_pass_begin.pClearValues = clear_values.data();
-
- vkCmdBeginRenderPass(
- draw_command_buffer, &render_pass_begin,VK_SUBPASS_CONTENTS_INLINE);
-
- VkViewport vk_viewport{};
- vk_viewport.width = static_cast<float>(cg_core.screen_width);
- vk_viewport.height = static_cast<float>(cg_core.screen_height);
- vk_viewport.minDepth = 0.0f;
- vk_viewport.maxDepth = 1.0f;
- vkCmdSetViewport(draw_command_buffer, 0, 1, &vk_viewport);
-
- VkRect2D vk_scissor{};
- vk_scissor.extent.width = cg_core.screen_width;
- vk_scissor.extent.height = cg_core.screen_height;
- vk_scissor.offset.x = 0;
- vk_scissor.offset.y = 0;
- vkCmdSetScissor(draw_command_buffer, 0, 1, &vk_scissor);
-
- // Draw models
- for(auto& [model, instances] : this->models_to_draw[this->current_frame])
- {
- // Commands
- {
- std::array<VkDescriptorSet, 2> vk_descriptor_sets{
- this->world_view_descriptor_sets[image_index],
- model->descriptor_sets[image_index]};
- VkBuffer vertex_buffers[]{model->vertex_buffer->buffer};
- VkDeviceSize offsets[]{0};
-
- vkCmdBindDescriptorSets(
- draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
- 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);
- vkCmdBindVertexBuffers(
- draw_command_buffer, 0, 1, vertex_buffers, offsets);
- vkCmdBindIndexBuffer(
- draw_command_buffer, model->index_buffer->buffer, 0,
- VK_INDEX_TYPE_UINT32);
- vkCmdDrawIndexed(
- draw_command_buffer, model->index_count, instances.size(), 0, 0, 0);
- }
-
- VK::UBOModelInstance ubo_model_instance;
-
- for(int i{0}; i < instances.size(); i++)
- {
- // Object matrix.
- glm::mat4 instance_matrix{1.0f};
- instance_matrix = glm::translate(
- instance_matrix, instances[i].position);
- instance_matrix = glm::rotate(
- instance_matrix, instances[i].rotation.x, glm::vec3{1.0, 0.0, 0.0});
- instance_matrix = glm::rotate(
- instance_matrix, instances[i].rotation.y, glm::vec3{0.0, 1.0, 0.0});
- instance_matrix = glm::rotate(
- instance_matrix, instances[i].rotation.z, glm::vec3{0.0, 0.0, 1.0});
-
- ubo_model_instance.model[i] = instance_matrix;
- }
-
- model->ub_model_instance[image_index].copy_data(&ubo_model_instance);
- }
- vkCmdEndRenderPass(draw_command_buffer);
-
- if(vkEndCommandBuffer(draw_command_buffer) != VK_SUCCESS)
- throw std::runtime_error{"Failed to end draw command buffer."};
- }
-
- // Update view projection uniform buffers
- {
- VK::UBOViewProjection ubo_view_projection{};
-
- // View matrix.
- ubo_view_projection.view = glm::mat4{1.0f};
- ubo_view_projection.view = glm::translate(
- ubo_view_projection.view, *this->camera_position);
- ubo_view_projection.view = glm::rotate(
- ubo_view_projection.view, this->camera_rotation->y,
- glm::vec3{0.0, 1.0, 0.0});
- ubo_view_projection.view = glm::rotate(
- ubo_view_projection.view, this->camera_rotation->x,
- glm::vec3{1.0, 0.0, 0.0});
- ubo_view_projection.view = glm::rotate(
- ubo_view_projection.view, this->camera_rotation->z,
- glm::vec3{0.0, 0.0, 1.0});
- ubo_view_projection.view = glm::inverse(ubo_view_projection.view);
-
- // Projection matrix.
- ubo_view_projection.proj = glm::perspective(
- glm::radians(45.0f),
- cg_core.screen_width / static_cast<float>(cg_core.screen_height),
- 0.1f, 100.0f);
- ubo_view_projection.proj[1][1] *= -1;
-
- ubo_view_projection.ambient_color = glm::vec4{0.25, 0.25, 0.25, 1.0};
-
- this->ub_view_projection[image_index].copy_data(&ubo_view_projection);
- }
-
- // Update directional light uniform buffers
- {
- UBODirectionalLight ubo_directional_light{};
- ubo_directional_light.direction = glm::vec3{-0.57735, -0.57735, -0.57735};
- ubo_directional_light.color = glm::vec4{0.8, 0.8, 0.8, 1.0};
-
- this->ub_directional_light[image_index].copy_data(&ubo_directional_light);
- }
-
- // Submit drawing command.
- {
- auto queue{this->queue_family->get_queue()};
-
- VkSemaphore wait_semaphores[]{
- this->image_available_semaphores[this->current_frame]};
- VkPipelineStageFlags wait_stages[] =
- {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
- VkSemaphore signal_semaphores[]{
- this->render_finished_semaphores[this->current_frame]};
-
- VkSubmitInfo submit_info{};
- submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submit_info.pNext = nullptr;
- submit_info.waitSemaphoreCount = 1;
- submit_info.pWaitSemaphores = wait_semaphores;
- submit_info.pWaitDstStageMask = wait_stages;
- submit_info.commandBufferCount = 1;
- submit_info.pCommandBuffers = &draw_command_buffer;
- submit_info.signalSemaphoreCount = 1;
- submit_info.pSignalSemaphores = signal_semaphores;
-
- if(vkQueueSubmit(
- queue.queue, 1, &submit_info,
- this->in_flight_fences[this->current_frame]) != VK_SUCCESS)
- throw std::runtime_error{"Failed to submit draw command buffer."};
-
- VkSwapchainKHR swap_chains[]{cg_core.vk_swapchain->swapchain};
-
- VkPresentInfoKHR present_info{};
- present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
- present_info.pNext = nullptr;
- present_info.waitSemaphoreCount = 1;
- present_info.pWaitSemaphores = signal_semaphores;
- present_info.swapchainCount = 1;
- present_info.pSwapchains = swap_chains;
- present_info.pImageIndices = &image_index;
- present_info.pResults = nullptr;
-
- vkQueuePresentKHR(queue.queue, &present_info);
-
- // Prepare for the next frame.
- this->current_frame =
- (this->current_frame + 1) % this->max_frames_in_flight;
- this->models_to_draw[this->current_frame].clear();
- }
-}
-
-}