diff --git a/shadowmapping/shadowmapping.cpp b/shadowmapping/shadowmapping.cpp index 309006fb..4acd2c5b 100644 --- a/shadowmapping/shadowmapping.cpp +++ b/shadowmapping/shadowmapping.cpp @@ -130,7 +130,7 @@ public: struct OffscreenPass { int32_t width, height; VkFramebuffer frameBuffer; - FrameBufferAttachment color, depth; + FrameBufferAttachment depth; VkRenderPass renderPass; VkSampler depthSampler; VkDescriptorImageInfo descriptor; @@ -156,11 +156,6 @@ public: // Frame buffer vkDestroySampler(device, offscreenPass.depthSampler, nullptr); - // 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); @@ -197,40 +192,24 @@ public: void prepareOffscreenRenderpass() { // todo: no color attachment required - VkAttachmentDescription attDesc[2]; - attDesc[0].format = FB_COLOR_FORMAT; - attDesc[0].samples = VK_SAMPLE_COUNT_1_BIT; - attDesc[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attDesc[0].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // We won't sample from color, so throw away - attDesc[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attDesc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attDesc[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - attDesc[0].flags = VK_FLAGS_NONE; - - attDesc[1].format = DEPTH_FORMAT; - attDesc[1].samples = VK_SAMPLE_COUNT_1_BIT; - attDesc[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attDesc[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // We will read from depth, so it's important to store the depth attachment results - attDesc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attDesc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attDesc[1].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - attDesc[1].flags = VK_FLAGS_NONE; - - VkAttachmentReference colorReference = {}; - colorReference.attachment = 0; - colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkAttachmentDescription attchmentDescription{}; + attchmentDescription.format = DEPTH_FORMAT; + attchmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; + attchmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear depth at beginning of the render pass + attchmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // We will read from depth, so it's important to store the depth attachment results + attchmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attchmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attchmentDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // We don't care about initial layout of the attachment + attchmentDescription.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // Attachment will be transitioned to shader read at render pass end VkAttachmentReference depthReference = {}; - depthReference.attachment = 1; - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depthReference.attachment = 0; + depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Attachment will be used as depth/stencil during render pass VkSubpassDescription subpass = {}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorReference; - subpass.pDepthStencilAttachment = &depthReference; + subpass.colorAttachmentCount = 0; // No color attachments + subpass.pDepthStencilAttachment = &depthReference; // Reference to our depth attachment // Use subpass dependencies for layout transitions std::array dependencies; @@ -240,20 +219,20 @@ public: dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; dependencies[1].srcSubpass = 0; dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; VkRenderPassCreateInfo renderPassCreateInfo = vkTools::initializers::renderPassCreateInfo(); - renderPassCreateInfo.attachmentCount = 2; - renderPassCreateInfo.pAttachments = attDesc; + renderPassCreateInfo.attachmentCount = 1; + renderPassCreateInfo.pAttachments = &attchmentDescription; renderPassCreateInfo.subpassCount = 1; renderPassCreateInfo.pSubpasses = &subpass; renderPassCreateInfo.dependencyCount = static_cast(dependencies.size()); @@ -271,10 +250,9 @@ public: VkFormat fbColorFormat = FB_COLOR_FORMAT; - // Color attachment + // For shadow mapping we only need a depth attachment VkImageCreateInfo image = vkTools::initializers::imageCreateInfo(); image.imageType = VK_IMAGE_TYPE_2D; - image.format = fbColorFormat; image.extent.width = offscreenPass.width; image.extent.height = offscreenPass.height; image.extent.depth = 1; @@ -282,36 +260,17 @@ public: image.arrayLayers = 1; image.samples = VK_SAMPLE_COUNT_1_BIT; image.tiling = VK_IMAGE_TILING_OPTIMAL; - // Image of the framebuffer is blit source - image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + image.format = DEPTH_FORMAT; // Depth stencil attachment + image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; // We will sample directly from the depth attachment for the shadow mapping + VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.depth.image)); VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo(); VkMemoryRequirements memReqs; - - VkImageViewCreateInfo colorImageView = vkTools::initializers::imageViewCreateInfo(); - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = fbColorFormat; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.color.image)); - - vkGetImageMemoryRequirements(device, offscreenPass.color.image, &memReqs); + vkGetImageMemoryRequirements(device, offscreenPass.depth.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)); - - colorImageView.image = offscreenPass.color.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreenPass.color.view)); - - // Depth stencil attachment - image.format = DEPTH_FORMAT; - // We will sample directly from the depth attachment for the shadow mapping - image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.depth.mem)); + VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.mem, 0)); VkImageViewCreateInfo depthStencilView = vkTools::initializers::imageViewCreateInfo(); depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; @@ -322,14 +281,6 @@ public: depthStencilView.subresourceRange.levelCount = 1; depthStencilView.subresourceRange.baseArrayLayer = 0; depthStencilView.subresourceRange.layerCount = 1; - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.depth.image)); - - vkGetImageMemoryRequirements(device, offscreenPass.depth.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.depth.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.mem, 0)); - depthStencilView.image = offscreenPass.depth.image; VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view)); @@ -349,17 +300,13 @@ public: sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &offscreenPass.depthSampler)); - VkImageView attachments[2]; - attachments[0] = offscreenPass.color.view; - attachments[1] = offscreenPass.depth.view; - prepareOffscreenRenderpass(); // Create frame buffer VkFramebufferCreateInfo fbufCreateInfo = vkTools::initializers::framebufferCreateInfo(); fbufCreateInfo.renderPass = offscreenPass.renderPass; - fbufCreateInfo.attachmentCount = 2; - fbufCreateInfo.pAttachments = attachments; + fbufCreateInfo.attachmentCount = 1; + fbufCreateInfo.pAttachments = &offscreenPass.depth.view; fbufCreateInfo.width = offscreenPass.width; fbufCreateInfo.height = offscreenPass.height; fbufCreateInfo.layers = 1; @@ -382,9 +329,8 @@ public: VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; + VkClearValue clearValues[1]; + clearValues[0].depthStencil = { 1.0f, 0 }; VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo(); renderPassBeginInfo.renderPass = offscreenPass.renderPass; @@ -791,6 +737,8 @@ public: // Offscreen pipeline shaderStages[0] = loadShader(getAssetPath() + "shaders/shadowmapping/offscreen.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/shadowmapping/offscreen.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + // No blend attachment states (no color attachments used) + colorBlendState.attachmentCount = 0; // Cull front faces depthStencilState.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; // Enable depth bias