render depth to cubemap faces directly
This commit is contained in:
parent
b9f0ac91d2
commit
8eeb6599d6
1 changed files with 36 additions and 107 deletions
|
|
@ -72,6 +72,7 @@ public:
|
||||||
VkDescriptorSetLayout descriptorSetLayout;
|
VkDescriptorSetLayout descriptorSetLayout;
|
||||||
|
|
||||||
vks::Texture shadowCubeMap;
|
vks::Texture shadowCubeMap;
|
||||||
|
std::array<VkImageView, 6> shadowCubeMapFaceImageViews;
|
||||||
|
|
||||||
// Framebuffer for offscreen rendering
|
// Framebuffer for offscreen rendering
|
||||||
struct FrameBufferAttachment {
|
struct FrameBufferAttachment {
|
||||||
|
|
@ -81,8 +82,8 @@ public:
|
||||||
};
|
};
|
||||||
struct OffscreenPass {
|
struct OffscreenPass {
|
||||||
int32_t width, height;
|
int32_t width, height;
|
||||||
VkFramebuffer frameBuffer;
|
std::array<VkFramebuffer, 6> frameBuffers;
|
||||||
FrameBufferAttachment color, depth;
|
FrameBufferAttachment depth;
|
||||||
VkRenderPass renderPass;
|
VkRenderPass renderPass;
|
||||||
VkSampler sampler;
|
VkSampler sampler;
|
||||||
VkDescriptorImageInfo descriptor;
|
VkDescriptorImageInfo descriptor;
|
||||||
|
|
@ -107,24 +108,25 @@ public:
|
||||||
// Note : Inherited destructor cleans up resources stored in base class
|
// Note : Inherited destructor cleans up resources stored in base class
|
||||||
|
|
||||||
// Cube map
|
// Cube map
|
||||||
|
for (uint32_t i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
vkDestroyImageView(device, shadowCubeMapFaceImageViews[i], nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
vkDestroyImageView(device, shadowCubeMap.view, nullptr);
|
vkDestroyImageView(device, shadowCubeMap.view, nullptr);
|
||||||
vkDestroyImage(device, shadowCubeMap.image, nullptr);
|
vkDestroyImage(device, shadowCubeMap.image, nullptr);
|
||||||
vkDestroySampler(device, shadowCubeMap.sampler, nullptr);
|
vkDestroySampler(device, shadowCubeMap.sampler, nullptr);
|
||||||
vkFreeMemory(device, shadowCubeMap.deviceMemory, 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
|
// Depth attachment
|
||||||
vkDestroyImageView(device, offscreenPass.depth.view, nullptr);
|
vkDestroyImageView(device, offscreenPass.depth.view, nullptr);
|
||||||
vkDestroyImage(device, offscreenPass.depth.image, nullptr);
|
vkDestroyImage(device, offscreenPass.depth.image, nullptr);
|
||||||
vkFreeMemory(device, offscreenPass.depth.mem, 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);
|
vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr);
|
||||||
|
|
||||||
|
|
@ -160,7 +162,7 @@ public:
|
||||||
imageCreateInfo.arrayLayers = 6;
|
imageCreateInfo.arrayLayers = 6;
|
||||||
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
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.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
||||||
|
|
@ -221,6 +223,16 @@ public:
|
||||||
view.subresourceRange.layerCount = 6;
|
view.subresourceRange.layerCount = 6;
|
||||||
view.image = shadowCubeMap.image;
|
view.image = shadowCubeMap.image;
|
||||||
VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &shadowCubeMap.view));
|
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
|
// 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.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
|
||||||
VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo();
|
|
||||||
|
|
||||||
VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo();
|
VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo();
|
||||||
colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
colorImageView.format = fbColorFormat;
|
colorImageView.format = fbColorFormat;
|
||||||
|
|
@ -262,27 +272,8 @@ public:
|
||||||
colorImageView.subresourceRange.baseArrayLayer = 0;
|
colorImageView.subresourceRange.baseArrayLayer = 0;
|
||||||
colorImageView.subresourceRange.layerCount = 1;
|
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);
|
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
|
// Depth stencil attachment
|
||||||
imageCreateInfo.format = fbDepthFormat;
|
imageCreateInfo.format = fbDepthFormat;
|
||||||
imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
|
|
@ -299,7 +290,11 @@ public:
|
||||||
depthStencilView.subresourceRange.layerCount = 1;
|
depthStencilView.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreenPass.depth.image));
|
VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreenPass.depth.image));
|
||||||
|
|
||||||
|
VkMemoryRequirements memReqs;
|
||||||
vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs);
|
vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs);
|
||||||
|
|
||||||
|
VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo();
|
||||||
memAlloc.allocationSize = memReqs.size;
|
memAlloc.allocationSize = memReqs.size;
|
||||||
memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
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(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.depth.mem));
|
||||||
|
|
@ -318,7 +313,6 @@ public:
|
||||||
VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view));
|
VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view));
|
||||||
|
|
||||||
VkImageView attachments[2];
|
VkImageView attachments[2];
|
||||||
attachments[0] = offscreenPass.color.view;
|
|
||||||
attachments[1] = offscreenPass.depth.view;
|
attachments[1] = offscreenPass.depth.view;
|
||||||
|
|
||||||
VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo();
|
VkFramebufferCreateInfo fbufCreateInfo = vks::initializers::framebufferCreateInfo();
|
||||||
|
|
@ -329,11 +323,15 @@ public:
|
||||||
fbufCreateInfo.height = offscreenPass.height;
|
fbufCreateInfo.height = offscreenPass.height;
|
||||||
fbufCreateInfo.layers = 1;
|
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
|
// 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
|
// Uses push constants for quick update of view matrix for the current cube map face
|
||||||
void updateCubeFace(uint32_t faceIndex, VkCommandBuffer commandBuffer)
|
void updateCubeFace(uint32_t faceIndex, VkCommandBuffer commandBuffer)
|
||||||
{
|
{
|
||||||
|
|
@ -344,7 +342,7 @@ public:
|
||||||
VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo();
|
VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo();
|
||||||
// Reuse render pass from example pass
|
// Reuse render pass from example pass
|
||||||
renderPassBeginInfo.renderPass = offscreenPass.renderPass;
|
renderPassBeginInfo.renderPass = offscreenPass.renderPass;
|
||||||
renderPassBeginInfo.framebuffer = offscreenPass.frameBuffer;
|
renderPassBeginInfo.framebuffer = offscreenPass.frameBuffers[faceIndex];
|
||||||
renderPassBeginInfo.renderArea.extent.width = offscreenPass.width;
|
renderPassBeginInfo.renderArea.extent.width = offscreenPass.width;
|
||||||
renderPassBeginInfo.renderArea.extent.height = offscreenPass.height;
|
renderPassBeginInfo.renderArea.extent.height = offscreenPass.height;
|
||||||
renderPassBeginInfo.clearValueCount = 2;
|
renderPassBeginInfo.clearValueCount = 2;
|
||||||
|
|
@ -395,73 +393,6 @@ public:
|
||||||
models.scene.draw(commandBuffer);
|
models.scene.draw(commandBuffer);
|
||||||
|
|
||||||
vkCmdEndRenderPass(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()
|
void buildCommandBuffers()
|
||||||
|
|
@ -515,8 +446,6 @@ public:
|
||||||
VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
|
VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
|
||||||
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
|
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);
|
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, NULL);
|
||||||
|
|
||||||
if (displayCubeMap)
|
if (displayCubeMap)
|
||||||
|
|
@ -633,8 +562,8 @@ public:
|
||||||
osAttachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
osAttachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
osAttachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
osAttachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
osAttachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
osAttachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
osAttachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
osAttachments[0].initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
osAttachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
osAttachments[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
|
||||||
// Depth attachment
|
// Depth attachment
|
||||||
osAttachments[1].format = fbDepthFormat;
|
osAttachments[1].format = fbDepthFormat;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue