#include "UwURenderEngine.hpp" #include #include #include #include #include #include "GPU_GarbageCollector.h" #include "../Game/Actors/Camera.hpp" #include "Core/CoreInstance.hpp" #include "Game/GameInstance.hpp" #include "Game/World/World.hpp" #include "../Game/Actors/Mesh/Mesh.hpp" #include "DeviceFunctions/DeviceFunctions.hpp" RENDER_ENGINE_FACTORY_GENERATE(UwURenderEngine) VkShaderModule UwURenderEngine::create_shader_module(const std::string& code) const { VkShaderModuleCreateInfo shader_module_info{}; shader_module_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; shader_module_info.codeSize = code.size(); shader_module_info.pCode = reinterpret_cast(code.c_str()); VkShaderModule shader_module; VK_CHECK(vkCreateShaderModule(device_.get_native(), &shader_module_info, nullptr, &shader_module)) return shader_module; } void UwURenderEngine::create_render_pass() { VkAttachmentDescription attachment_description{}; attachment_description.format = swapchain_.get_image_format(); attachment_description.samples = VK_SAMPLE_COUNT_1_BIT; attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachment_description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachment_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachment_description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; attachment_description.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; VkAttachmentReference attachment_reference; attachment_reference.attachment = 0; attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkSubpassDescription subpass_description{}; subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass_description.colorAttachmentCount = 1; subpass_description.pColorAttachments = &attachment_reference; VkSubpassDependency dependency{}; dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependency.srcAccessMask = 0; dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; VkRenderPassCreateInfo render_pass_info{}; render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; render_pass_info.attachmentCount = 1; render_pass_info.pAttachments = &attachment_description; render_pass_info.subpassCount = 1; render_pass_info.pSubpasses = &subpass_description; render_pass_info.dependencyCount = 1; render_pass_info.pDependencies = &dependency; VK_CHECK(vkCreateRenderPass(device_.get_native(), &render_pass_info, nullptr, &render_pass_)) } void UwURenderEngine::create_description_set_layout() { VkDescriptorSetLayoutBinding ubo_layout_binding; ubo_layout_binding.binding = 0; ubo_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; ubo_layout_binding.descriptorCount = 1; ubo_layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; ubo_layout_binding.pImmutableSamplers = nullptr; VkDescriptorSetLayoutCreateInfo ubo_layout_info{}; ubo_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; ubo_layout_info.bindingCount = 1; ubo_layout_info.pBindings = &ubo_layout_binding; VK_CHECK(vkCreateDescriptorSetLayout(device_.get_native(), &ubo_layout_info, nullptr, &ubo_layout_binding_)) } void UwURenderEngine::create_uniform_buffers() { uniform_buffers_.resize(swapchain_.get_images().size()); uniform_buffers_memory_.resize(swapchain_.get_images().size()); uniform_buffers_mapped_.resize(swapchain_.get_images().size()); std::vector arr_indices = physical_device_.get_unique_family_indices(); for (size_t i = 0; i < swapchain_.get_images().size(); ++i) { constexpr VkDeviceSize size = sizeof(UniformBufferObject); uniform_buffers_[i] = DeviceFunctions::create_buffer(device_.get_native(), size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, arr_indices); uniform_buffers_memory_[i] = DeviceFunctions::allocate_device_memory(physical_device_.get_native(), device_.get_native(), uniform_buffers_[i], VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); vkBindBufferMemory(device_.get_native(), uniform_buffers_[i], uniform_buffers_memory_[i], 0); vkMapMemory(device_.get_native(), uniform_buffers_memory_[i], 0, size, 0, &uniform_buffers_mapped_[i]); } } void UwURenderEngine::create_descriptor_pool() { VkDescriptorPoolSize pool_size; pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; pool_size.descriptorCount = static_cast(swapchain_.get_images().size()); VkDescriptorPoolCreateInfo descriptor_pool_info{}; descriptor_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; descriptor_pool_info.poolSizeCount = 1; descriptor_pool_info.pPoolSizes = &pool_size; descriptor_pool_info.maxSets = static_cast(swapchain_.get_images().size()); VK_CHECK(vkCreateDescriptorPool(device_.get_native(), &descriptor_pool_info, nullptr, &descriptor_pool_)) } void UwURenderEngine::create_descriptor_sets() { std::vector layouts(swapchain_.get_images().size(), ubo_layout_binding_); VkDescriptorSetAllocateInfo descriptor_set_allocate_info{}; descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; descriptor_set_allocate_info.descriptorPool = descriptor_pool_; descriptor_set_allocate_info.descriptorSetCount = static_cast(swapchain_.get_images().size()); descriptor_set_allocate_info.pSetLayouts = layouts.data(); descriptor_sets_.resize(swapchain_.get_images().size()); VK_CHECK(vkAllocateDescriptorSets(device_.get_native(), &descriptor_set_allocate_info, descriptor_sets_.data())) for (size_t i = 0; i < swapchain_.get_images().size(); ++i) { VkDescriptorBufferInfo buffer_info{}; buffer_info.buffer = uniform_buffers_[i]; buffer_info.offset = 0; buffer_info.range = sizeof(UniformBufferObject); VkWriteDescriptorSet write_descriptor_set{}; write_descriptor_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write_descriptor_set.dstSet = descriptor_sets_[i]; write_descriptor_set.dstBinding = 0; write_descriptor_set.dstArrayElement = 0; write_descriptor_set.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; write_descriptor_set.descriptorCount = 1; write_descriptor_set.pBufferInfo = &buffer_info; write_descriptor_set.pImageInfo = nullptr; write_descriptor_set.pTexelBufferView = nullptr; vkUpdateDescriptorSets(device_.get_native(), 1, &write_descriptor_set, 0, nullptr); } } void UwURenderEngine::create_graphics_pipeline() { std::ifstream vertex_shader_file("Shaders/vertex.spv", std::ios::binary); if (!vertex_shader_file.is_open()) throw std::runtime_error("Vertex shader not found"); std::ifstream fragment_shader_file("Shaders/fragment.spv", std::ios::binary); if (!fragment_shader_file.is_open()) { vertex_shader_file.close(); throw std::runtime_error("Fragment shader not found"); } std::string vertex_shader_code((std::istreambuf_iterator(vertex_shader_file)), std::istreambuf_iterator()); std::string fragment_shader_code((std::istreambuf_iterator(fragment_shader_file)), std::istreambuf_iterator()); vertex_shader_file.close(); fragment_shader_file.close(); VkShaderModule vertex_shader = create_shader_module(vertex_shader_code); VkShaderModule fragment_shader = create_shader_module(fragment_shader_code); VkPipelineShaderStageCreateInfo vertex_shader_stage_info{}; vertex_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; vertex_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT; vertex_shader_stage_info.module = vertex_shader; vertex_shader_stage_info.pName = "main"; VkPipelineShaderStageCreateInfo fragment_shader_stage_info{}; fragment_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; fragment_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT; fragment_shader_stage_info.module = fragment_shader; fragment_shader_stage_info.pName = "main"; VkPipelineShaderStageCreateInfo shader_stages[] = {vertex_shader_stage_info, fragment_shader_stage_info}; const std::vector dynamic_states = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; VkPipelineDynamicStateCreateInfo dynamic_state_info{}; dynamic_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; dynamic_state_info.dynamicStateCount = static_cast(dynamic_states.size()); dynamic_state_info.pDynamicStates = dynamic_states.data(); VkVertexInputBindingDescription binding_description = ModelManager::Vertex::get_binding_description(); std::array attribute_descriptions = ModelManager::Vertex::get_vertex_attribute_descriptions(); VkPipelineVertexInputStateCreateInfo vertex_input_info{}; vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertex_input_info.vertexBindingDescriptionCount = 1; vertex_input_info.pVertexBindingDescriptions = &binding_description; vertex_input_info.vertexAttributeDescriptionCount = static_cast(attribute_descriptions.size()); vertex_input_info.pVertexAttributeDescriptions = attribute_descriptions.data(); VkPipelineInputAssemblyStateCreateInfo input_assembly_info{}; input_assembly_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; input_assembly_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; input_assembly_info.primitiveRestartEnable = VK_FALSE; VkViewport viewport{}; viewport.x = 0.0f; viewport.y = 0.0f; viewport.width = static_cast(swapchain_.get_extent().width); viewport.height = static_cast(swapchain_.get_extent().height); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor{}; scissor.offset = {0, 0}; scissor.extent = swapchain_.get_extent(); VkPipelineViewportStateCreateInfo viewport_info{}; viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; viewport_info.viewportCount = 1; viewport_info.pViewports = &viewport; viewport_info.scissorCount = 1; viewport_info.pScissors = &scissor; VkPipelineRasterizationStateCreateInfo rasterization_info{}; rasterization_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; rasterization_info.depthClampEnable = VK_FALSE; rasterization_info.rasterizerDiscardEnable = VK_FALSE; rasterization_info.polygonMode = VK_POLYGON_MODE_FILL; rasterization_info.lineWidth = 1.0f; rasterization_info.cullMode = VK_CULL_MODE_BACK_BIT; rasterization_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rasterization_info.depthBiasEnable = VK_FALSE; VkPipelineMultisampleStateCreateInfo multisample_info{}; multisample_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisample_info.sampleShadingEnable = VK_FALSE; multisample_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; VkPipelineColorBlendAttachmentState color_blend_attachment_state{}; color_blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; color_blend_attachment_state.blendEnable = VK_TRUE; color_blend_attachment_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; color_blend_attachment_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; color_blend_attachment_state.colorBlendOp = VK_BLEND_OP_ADD; color_blend_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; color_blend_attachment_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; color_blend_attachment_state.alphaBlendOp = VK_BLEND_OP_ADD; VkPipelineColorBlendStateCreateInfo color_blend_info{}; color_blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; color_blend_info.logicOpEnable = VK_FALSE; color_blend_info.attachmentCount = 1; color_blend_info.pAttachments = &color_blend_attachment_state; color_blend_info.blendConstants[0] = 0.0f; color_blend_info.blendConstants[1] = 0.0f; color_blend_info.blendConstants[2] = 0.0f; color_blend_info.blendConstants[3] = 0.0f; VkPipelineLayoutCreateInfo pipeline_layout_info{}; pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipeline_layout_info.setLayoutCount = 1; pipeline_layout_info.pSetLayouts = &ubo_layout_binding_; VK_CHECK(vkCreatePipelineLayout(device_.get_native(), &pipeline_layout_info, nullptr, &pipeline_layout_)) VkGraphicsPipelineCreateInfo graphics_pipeline_info{}; graphics_pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; graphics_pipeline_info.stageCount = 2; graphics_pipeline_info.pStages = shader_stages; graphics_pipeline_info.layout = pipeline_layout_; graphics_pipeline_info.pColorBlendState = &color_blend_info; graphics_pipeline_info.pDynamicState = &dynamic_state_info; graphics_pipeline_info.pInputAssemblyState = &input_assembly_info; graphics_pipeline_info.pMultisampleState = &multisample_info; graphics_pipeline_info.pRasterizationState = &rasterization_info; graphics_pipeline_info.pViewportState = &viewport_info; graphics_pipeline_info.pVertexInputState = &vertex_input_info; graphics_pipeline_info.pDepthStencilState = nullptr; graphics_pipeline_info.renderPass = render_pass_; graphics_pipeline_info.subpass = 0; graphics_pipeline_info.basePipelineHandle = nullptr; graphics_pipeline_info.basePipelineIndex = -1; VK_CHECK(vkCreateGraphicsPipelines(device_.get_native(), nullptr, 1, &graphics_pipeline_info, nullptr, &graphics_pipeline_)) vkDestroyShaderModule(device_.get_native(), vertex_shader, nullptr); vkDestroyShaderModule(device_.get_native(), fragment_shader, nullptr); } void UwURenderEngine::create_framebuffers() { framebuffers_.resize(swapchain_.get_images().size()); VkFramebufferCreateInfo framebuffer_info{}; framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebuffer_info.renderPass = render_pass_; framebuffer_info.attachmentCount = 1; framebuffer_info.width = swapchain_.get_extent().width; framebuffer_info.height = swapchain_.get_extent().height; framebuffer_info.layers = 1; for (size_t i = 0; i < framebuffers_.size(); ++i) { framebuffer_info.pAttachments = &swapchain_.get_image_views()[i]; VK_CHECK(vkCreateFramebuffer(device_.get_native(), &framebuffer_info, nullptr, &framebuffers_[i])) } } void UwURenderEngine::create_command_pool() { VkObjects::PhysicalDevice::QueueFamilyIndices queue_family_indices = physical_device_.get_queue_family_indices(); VkCommandPoolCreateInfo command_pool_info{}; command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; command_pool_info.queueFamilyIndex = queue_family_indices.graphics_family; command_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; VK_CHECK(vkCreateCommandPool(device_.get_native(), &command_pool_info, nullptr, &command_pool_)) } void UwURenderEngine::allocate_vertex_buffer() { VkObjects::PhysicalDevice::QueueFamilyIndices indices = physical_device_.get_queue_family_indices(); std::vector arr_indices = physical_device_.get_unique_family_indices(); std::vector transfer_index = {indices.transfer_family}; VkDeviceSize size_buffer = sizeof(vertices_[0]) * vertices_.size(); VkBuffer staging_buffer = DeviceFunctions::create_buffer(device_.get_native(), size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, transfer_index); VkDeviceMemory staging_buffer_memory = DeviceFunctions::allocate_device_memory( physical_device_.get_native(), device_.get_native(), staging_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); vertex_buffer_ = DeviceFunctions::create_buffer(device_.get_native(), size_buffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, arr_indices); vertex_buffer_memory_ = DeviceFunctions::allocate_device_memory(physical_device_.get_native(), device_.get_native(), vertex_buffer_, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); VK_CHECK(vkBindBufferMemory(device_.get_native(), staging_buffer, staging_buffer_memory, 0)) VK_CHECK(vkBindBufferMemory(device_.get_native(), vertex_buffer_, vertex_buffer_memory_, 0)) void* data; VK_CHECK(vkMapMemory(device_.get_native(), staging_buffer_memory, 0, size_buffer, 0, &data)) memcpy(data, vertices_.data(), size_buffer); vkUnmapMemory(device_.get_native(), staging_buffer_memory); DeviceFunctions::device_memcpy(device_.get_native(), indices.transfer_family, staging_buffer, vertex_buffer_, size_buffer); vkFreeMemory(device_.get_native(), staging_buffer_memory, nullptr); vkDestroyBuffer(device_.get_native(), staging_buffer, nullptr); } void UwURenderEngine::allocate_index_buffer() { std::vector arr_indices = physical_device_.get_unique_family_indices(); VkObjects::PhysicalDevice::QueueFamilyIndices indices = physical_device_.get_queue_family_indices(); std::vector transfer_index = {indices.transfer_family}; VkDeviceSize size_buffer = sizeof(indices_[0]) * indices_.size(); VkBuffer staging_buffer = DeviceFunctions::create_buffer(device_.get_native(), size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, transfer_index); VkDeviceMemory staging_buffer_memory = DeviceFunctions::allocate_device_memory( physical_device_.get_native(), device_.get_native(), staging_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); vkBindBufferMemory(device_.get_native(), staging_buffer, staging_buffer_memory, 0); void* data; vkMapMemory(device_.get_native(), staging_buffer_memory, 0, size_buffer, 0, &data); memcpy(data, indices_.data(), size_buffer); vkUnmapMemory(device_.get_native(), staging_buffer_memory); index_buffer_ = DeviceFunctions::create_buffer(device_.get_native(), size_buffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, arr_indices); index_buffer_memory_ = DeviceFunctions::allocate_device_memory(physical_device_.get_native(), device_.get_native(), index_buffer_, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); vkBindBufferMemory(device_.get_native(), index_buffer_, index_buffer_memory_, 0); DeviceFunctions::device_memcpy(device_.get_native(), indices.transfer_family,staging_buffer, index_buffer_, size_buffer); vkDestroyBuffer(device_.get_native(), staging_buffer, nullptr); vkFreeMemory(device_.get_native(), staging_buffer_memory, nullptr); } void UwURenderEngine::allocate_command_buffers() { command_buffers_.resize(swapchain_.get_images().size()); VkCommandBufferAllocateInfo command_buffer_allocate_info{}; command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; command_buffer_allocate_info.commandPool = command_pool_; command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; command_buffer_allocate_info.commandBufferCount = static_cast(command_buffers_.size()); VK_CHECK(vkAllocateCommandBuffers(device_.get_native(), &command_buffer_allocate_info, command_buffers_.data())) } void UwURenderEngine::create_sync_objects() { image_available_semaphores_.resize(swapchain_.get_images().size()); render_finished_semaphores_.resize(swapchain_.get_images().size()); in_flight_fences_.resize(swapchain_.get_images().size()); VkSemaphoreCreateInfo semaphore_info{}; semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; VkFenceCreateInfo fence_info{}; fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; for (size_t i = 0; i < swapchain_.get_images().size(); ++i) { VK_CHECK(vkCreateSemaphore(device_.get_native(), &semaphore_info, nullptr, &image_available_semaphores_[i])) VK_CHECK(vkCreateSemaphore(device_.get_native(), &semaphore_info, nullptr, &render_finished_semaphores_[i])) VK_CHECK(vkCreateFence(device_.get_native(), &fence_info, nullptr, &in_flight_fences_[i])) } } void UwURenderEngine::record_command_buffer(VkCommandBuffer command_buffer, uint32_t image_index) const { VkCommandBufferBeginInfo command_buffer_begin_info{}; command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; VK_CHECK(vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info)) constexpr VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; VkRenderPassBeginInfo render_pass_begin_info{}; render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; render_pass_begin_info.renderPass = render_pass_; render_pass_begin_info.framebuffer = framebuffers_[image_index]; render_pass_begin_info.renderArea.offset = {0, 0}; render_pass_begin_info.renderArea.extent = swapchain_.get_extent(); render_pass_begin_info.clearValueCount = 1; render_pass_begin_info.pClearValues = &clear_color; vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline_); VkBuffer vertex_buffers[] = {vertex_buffer_}; VkDeviceSize offset[] = {0}; vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offset); vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, 0, 1, &descriptor_sets_[current_frame_], 0, nullptr); vkCmdBindIndexBuffer(command_buffer, index_buffer_, 0, VK_INDEX_TYPE_UINT16); VkViewport viewport; viewport.x = 0.0f; viewport.y = 0.0f; viewport.width = static_cast(swapchain_.get_extent().width); viewport.height = static_cast(swapchain_.get_extent().height); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; vkCmdSetViewport(command_buffer, 0, 1, &viewport); VkRect2D scissor; scissor.offset = {0, 0}; scissor.extent = swapchain_.get_extent(); vkCmdSetScissor(command_buffer, 0, 1, &scissor); vkCmdDrawIndexed(command_buffer, static_cast(indices_.size()), 1, 0, 0, 0); vkCmdEndRenderPass(command_buffer); VK_CHECK(vkEndCommandBuffer(command_buffer)) } void UwURenderEngine::update_uniform_buffer(uint32_t current_frame) const { glm::vec3 eye{0, 0, 0}; glm::vec3 center{0, 0, 0}; glm::vec3 up{0, 1, 0}; if (active_camera_.expired() == false) { std::shared_ptr camera = active_camera_.lock(); Vector3D loc = camera->GetActorLocate(); eye = {loc.x, loc.y, loc.z}; Vector3D rot = camera->GetActorRotate(); glm::vec3 direction{glm::cos(rot.x)*glm::cos(rot.y), glm::sin(rot.x)*glm::cos(rot.y), glm::sin(rot.y)}; center = eye + direction; up = {0, glm::sin(rot.z), glm::cos(rot.z)}; } // static auto start_time = std::chrono::high_resolution_clock::now(); // auto current_time = std::chrono::high_resolution_clock::now(); // float time = std::chrono::duration_cast>(current_time - start_time).count(); UniformBufferObject ubo; ubo.model = glm::rotate(glm::mat4(1.0f), /*time * glm::radians(45.0f)*/0.f, glm::vec3(0.0f, 0.0f, 1.0f)); ubo.view = glm::lookAt(eye, center, up); ubo.proj = glm::perspective(glm::radians(45.0f), static_cast(swapchain_.get_extent().width) / static_cast(swapchain_.get_extent().height), 0.1f, 256.0f); ubo.proj[1][1] *= -1; memcpy(uniform_buffers_mapped_[current_frame], &ubo, sizeof(ubo)); } void UwURenderEngine::draw_frame() { vkWaitForFences(device_.get_native(), 1, &in_flight_fences_[current_frame_], VK_TRUE, UINT64_MAX); vkResetFences(device_.get_native(), 1, &in_flight_fences_[current_frame_]); // Free video memory garbage_collector_->FreeHeap(); uint32_t image_index; vkAcquireNextImageKHR(device_.get_native(), swapchain_.get_native(), UINT64_MAX, image_available_semaphores_[current_frame_], VK_NULL_HANDLE, &image_index); vkResetCommandBuffer(command_buffers_[current_frame_], 0); update_uniform_buffer(current_frame_); record_command_buffer(command_buffers_[current_frame_], image_index); VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo submit_info{}; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.commandBufferCount = 1; submit_info.pCommandBuffers = &command_buffers_[current_frame_]; submit_info.waitSemaphoreCount = 1; submit_info.pWaitSemaphores = &image_available_semaphores_[current_frame_]; submit_info.pWaitDstStageMask = &wait_stage; submit_info.signalSemaphoreCount = 1; submit_info.pSignalSemaphores = &render_finished_semaphores_[current_frame_]; VK_CHECK(vkQueueSubmit(device_.get_graphics_queue(), 1, &submit_info, in_flight_fences_[current_frame_])) VkSwapchainKHR swapchain = swapchain_.get_native(); VkPresentInfoKHR present_info{}; present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present_info.waitSemaphoreCount = 1; present_info.pWaitSemaphores = &render_finished_semaphores_[current_frame_]; present_info.swapchainCount = 1; present_info.pSwapchains = &swapchain; present_info.pImageIndices = &image_index; present_info.pResults = nullptr; vkQueuePresentKHR(device_.get_present_queue(), &present_info); current_frame_ = (current_frame_ + 1) % static_cast(swapchain_.get_images().size()); } UwURenderEngine::UwURenderEngine(CoreInstance& core): RenderEngineBase(core), core_(core), instance_(core), surface_(instance_, get_window()), physical_device_(instance_, surface_, deviceExtensions), device_(physical_device_, deviceExtensions), swapchain_(surface_, physical_device_, device_, get_window()) { create_render_pass(); create_description_set_layout(); create_uniform_buffers(); create_descriptor_pool(); create_descriptor_sets(); create_graphics_pipeline(); create_framebuffers(); create_command_pool(); allocate_vertex_buffer(); allocate_command_buffers(); allocate_index_buffer(); create_sync_objects(); garbage_collector_.reset(new GPU_GarbageCollector(device_.get_native())); model_manager_.reset(new ModelManager(physical_device_.get_native(), device_.get_native())); } UwURenderEngine::~UwURenderEngine() { vkDeviceWaitIdle(device_.get_native()); if (index_buffer_memory_ != VK_NULL_HANDLE) vkFreeMemory(device_.get_native(), index_buffer_memory_, nullptr); if (index_buffer_ != VK_NULL_HANDLE) vkDestroyBuffer(device_.get_native(), index_buffer_, nullptr); if (vertex_buffer_memory_ != VK_NULL_HANDLE) vkFreeMemory(device_.get_native(), vertex_buffer_memory_, nullptr); if (vertex_buffer_ != VK_NULL_HANDLE) vkDestroyBuffer(device_.get_native(), vertex_buffer_, nullptr); for (auto& i : image_available_semaphores_) vkDestroySemaphore(device_.get_native(), i, nullptr); for (auto& i : render_finished_semaphores_) vkDestroySemaphore(device_.get_native(), i, nullptr); for (auto& i : in_flight_fences_) vkDestroyFence(device_.get_native(), i, nullptr); if (command_buffers_.empty() == false) vkFreeCommandBuffers(device_.get_native(), command_pool_, static_cast(command_buffers_.size()), command_buffers_.data()); if (command_pool_ != VK_NULL_HANDLE) vkDestroyCommandPool(device_.get_native(), command_pool_, nullptr); for (auto& i : framebuffers_) vkDestroyFramebuffer(device_.get_native(), i, nullptr); if (graphics_pipeline_ != VK_NULL_HANDLE) vkDestroyPipeline(device_.get_native(), graphics_pipeline_, nullptr); if (pipeline_layout_ != VK_NULL_HANDLE) vkDestroyPipelineLayout(device_.get_native(), pipeline_layout_, nullptr); for (size_t i = 0; i < uniform_buffers_.size(); ++i) { vkUnmapMemory(device_.get_native(), uniform_buffers_memory_[i]); vkFreeMemory(device_.get_native(), uniform_buffers_memory_[i], nullptr); vkDestroyBuffer(device_.get_native(), uniform_buffers_[i], nullptr); } uniform_buffers_.clear(); uniform_buffers_memory_.clear(); uniform_buffers_mapped_.clear(); vkDestroyDescriptorPool(device_.get_native(), descriptor_pool_, nullptr); if (ubo_layout_binding_ != VK_NULL_HANDLE) vkDestroyDescriptorSetLayout(device_.get_native(), ubo_layout_binding_, nullptr); if (render_pass_ != VK_NULL_HANDLE) vkDestroyRenderPass(device_.get_native(), render_pass_, nullptr); } void UwURenderEngine::start() { World* world = core_.GetGameInstance()->GetWorld(); std::vector> meshes = world->GetActorsByClass(); for (auto& i : meshes) { std::shared_ptr mesh = i.lock(); mesh->load_model(mesh->GetModelName()); } while (!glfwWindowShouldClose(get_window())) { glfwPollEvents(); draw_frame(); } } void UwURenderEngine::stop_render() const { if (!glfwWindowShouldClose(get_window())) glfwSetWindowShouldClose(get_window(), true); } void UwURenderEngine::SetActiveCamera(const std::weak_ptr& camera) { std::scoped_lock lock(m_active_camera_); active_camera_ = camera; }