Replace renderpass with dynamic rendering (imgui broken)

This commit is contained in:
bailehuni 2024-03-25 17:49:52 +00:00
parent f04c516d2b
commit dcd71d3a14
6 changed files with 175 additions and 174 deletions

View File

@ -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;

View File

@ -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<VkBufferMemoryBarrier2> 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<VkBufferMemoryBarrier2> 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<VkImageMemoryBarrier2, 2> 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<VkClearValue, 2> 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<VkBufferMemoryBarrier2> 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<VkSemaphore> waitSemaphores{};
std::vector<VkPipelineStageFlags> 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);

View File

@ -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<Line>& debug_lines)

View File

@ -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) {

View File

@ -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<VkAttachmentDescription, 2> 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<VkImageView, 2> 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);
}

View File

@ -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<std::pair<VkImage, VkImageView>> swapchainImages{};
std::vector<DepthStencil> depthImages{};
std::vector<VkFramebuffer> framebuffers{};
//std::vector<VkFramebuffer> framebuffers{};
};
struct SwapchainInfo {