From 8eeb6599d67b05be33bf61139a05a72d2c27d719 Mon Sep 17 00:00:00 2001 From: michead Date: Sat, 28 Nov 2020 11:01:11 +0000 Subject: [PATCH] render depth to cubemap faces directly --- .../shadowmappingomni/shadowmappingomni.cpp | 143 +++++------------- 1 file changed, 36 insertions(+), 107 deletions(-) diff --git a/examples/shadowmappingomni/shadowmappingomni.cpp b/examples/shadowmappingomni/shadowmappingomni.cpp index 02e39531..5535de8c 100644 --- a/examples/shadowmappingomni/shadowmappingomni.cpp +++ b/examples/shadowmappingomni/shadowmappingomni.cpp @@ -72,6 +72,7 @@ public: VkDescriptorSetLayout descriptorSetLayout; vks::Texture shadowCubeMap; + std::array shadowCubeMapFaceImageViews; // Framebuffer for offscreen rendering struct FrameBufferAttachment { @@ -81,8 +82,8 @@ public: }; struct OffscreenPass { int32_t width, height; - VkFramebuffer frameBuffer; - FrameBufferAttachment color, depth; + std::array frameBuffers; + FrameBufferAttachment depth; VkRenderPass renderPass; VkSampler sampler; VkDescriptorImageInfo descriptor; @@ -107,24 +108,25 @@ public: // Note : Inherited destructor cleans up resources stored in base class // Cube map + for (uint32_t i = 0; i < 6; i++) + { + vkDestroyImageView(device, shadowCubeMapFaceImageViews[i], nullptr); + } + vkDestroyImageView(device, shadowCubeMap.view, nullptr); vkDestroyImage(device, shadowCubeMap.image, nullptr); vkDestroySampler(device, shadowCubeMap.sampler, nullptr); vkFreeMemory(device, shadowCubeMap.deviceMemory, nullptr); - // Frame buffer - - // Color attachment - vkDestroyImageView(device, offscreenPass.color.view, nullptr); - vkDestroyImage(device, offscreenPass.color.image, nullptr); - vkFreeMemory(device, offscreenPass.color.mem, nullptr); - // Depth attachment vkDestroyImageView(device, offscreenPass.depth.view, nullptr); vkDestroyImage(device, offscreenPass.depth.image, nullptr); vkFreeMemory(device, offscreenPass.depth.mem, nullptr); - vkDestroyFramebuffer(device, offscreenPass.frameBuffer, nullptr); + for (uint32_t i = 0; i < 6; i++) + { + vkDestroyFramebuffer(device, offscreenPass.frameBuffers[i], nullptr); + } vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); @@ -160,7 +162,7 @@ public: imageCreateInfo.arrayLayers = 6; imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; @@ -221,6 +223,16 @@ public: view.subresourceRange.layerCount = 6; view.image = shadowCubeMap.image; VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &shadowCubeMap.view)); + + view.viewType = VK_IMAGE_VIEW_TYPE_2D; + view.subresourceRange.layerCount = 1; + view.image = shadowCubeMap.image; + + for (uint32_t i = 0; i < 6; i++) + { + view.subresourceRange.baseArrayLayer = i; + VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &shadowCubeMapFaceImageViews[i])); + } } // Prepare a new framebuffer for offscreen rendering @@ -249,8 +261,6 @@ public: imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); - VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; colorImageView.format = fbColorFormat; @@ -262,27 +272,8 @@ public: colorImageView.subresourceRange.baseArrayLayer = 0; colorImageView.subresourceRange.layerCount = 1; - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreenPass.color.image)); - vkGetImageMemoryRequirements(device, offscreenPass.color.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.color.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.color.image, offscreenPass.color.mem, 0)); - VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vks::tools::setImageLayout( - layoutCmd, - offscreenPass.color.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - colorImageView.image = offscreenPass.color.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreenPass.color.view)); - // Depth stencil attachment imageCreateInfo.format = fbDepthFormat; imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; @@ -299,7 +290,11 @@ public: depthStencilView.subresourceRange.layerCount = 1; VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreenPass.depth.image)); + + VkMemoryRequirements memReqs; vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs); + + VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); memAlloc.allocationSize = memReqs.size; memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.depth.mem)); @@ -318,7 +313,6 @@ public: VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view)); VkImageView attachments[2]; - attachments[0] = offscreenPass.color.view; attachments[1] = offscreenPass.depth.view; VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo(); @@ -329,11 +323,15 @@ public: fbufCreateInfo.height = offscreenPass.height; fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreenPass.frameBuffer)); + for (uint32_t i = 0; i < 6; i++) + { + attachments[0] = shadowCubeMapFaceImageViews[i]; + VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreenPass.frameBuffers[i])); + } } // Updates a single cube map face - // Renders the scene with face's view and does a copy from framebuffer to cube face + // Renders the scene with face's view directly to the cubemap layer `faceIndex` // Uses push constants for quick update of view matrix for the current cube map face void updateCubeFace(uint32_t faceIndex, VkCommandBuffer commandBuffer) { @@ -344,7 +342,7 @@ public: VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); // Reuse render pass from example pass renderPassBeginInfo.renderPass = offscreenPass.renderPass; - renderPassBeginInfo.framebuffer = offscreenPass.frameBuffer; + renderPassBeginInfo.framebuffer = offscreenPass.frameBuffers[faceIndex]; renderPassBeginInfo.renderArea.extent.width = offscreenPass.width; renderPassBeginInfo.renderArea.extent.height = offscreenPass.height; renderPassBeginInfo.clearValueCount = 2; @@ -395,73 +393,6 @@ public: models.scene.draw(commandBuffer); vkCmdEndRenderPass(commandBuffer); - // Make sure color writes to the framebuffer are finished before using it as transfer source - vks::tools::setImageLayout( - commandBuffer, - offscreenPass.color.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - - VkImageSubresourceRange cubeFaceSubresourceRange = {}; - cubeFaceSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - cubeFaceSubresourceRange.baseMipLevel = 0; - cubeFaceSubresourceRange.levelCount = 1; - cubeFaceSubresourceRange.baseArrayLayer = faceIndex; - cubeFaceSubresourceRange.layerCount = 1; - - // Change image layout of one cubemap face to transfer destination - vks::tools::setImageLayout( - commandBuffer, - shadowCubeMap.image, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - cubeFaceSubresourceRange); - - // Copy region for transfer from framebuffer to cube face - VkImageCopy copyRegion = {}; - - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.srcSubresource.baseArrayLayer = 0; - copyRegion.srcSubresource.mipLevel = 0; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.srcOffset = { 0, 0, 0 }; - - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.baseArrayLayer = faceIndex; - copyRegion.dstSubresource.mipLevel = 0; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.dstOffset = { 0, 0, 0 }; - - copyRegion.extent.width = shadowCubeMap.width; - copyRegion.extent.height = shadowCubeMap.height; - copyRegion.extent.depth = 1; - - // Put image copy into command buffer - vkCmdCopyImage( - commandBuffer, - offscreenPass.color.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - shadowCubeMap.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - ©Region); - - // Transform framebuffer color attachment back - vks::tools::setImageLayout( - commandBuffer, - offscreenPass.color.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - // Change image layout of copied face to shader read - vks::tools::setImageLayout( - commandBuffer, - shadowCubeMap.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - cubeFaceSubresourceRange); } void buildCommandBuffers() @@ -515,8 +446,6 @@ public: VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - VkDeviceSize offsets[1] = { 0 }; - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, NULL); if (displayCubeMap) @@ -633,8 +562,8 @@ public: osAttachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; osAttachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; osAttachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - osAttachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - osAttachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + osAttachments[0].initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + osAttachments[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // Depth attachment osAttachments[1].format = fbDepthFormat;