From f1f1576543bb4e0f3b9bc4cd0ba4a12a70546c3c Mon Sep 17 00:00:00 2001 From: Frederico Linhares Date: Tue, 30 Aug 2022 17:45:40 -0300 Subject: feat Create 2d graphics pipeline --- src/vk/graphics_pipeline.cpp | 1064 ------------------------------------------ 1 file changed, 1064 deletions(-) delete mode 100644 src/vk/graphics_pipeline.cpp (limited to 'src/vk/graphics_pipeline.cpp') 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 -#include - -#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(obj); - - std::array 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(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(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(obj); - - std::array 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(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(obj); - - std::array 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(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(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(obj); - - self->ub_view_projection.clear(); -} - -void -load_directional_light_uniform_buffer(void *obj) -{ - auto self = static_cast(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(obj); - - self->ub_directional_light.clear(); -} - -void -load_descriptor_pool(void *obj) -{ - auto self = static_cast(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(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(obj); - - std::vector 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(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 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(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(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(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(obj); - - vkDestroyImageView( - cg_core.vk_device_with_swapchain->device, self->depth_image_view, nullptr); -} - -void -load_render_pass(void *obj) -{ - auto self = static_cast(obj); - - std::array 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(obj); - - vkDestroyRenderPass( - cg_core.vk_device_with_swapchain->device, self->render_pass, nullptr); -} - -void -load_framebuffer(void *obj) -{ - auto self = static_cast(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 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(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(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 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(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(cg_core.screen_width); - viewport.height = static_cast(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(obj); - - vkDestroyPipeline( - cg_core.vk_device_with_swapchain->device, self->graphic_pipeline, nullptr); -} - -void -load_frame_sync(void *obj) -{ - auto self = static_cast(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(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(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(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(obj); - - vkWaitForFences(cg_core.vk_device_with_swapchain->device, 2, - self->in_flight_fences.data(), VK_TRUE, - std::numeric_limits::max()); - vkDestroyCommandPool( - self->queue_family->device->device, self->command_pool, nullptr); -} - -void -load_draw_command_buffer(void *obj) -{ - auto self = static_cast(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(0.0f, 0.0f, 0.0f)}, - camera_rotation{std::make_shared(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::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::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 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(cg_core.screen_width); - vk_viewport.height = static_cast(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 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(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(); - } -} - -} -- cgit v1.2.3