diff --git a/src/application.cpp b/src/application.cpp index c688a33..cefd282 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -224,9 +224,9 @@ void Application::GameLoop() debug_menu_state.show_info_window = !debug_menu_state.show_info_window; } - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplSDL2_NewFrame(); - ImGui::NewFrame(); + //ImGui_ImplVulkan_NewFrame(); + //ImGui_ImplSDL2_NewFrame(); + //ImGui::NewFrame(); if (debug_menu_state.menu_active) { if (ImGui::Begin("debugMenu", 0)) { @@ -269,7 +269,7 @@ void Application::GameLoop() ImGui::End(); } - ImGui::Render(); + //ImGui::Render(); const RenderList* static_list = nullptr; const RenderList* dynamic_list = nullptr; diff --git a/src/gfx_device_vulkan.cpp b/src/gfx_device_vulkan.cpp index d8cf1cd..cd082c9 100644 --- a/src/gfx_device_vulkan.cpp +++ b/src/gfx_device_vulkan.cpp @@ -424,39 +424,42 @@ GFXDevice::GFXDevice(const char* appName, const char* appVersion, SDL_Window* wi deviceRequirements.optionalExtensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); deviceRequirements.requiredFeatures.samplerAnisotropy = VK_TRUE; // deviceRequirements.requiredFeatures.fillModeNonSolid = VK_TRUE; + // extension feature memoryPriority is enabled if extension is specified above + // synchronization2 is always required as it's part of Vulkan 1.3 + // dynamic_rendering is always required as it's part of Vulkan 1.3 deviceRequirements.formats.push_back( - FormatRequirements{.format = VK_FORMAT_R8G8B8A8_SRGB, + FormatRequirements{.format = VK_FORMAT_R8G8B8A8_SRGB, // 2D textures and cubemaps .properties = VkFormatProperties{ .linearTilingFeatures = {}, .optimalTilingFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT, .bufferFeatures = {}, }}); - deviceRequirements.formats.push_back(FormatRequirements{.format = VK_FORMAT_R32G32_SFLOAT, + deviceRequirements.formats.push_back(FormatRequirements{.format = VK_FORMAT_R32G32_SFLOAT, // vec2 vertex attribute .properties = VkFormatProperties{ .linearTilingFeatures = {}, .optimalTilingFeatures = {}, .bufferFeatures = VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT, }}); - deviceRequirements.formats.push_back(FormatRequirements{.format = VK_FORMAT_R32G32B32_SFLOAT, + deviceRequirements.formats.push_back(FormatRequirements{.format = VK_FORMAT_R32G32B32_SFLOAT, // vec3 vertex attribute .properties = VkFormatProperties{ .linearTilingFeatures = {}, .optimalTilingFeatures = {}, .bufferFeatures = VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT, }}); - deviceRequirements.formats.push_back(FormatRequirements{.format = VK_FORMAT_R32G32B32A32_SFLOAT, + deviceRequirements.formats.push_back(FormatRequirements{.format = VK_FORMAT_R32G32B32A32_SFLOAT, // vec4 vertex attribute .properties = VkFormatProperties{ .linearTilingFeatures = {}, .optimalTilingFeatures = {}, .bufferFeatures = VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT, }}); - deviceRequirements.formats.push_back( // Depth buffer format - FormatRequirements{.format = VK_FORMAT_D16_UNORM, - .properties = VkFormatProperties{ - .linearTilingFeatures = {}, - .optimalTilingFeatures = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, - .bufferFeatures = {}, - }}); + deviceRequirements.formats.push_back(FormatRequirements{.format = VK_FORMAT_D16_UNORM, // depth buffer format + .properties = VkFormatProperties{ + .linearTilingFeatures = {}, + .optimalTilingFeatures = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, + .bufferFeatures = {}, + }}); + // the surface format is found later in createSwapchain(); pimpl->device = createDevice(pimpl->instance.instance, deviceRequirements, pimpl->surface); @@ -572,6 +575,8 @@ void GFXDevice::GetViewportSize(uint32_t* w, uint32_t* h) void GFXDevice::SetupImguiBackend() { + // disable imgui for now +#if 0 ImGui_ImplVulkan_InitInfo initInfo{}; initInfo.Instance = pimpl->instance.instance; initInfo.PhysicalDevice = pimpl->device.physicalDevice; @@ -621,13 +626,23 @@ void GFXDevice::SetupImguiBackend() vkFreeCommandBuffers(pimpl->device.device, pimpl->graphicsCommandPool, 1, &commandBuffer); ImGui_ImplVulkan_DestroyFontUploadObjects(); +#endif } -void GFXDevice::ShutdownImguiBackend() { ImGui_ImplVulkan_Shutdown(); } +void GFXDevice::ShutdownImguiBackend() +{ + // disable imgui for now +#if 0 + ImGui_ImplVulkan_Shutdown(); +#endif +} void GFXDevice::CmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData* draw_data) { + // disable imgui rendering for now +#if 0 ImGui_ImplVulkan_RenderDrawData(draw_data, draw_buffer->frameData.drawBuf); +#endif } gfx::DrawBuffer* GFXDevice::BeginRender() @@ -640,14 +655,15 @@ gfx::DrawBuffer* GFXDevice::BeginRender() vmaSetCurrentFrameIndex(pimpl->allocator, (uint32_t)pimpl->FRAMECOUNT); /* wait until the previous frame RENDERING has finished */ + // this allows for images acquired by vkAcquireNextImageKHR to be used immediately res = vkWaitForFences(pimpl->device.device, 1, &frameData.renderFence, VK_TRUE, 1000000000LL); VKCHECK(res); res = vkResetFences(pimpl->device.device, 1, &frameData.renderFence); VKCHECK(res); /* perform any pending uniform buffer writes */ - VKCHECK(vkResetCommandPool(pimpl->device.device, frameData.transferPool, 0)); // TODO: possibly delete this + VKCHECK(vkResetCommandPool(pimpl->device.device, frameData.transferPool, 0)); VkCommandBufferBeginInfo transferBeginInfo{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .pNext = nullptr, @@ -658,28 +674,7 @@ gfx::DrawBuffer* GFXDevice::BeginRender() // transfer cmds... - if (pimpl->FRAMECOUNT >= FRAMES_IN_FLIGHT) { // cannot (and don't need to) do ownership transfer on first frame[s] - // acquire ownership of buffers - std::vector acquireBarriers{}; - for (gfx::UniformBuffer* uniformBuffer : pimpl->write_queues[currentFrameIndex].uniform_buffer_writes) { - VkBufferMemoryBarrier2& barrier = acquireBarriers.emplace_back(); - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2; - barrier.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT; - barrier.srcAccessMask = 0; - barrier.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT; - barrier.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; - barrier.srcQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; - barrier.dstQueueFamilyIndex = pimpl->device.queues.transferQueueFamily; - barrier.buffer = uniformBuffer->gpuBuffers[currentFrameIndex].buffer; - barrier.offset = 0; - barrier.size = uniformBuffer->gpuBuffers[currentFrameIndex].size; - } - VkDependencyInfo dependencyInfo{}; - dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; - dependencyInfo.bufferMemoryBarrierCount = (uint32_t)acquireBarriers.size(); - dependencyInfo.pBufferMemoryBarriers = acquireBarriers.data(); - vkCmdPipelineBarrier2(frameData.transferBuf, &dependencyInfo); - } + // ownership transfer isn't needed since the data isn't accessed it's just overwritten { // copy stagings buffers to GPU buffer @@ -759,9 +754,9 @@ gfx::DrawBuffer* GFXDevice::BeginRender() res = vkBeginCommandBuffer(frameData.drawBuf, &beginInfo); VKCHECK(res); - { // RECORDING + { // RECORDING, this is executed after the uniform write semaphore is signalled - // acquire ownership of buffers + // acquire ownership of uniform buffers std::vector acquireBarriers{}; for (gfx::UniformBuffer* uniformBuffer : pimpl->write_queues[currentFrameIndex].uniform_buffer_writes) { VkBufferMemoryBarrier2& barrier = acquireBarriers.emplace_back(); @@ -782,6 +777,51 @@ gfx::DrawBuffer* GFXDevice::BeginRender() dependencyInfo.pBufferMemoryBarriers = acquireBarriers.data(); vkCmdPipelineBarrier2(frameData.drawBuf, &dependencyInfo); + VkImageMemoryBarrier2 colorImageBarrier{}; + colorImageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; + colorImageBarrier.pNext = nullptr; + colorImageBarrier.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; + colorImageBarrier.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; + colorImageBarrier.srcAccessMask = 0; + colorImageBarrier.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT; + colorImageBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorImageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + colorImageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + colorImageBarrier.image = pimpl->swapchain.swapchainImages[swapchainImageIndex].first; + VkImageSubresourceRange colorImageRange{}; + colorImageRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + colorImageRange.baseMipLevel = 0; + colorImageRange.levelCount = 1; + colorImageRange.baseArrayLayer = 0; + colorImageRange.layerCount = 1; + colorImageBarrier.subresourceRange = colorImageRange; + + VkImageMemoryBarrier2 depthImageBarrier{}; + depthImageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; + depthImageBarrier.pNext = nullptr; + depthImageBarrier.srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT; + depthImageBarrier.dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT; + depthImageBarrier.srcAccessMask = 0; + depthImageBarrier.dstAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + depthImageBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depthImageBarrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depthImageBarrier.image = pimpl->swapchain.depthImages[swapchainImageIndex].image; + VkImageSubresourceRange depthImageRange{}; + depthImageRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + depthImageRange.baseMipLevel = 0; + depthImageRange.levelCount = 1; + depthImageRange.baseArrayLayer = 0; + depthImageRange.layerCount = 1; + depthImageBarrier.subresourceRange = depthImageRange; + + std::array imageBarriers{colorImageBarrier, depthImageBarrier}; + VkDependencyInfo imageDependencyInfo{}; + imageDependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; + imageDependencyInfo.imageMemoryBarrierCount = imageBarriers.size(); + imageDependencyInfo.pImageMemoryBarriers = imageBarriers.data(); + vkCmdPipelineBarrier2(frameData.drawBuf, &imageDependencyInfo); + std::array clearValues{}; // Using same value for all components enables // compression according to NVIDIA Best Practices clearValues[0].color.float32[0] = 1.0f; @@ -790,16 +830,37 @@ gfx::DrawBuffer* GFXDevice::BeginRender() clearValues[0].color.float32[3] = 1.0f; clearValues[1].depthStencil.depth = 1.0f; - VkRenderPassBeginInfo passBegin{}; - passBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - passBegin.pNext = nullptr; - passBegin.renderPass = pimpl->swapchain.renderpass; - passBegin.framebuffer = pimpl->swapchain.framebuffers[swapchainImageIndex]; - passBegin.renderArea.extent = pimpl->swapchain.extent; - passBegin.renderArea.offset = {0, 0}; - passBegin.clearValueCount = (uint32_t)clearValues.size(); - passBegin.pClearValues = clearValues.data(); - vkCmdBeginRenderPass(frameData.drawBuf, &passBegin, VK_SUBPASS_CONTENTS_INLINE); + VkRenderingAttachmentInfo colorAttachment{}; + colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; + colorAttachment.pNext = nullptr; + colorAttachment.imageView = pimpl->swapchain.swapchainImages[swapchainImageIndex].second; + colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorAttachment.resolveMode = VK_RESOLVE_MODE_NONE; + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachment.clearValue = clearValues[0]; + VkRenderingAttachmentInfo depthAttachment{}; + depthAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; + depthAttachment.pNext = nullptr; + depthAttachment.imageView = pimpl->swapchain.depthImages[swapchainImageIndex].view; + depthAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depthAttachment.resolveMode = VK_RESOLVE_MODE_NONE; + depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depthAttachment.clearValue = clearValues[1]; + + VkRenderingInfo renderingInfo{}; + renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + renderingInfo.pNext = nullptr; + renderingInfo.flags = 0; + renderingInfo.renderArea = VkRect2D{VkOffset2D{0, 0}, VkExtent2D{pimpl->swapchain.extent.width, pimpl->swapchain.extent.height}}; + renderingInfo.layerCount = 1; + renderingInfo.viewMask = 0; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachments = &colorAttachment; + renderingInfo.pDepthAttachment = &depthAttachment; + renderingInfo.pStencilAttachment = nullptr; + vkCmdBeginRendering(frameData.drawBuf, &renderingInfo); VkViewport viewport{}; if (flip_viewport) { @@ -824,6 +885,9 @@ gfx::DrawBuffer* GFXDevice::BeginRender() vkCmdSetScissor(frameData.drawBuf, 0, 1, &scissor); } + // clear write queue + pimpl->write_queues[currentFrameIndex].uniform_buffer_writes.clear(); + // hand command buffer over to caller gfx::DrawBuffer* drawBuffer = new gfx::DrawBuffer; drawBuffer->frameData = frameData; @@ -839,8 +903,9 @@ void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer) uint32_t swapchainImageIndex = drawBuffer->imageIndex; VkResult res; - vkCmdEndRenderPass(drawBuffer->frameData.drawBuf); + vkCmdEndRendering(drawBuffer->frameData.drawBuf); +#if 0 // transfer ownership of uniform buffers back to transfer queue std::vector releaseBarriers{}; for (gfx::UniformBuffer* uniformBuffer : pimpl->write_queues[drawBuffer->currentFrameIndex].uniform_buffer_writes) { @@ -861,6 +926,35 @@ void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer) dependencyInfo.bufferMemoryBarrierCount = (uint32_t)releaseBarriers.size(); dependencyInfo.pBufferMemoryBarriers = releaseBarriers.data(); vkCmdPipelineBarrier2(drawBuffer->frameData.drawBuf, &dependencyInfo); +#endif + + // Make color attachment presentable. + // The present and draw queues are part of the same family so no ownership transfer needed + VkImageMemoryBarrier2 colorImageBarrier{}; + colorImageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; + colorImageBarrier.pNext = nullptr; + colorImageBarrier.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; + colorImageBarrier.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; // semaphore takes care of this + colorImageBarrier.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT; + colorImageBarrier.dstAccessMask = 0; + colorImageBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + colorImageBarrier.srcQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; + colorImageBarrier.dstQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; + colorImageBarrier.image = pimpl->swapchain.swapchainImages[swapchainImageIndex].first; + VkImageSubresourceRange colorImageRange{}; + colorImageRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + colorImageRange.baseMipLevel = 0; + colorImageRange.levelCount = 1; + colorImageRange.baseArrayLayer = 0; + colorImageRange.layerCount = 1; + colorImageBarrier.subresourceRange = colorImageRange; + + VkDependencyInfo imageDependencyInfo{}; + imageDependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; + imageDependencyInfo.imageMemoryBarrierCount = 1; + imageDependencyInfo.pImageMemoryBarriers = &colorImageBarrier; + vkCmdPipelineBarrier2(drawBuffer->frameData.drawBuf, &imageDependencyInfo); res = vkEndCommandBuffer(drawBuffer->frameData.drawBuf); VKCHECK(res); @@ -870,9 +964,9 @@ void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer) std::vector waitSemaphores{}; std::vector waitDstStageMasks{}; - waitSemaphores.push_back(drawBuffer->frameData.presentSemaphore); + waitSemaphores.push_back(drawBuffer->frameData.presentSemaphore); // wait for image from 2nd last frame to be presented so it can be rendered to again waitDstStageMasks.push_back(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - waitSemaphores.push_back(drawBuffer->frameData.transferSemaphore); + waitSemaphores.push_back(drawBuffer->frameData.transferSemaphore); // wait for uniform buffer copies to complete waitDstStageMasks.push_back(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); VkSubmitInfo submitInfo{ @@ -907,9 +1001,6 @@ void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer) else if (res != VK_SUCCESS) throw std::runtime_error("Failed to queue present! Code: " + std::to_string(res)); - // clear write queue - pimpl->write_queues[drawBuffer->currentFrameIndex].uniform_buffer_writes.clear(); - pimpl->FRAMECOUNT++; delete drawBuffer; @@ -1162,11 +1253,19 @@ gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info) createInfo.pColorBlendState = &colorBlending; createInfo.pDynamicState = &dynamicState; createInfo.layout = pipeline->layout; - createInfo.renderPass = pimpl->swapchain.renderpass; + createInfo.renderPass = VK_NULL_HANDLE; createInfo.subpass = 0; createInfo.basePipelineHandle = VK_NULL_HANDLE; createInfo.basePipelineIndex = -1; + VkPipelineRenderingCreateInfo renderingInfo{}; + renderingInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachmentFormats = &pimpl->swapchain.surfaceFormat.format; + renderingInfo.depthAttachmentFormat = pimpl->swapchain.depthStencilFormat; + + createInfo.pNext = &renderingInfo; + res = vkCreateGraphicsPipelines(pimpl->device.device, VK_NULL_HANDLE, 1, &createInfo, nullptr, &pipeline->handle); assert(res == VK_SUCCESS); diff --git a/src/renderer.cpp b/src/renderer.cpp index 7324d27..28d8401 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -250,10 +250,10 @@ void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform) device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data); // override with light matrix - frame_uniform.uniform_buffer_data.data = glm::mat4{1.0f}; - device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data); - global_uniform.uniform_buffer_data.data.proj = global_uniform.uniform_buffer_data.data.lightSpaceMatrix; - device_->WriteUniformBuffer(global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data); + //frame_uniform.uniform_buffer_data.data = glm::mat4{1.0f}; + //device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data); + //global_uniform.uniform_buffer_data.data.proj = global_uniform.uniform_buffer_data.data.lightSpaceMatrix; + //device_->WriteUniformBuffer(global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data); } void Renderer::Render(const RenderList* static_list, const RenderList* dynamic_list, const std::vector& debug_lines) diff --git a/src/vulkan/device.cpp b/src/vulkan/device.cpp index 6f17959..254cf52 100644 --- a/src/vulkan/device.cpp +++ b/src/vulkan/device.cpp @@ -75,8 +75,11 @@ Device createDevice(VkInstance instance, const DeviceRequirements& requirements, } /* check features */ + VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeatures{}; + dynamicRenderingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES; VkPhysicalDeviceMemoryPriorityFeaturesEXT memoryPriorityFeatures{}; memoryPriorityFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT; + memoryPriorityFeatures.pNext = &dynamicRenderingFeatures; VkPhysicalDeviceSynchronization2Features synchronization2Features{}; synchronization2Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES; synchronization2Features.pNext = &memoryPriorityFeatures; @@ -199,6 +202,9 @@ Device createDevice(VkInstance instance, const DeviceRequirements& requirements, /* ensure synchronization 2 is found */ if (synchronization2Features.synchronization2 == VK_FALSE) continue; + /* ensure dynamic_rendering is found */ + if (dynamicRenderingFeatures.dynamicRendering == VK_FALSE) continue; + /* check the memory priority extension was even requested */ bool memoryPriorityRequired = false; for (const char* ext : requirements.requiredExtensions) { @@ -341,8 +347,12 @@ Device createDevice(VkInstance instance, const DeviceRequirements& requirements, } /* set enabled features */ + VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeatures{}; + dynamicRenderingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES; + dynamicRenderingFeatures.dynamicRendering = VK_TRUE; VkPhysicalDeviceMemoryPriorityFeaturesEXT memoryPriorityFeatures{}; memoryPriorityFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT; + memoryPriorityFeatures.pNext = &dynamicRenderingFeatures; memoryPriorityFeatures.memoryPriority = d.memoryPriorityFeature ? VK_TRUE : VK_FALSE; VkPhysicalDeviceSynchronization2Features synchronization2Features{}; synchronization2Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES; @@ -391,6 +401,7 @@ Device createDevice(VkInstance instance, const DeviceRequirements& requirements, d.enabledExtensions.emplace_back(ext); } + // wtf is going on here?? if (transferFamily != graphicsFamily) { vkGetDeviceQueue(d.device, graphicsFamily, 0, &d.queues.presentQueue); if (queueFamilies[graphicsFamily].queueCount >= 2) { diff --git a/src/vulkan/swapchain.cpp b/src/vulkan/swapchain.cpp index 058de90..06ff960 100644 --- a/src/vulkan/swapchain.cpp +++ b/src/vulkan/swapchain.cpp @@ -149,89 +149,6 @@ namespace engine { vkDestroySwapchainKHR(info.device, scInfo.oldSwapchain, nullptr); } - /* create the render pass */ - if (sc->renderpass != VK_NULL_HANDLE) { - vkDestroyRenderPass(sc->device, sc->renderpass, nullptr); - } - VkAttachmentDescription colorAttachment{ - .flags = 0, - .format = sc->surfaceFormat.format, - .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, // ignored - .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, // ignored - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR - }; - VkAttachmentDescription depthStencilAttachment{ - .flags = 0, - .format = sc->depthStencilFormat, - .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, - .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, // the depth buffer is not used after the fragment shader - .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, // ignored - .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, // ignored - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL - }; - std::array attachments { colorAttachment, depthStencilAttachment }; - VkAttachmentReference colorAttachmentRef{ - .attachment = 0, - .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - }; - VkAttachmentReference depthStencilAttachmentRef{ - .attachment = 1, - .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL - }; - VkSubpassDescription subpass{ - .flags = 0, - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .inputAttachmentCount = 0, - .pInputAttachments = nullptr, - .colorAttachmentCount = 1, - .pColorAttachments = &colorAttachmentRef, - .pResolveAttachments = nullptr, - .pDepthStencilAttachment = &depthStencilAttachmentRef, - .preserveAttachmentCount = 0, - .pPreserveAttachments = nullptr, - }; - VkSubpassDependency attachmentDependencies[2] = { - { - // Depth buffer - .srcSubpass = VK_SUBPASS_EXTERNAL, - .dstSubpass = 0, - .srcStageMask = VK_PIPELINE_STAGE_NONE, - .dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - .dependencyFlags = 0, - }, - { - // Image Layout Transition - .srcSubpass = VK_SUBPASS_EXTERNAL, - .dstSubpass = 0, - .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - .dependencyFlags = 0, - }, - }; - VkRenderPassCreateInfo renderPassInfo{ - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .attachmentCount = (uint32_t)attachments.size(), - .pAttachments = attachments.data(), - .subpassCount = 1, - .pSubpasses = &subpass, - .dependencyCount = 2, - .pDependencies = attachmentDependencies, - }; - res = vkCreateRenderPass(sc->device, &renderPassInfo, nullptr, &sc->renderpass); - if (res != EXIT_SUCCESS) throw std::runtime_error("Failed to create renderpass!"); - // get all the image handles uint32_t swapchainImageCount = 0; res = vkGetSwapchainImagesKHR(info.device, sc->swapchain, &swapchainImageCount, nullptr); @@ -240,23 +157,20 @@ namespace engine { res = vkGetSwapchainImagesKHR(info.device, sc->swapchain, &swapchainImageCount, swapchainImages.data()); assert(res == VK_SUCCESS); - /* create image view and framebuffer for each image */ + /* create image view for each image */ if (sc->swapchainImages.size() == 0) { sc->swapchainImages.resize(swapchainImageCount); sc->depthImages.resize(swapchainImageCount); - sc->framebuffers.resize(swapchainImageCount); } for (uint32_t i = 0; i < swapchainImageCount; i++) { auto& [swapchainImage, swapchainImageView] = sc->swapchainImages.at(i); auto& [depthImage, depthAllocation, depthImageView] = sc->depthImages.at(i); - auto& framebuffer = sc->framebuffers.at(i); if (swapchainImageView != VK_NULL_HANDLE) vkDestroyImageView(sc->device, swapchainImageView, nullptr); if (depthImageView != VK_NULL_HANDLE) { vkDestroyImageView(sc->device, depthImageView, nullptr); vmaDestroyImage(sc->allocator, depthImage, depthAllocation); } - if (framebuffer != VK_NULL_HANDLE) vkDestroyFramebuffer(sc->device, framebuffer, nullptr); swapchainImage = swapchainImages[i]; @@ -333,33 +247,12 @@ namespace engine { res = vkCreateImageView(info.device, &depthViewInfo, nullptr, &depthImageView); assert(res == VK_SUCCESS); - std::array attachments { - swapchainImageView, depthImageView - }; - - VkFramebufferCreateInfo fbInfo{}; - fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fbInfo.pNext = nullptr; - fbInfo.flags = 0; - fbInfo.renderPass = sc->renderpass; - fbInfo.attachmentCount = (uint32_t)attachments.size(); - fbInfo.pAttachments = attachments.data(); - fbInfo.width = sc->extent.width; - fbInfo.height = sc->extent.height; - fbInfo.layers = 1; - - res = vkCreateFramebuffer(sc->device, &fbInfo, nullptr, &framebuffer); - if (res != VK_SUCCESS) throw std::runtime_error("Failed to create framebuffer for swapchain image!"); - } } void destroySwapchain(const Swapchain& sc) { - for (VkFramebuffer framebuffer : sc.framebuffers) { - vkDestroyFramebuffer(sc.device, framebuffer, nullptr); - } for (const auto& [image, view] : sc.swapchainImages) { vkDestroyImageView(sc.device, view, nullptr); } @@ -367,8 +260,6 @@ namespace engine { vkDestroyImageView(sc.device, view, nullptr); vmaDestroyImage(sc.allocator, image, allocation); } - - vkDestroyRenderPass(sc.device, sc.renderpass, nullptr); vkDestroySwapchainKHR(sc.device, sc.swapchain, nullptr); } diff --git a/src/vulkan/swapchain.h b/src/vulkan/swapchain.h index 7b7c983..908edd6 100644 --- a/src/vulkan/swapchain.h +++ b/src/vulkan/swapchain.h @@ -25,11 +25,11 @@ namespace engine { VkSurfaceCapabilitiesKHR surfaceCapabilities{}; VkPresentModeKHR presentMode{}; VkExtent2D extent{}; - VkRenderPass renderpass = VK_NULL_HANDLE; + //VkRenderPass renderpass = VK_NULL_HANDLE; VkFormat depthStencilFormat; std::vector> swapchainImages{}; std::vector depthImages{}; - std::vector framebuffers{}; + //std::vector framebuffers{}; }; struct SwapchainInfo {