Use offscreen render pass, refactoring and cleanup

This commit is contained in:
saschawillems 2016-08-13 20:35:22 +02:00
parent a84d5421fe
commit 5a049bb3fb
3 changed files with 84 additions and 88 deletions

View file

@ -116,7 +116,6 @@ public:
VkSemaphore semaphore = VK_NULL_HANDLE; VkSemaphore semaphore = VK_NULL_HANDLE;
} offscreenPass; } offscreenPass;
glm::vec3 meshPos = glm::vec3(0.0f, -1.5f, 0.0f); glm::vec3 meshPos = glm::vec3(0.0f, -1.5f, 0.0f);
glm::vec3 meshRot = glm::vec3(0.0f); glm::vec3 meshRot = glm::vec3(0.0f);

View file

@ -191,7 +191,6 @@ public:
// This is necessary as the offscreen frame buffer attachments use formats different to those from the example render pass // This is necessary as the offscreen frame buffer attachments use formats different to those from the example render pass
void prepareOffscreenRenderpass() void prepareOffscreenRenderpass()
{ {
// todo: no color attachment required
VkAttachmentDescription attchmentDescription{}; VkAttachmentDescription attchmentDescription{};
attchmentDescription.format = DEPTH_FORMAT; attchmentDescription.format = DEPTH_FORMAT;
attchmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; attchmentDescription.samples = VK_SAMPLE_COUNT_1_BIT;
@ -432,7 +431,7 @@ public:
} }
} }
void loadMeshes() void loadAssets()
{ {
loadMesh(getAssetPath() + "models/vulkanscene_shadow.dae", &meshes.scene, vertexLayout, 4.0f); loadMesh(getAssetPath() + "models/vulkanscene_shadow.dae", &meshes.scene, vertexLayout, 4.0f);
} }
@ -892,8 +891,8 @@ public:
void prepare() void prepare()
{ {
VulkanExampleBase::prepare(); VulkanExampleBase::prepare();
loadAssets();
generateQuad(); generateQuad();
loadMeshes();
prepareOffscreenFramebuffer(); prepareOffscreenFramebuffer();
setupVertexDescriptions(); setupVertexDescriptions();
prepareUniformBuffers(); prepareUniformBuffers();

View file

@ -111,19 +111,20 @@ public:
VkDeviceMemory mem; VkDeviceMemory mem;
VkImageView view; VkImageView view;
}; };
struct FrameBuffer { struct OffscreenPass {
int32_t width, height; int32_t width, height;
VkFramebuffer frameBuffer; VkFramebuffer frameBuffer;
FrameBufferAttachment color, depth; FrameBufferAttachment color, depth;
VkRenderPass renderPass; VkRenderPass renderPass;
} offScreenFrameBuf; VkSampler sampler;
VkDescriptorImageInfo descriptor;
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
// Semaphore used to synchronize between offscreen and final scene render pass
VkSemaphore semaphore = VK_NULL_HANDLE;
} offscreenPass;
VkCommandBuffer offScreenCmdBuffer = VK_NULL_HANDLE;
VkFormat fbDepthFormat; VkFormat fbDepthFormat;
// Semaphore used to synchronize offscreen rendering before using it's texture target for sampling
VkSemaphore offscreenSemaphore = VK_NULL_HANDLE;
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
{ {
zoom = -175.0f; zoom = -175.0f;
@ -148,18 +149,18 @@ public:
// Frame buffer // Frame buffer
// Color attachment // Color attachment
vkDestroyImageView(device, offScreenFrameBuf.color.view, nullptr); vkDestroyImageView(device, offscreenPass.color.view, nullptr);
vkDestroyImage(device, offScreenFrameBuf.color.image, nullptr); vkDestroyImage(device, offscreenPass.color.image, nullptr);
vkFreeMemory(device, offScreenFrameBuf.color.mem, nullptr); vkFreeMemory(device, offscreenPass.color.mem, nullptr);
// Depth attachment // Depth attachment
vkDestroyImageView(device, offScreenFrameBuf.depth.view, nullptr); vkDestroyImageView(device, offscreenPass.depth.view, nullptr);
vkDestroyImage(device, offScreenFrameBuf.depth.image, nullptr); vkDestroyImage(device, offscreenPass.depth.image, nullptr);
vkFreeMemory(device, offScreenFrameBuf.depth.mem, nullptr); vkFreeMemory(device, offscreenPass.depth.mem, nullptr);
vkDestroyFramebuffer(device, offScreenFrameBuf.frameBuffer, nullptr); vkDestroyFramebuffer(device, offscreenPass.frameBuffer, nullptr);
vkDestroyRenderPass(device, offScreenFrameBuf.renderPass, nullptr); vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr);
// Pipelibes // Pipelibes
vkDestroyPipeline(device, pipelines.scene, nullptr); vkDestroyPipeline(device, pipelines.scene, nullptr);
@ -179,8 +180,8 @@ public:
vkTools::destroyUniformData(device, &uniformData.offscreen); vkTools::destroyUniformData(device, &uniformData.offscreen);
vkTools::destroyUniformData(device, &uniformData.scene); vkTools::destroyUniformData(device, &uniformData.scene);
vkFreeCommandBuffers(device, cmdPool, 1, &offScreenCmdBuffer); vkFreeCommandBuffers(device, cmdPool, 1, &offscreenPass.commandBuffer);
vkDestroySemaphore(device, offscreenSemaphore, nullptr); vkDestroySemaphore(device, offscreenPass.semaphore, nullptr);
} }
void prepareCubeMap() void prepareCubeMap()
@ -269,8 +270,8 @@ public:
// copied to the different cube map faces // copied to the different cube map faces
void prepareOffscreenFramebuffer() void prepareOffscreenFramebuffer()
{ {
offScreenFrameBuf.width = FB_DIM; offscreenPass.width = FB_DIM;
offScreenFrameBuf.height = FB_DIM; offscreenPass.height = FB_DIM;
VkFormat fbColorFormat = FB_COLOR_FORMAT; VkFormat fbColorFormat = FB_COLOR_FORMAT;
@ -278,8 +279,8 @@ public:
VkImageCreateInfo imageCreateInfo = vkTools::initializers::imageCreateInfo(); VkImageCreateInfo imageCreateInfo = vkTools::initializers::imageCreateInfo();
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = fbColorFormat; imageCreateInfo.format = fbColorFormat;
imageCreateInfo.extent.width = offScreenFrameBuf.width; imageCreateInfo.extent.width = offscreenPass.width;
imageCreateInfo.extent.height = offScreenFrameBuf.height; imageCreateInfo.extent.height = offscreenPass.height;
imageCreateInfo.extent.depth = 1; imageCreateInfo.extent.depth = 1;
imageCreateInfo.mipLevels = 1; imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1; imageCreateInfo.arrayLayers = 1;
@ -305,24 +306,24 @@ public:
VkMemoryRequirements memReqs; VkMemoryRequirements memReqs;
VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offScreenFrameBuf.color.image)); VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreenPass.color.image));
vkGetImageMemoryRequirements(device, offScreenFrameBuf.color.image, &memReqs); vkGetImageMemoryRequirements(device, offscreenPass.color.image, &memReqs);
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, &offScreenFrameBuf.color.mem)); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.color.mem));
VK_CHECK_RESULT(vkBindImageMemory(device, offScreenFrameBuf.color.image, offScreenFrameBuf.color.mem, 0)); VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.color.image, offscreenPass.color.mem, 0));
VkCommandBuffer layoutCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); VkCommandBuffer layoutCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
vkTools::setImageLayout( vkTools::setImageLayout(
layoutCmd, layoutCmd,
offScreenFrameBuf.color.image, offscreenPass.color.image,
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
colorImageView.image = offScreenFrameBuf.color.image; colorImageView.image = offscreenPass.color.image;
VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offScreenFrameBuf.color.view)); VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreenPass.color.view));
// Depth stencil attachment // Depth stencil attachment
imageCreateInfo.format = fbDepthFormat; imageCreateInfo.format = fbDepthFormat;
@ -339,38 +340,38 @@ public:
depthStencilView.subresourceRange.baseArrayLayer = 0; depthStencilView.subresourceRange.baseArrayLayer = 0;
depthStencilView.subresourceRange.layerCount = 1; depthStencilView.subresourceRange.layerCount = 1;
VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offScreenFrameBuf.depth.image)); VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &offscreenPass.depth.image));
vkGetImageMemoryRequirements(device, offScreenFrameBuf.depth.image, &memReqs); vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs);
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, &offScreenFrameBuf.depth.mem)); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.depth.mem));
VK_CHECK_RESULT(vkBindImageMemory(device, offScreenFrameBuf.depth.image, offScreenFrameBuf.depth.mem, 0)); VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.mem, 0));
vkTools::setImageLayout( vkTools::setImageLayout(
layoutCmd, layoutCmd,
offScreenFrameBuf.depth.image, offscreenPass.depth.image,
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
VulkanExampleBase::flushCommandBuffer(layoutCmd, queue, true); VulkanExampleBase::flushCommandBuffer(layoutCmd, queue, true);
depthStencilView.image = offScreenFrameBuf.depth.image; depthStencilView.image = offscreenPass.depth.image;
VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offScreenFrameBuf.depth.view)); VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view));
VkImageView attachments[2]; VkImageView attachments[2];
attachments[0] = offScreenFrameBuf.color.view; attachments[0] = offscreenPass.color.view;
attachments[1] = offScreenFrameBuf.depth.view; attachments[1] = offscreenPass.depth.view;
VkFramebufferCreateInfo fbufCreateInfo = vkTools::initializers::framebufferCreateInfo(); VkFramebufferCreateInfo fbufCreateInfo = vkTools::initializers::framebufferCreateInfo();
fbufCreateInfo.renderPass = offScreenFrameBuf.renderPass; fbufCreateInfo.renderPass = offscreenPass.renderPass;
fbufCreateInfo.attachmentCount = 2; fbufCreateInfo.attachmentCount = 2;
fbufCreateInfo.pAttachments = attachments; fbufCreateInfo.pAttachments = attachments;
fbufCreateInfo.width = offScreenFrameBuf.width; fbufCreateInfo.width = offscreenPass.width;
fbufCreateInfo.height = offScreenFrameBuf.height; fbufCreateInfo.height = offscreenPass.height;
fbufCreateInfo.layers = 1; fbufCreateInfo.layers = 1;
VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offScreenFrameBuf.frameBuffer)); VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreenPass.frameBuffer));
} }
// Updates a single cube map face // Updates a single cube map face
@ -386,10 +387,10 @@ public:
VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo(); VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo();
// Reuse render pass from example pass // Reuse render pass from example pass
renderPassBeginInfo.renderPass = renderPass; renderPassBeginInfo.renderPass = offscreenPass.renderPass;
renderPassBeginInfo.framebuffer = offScreenFrameBuf.frameBuffer; renderPassBeginInfo.framebuffer = offscreenPass.frameBuffer;
renderPassBeginInfo.renderArea.extent.width = offScreenFrameBuf.width; renderPassBeginInfo.renderArea.extent.width = offscreenPass.width;
renderPassBeginInfo.renderArea.extent.height = offScreenFrameBuf.height; renderPassBeginInfo.renderArea.extent.height = offscreenPass.height;
renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.clearValueCount = 2;
renderPassBeginInfo.pClearValues = clearValues; renderPassBeginInfo.pClearValues = clearValues;
@ -421,31 +422,31 @@ public:
} }
// Render scene from cube face's point of view // Render scene from cube face's point of view
vkCmdBeginRenderPass(offScreenCmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(offscreenPass.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
// Update shader push constant block // Update shader push constant block
// Contains current face view matrix // Contains current face view matrix
vkCmdPushConstants( vkCmdPushConstants(
offScreenCmdBuffer, offscreenPass.commandBuffer,
pipelineLayouts.offscreen, pipelineLayouts.offscreen,
VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_VERTEX_BIT,
0, 0,
sizeof(glm::mat4), sizeof(glm::mat4),
&viewMatrix); &viewMatrix);
vkCmdBindPipeline(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.offscreen); vkCmdBindPipeline(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.offscreen);
vkCmdBindDescriptorSets(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.offscreen, 0, 1, &descriptorSets.offscreen, 0, NULL); vkCmdBindDescriptorSets(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.offscreen, 0, 1, &descriptorSets.offscreen, 0, NULL);
VkDeviceSize offsets[1] = { 0 }; VkDeviceSize offsets[1] = { 0 };
vkCmdBindVertexBuffers(offScreenCmdBuffer, VERTEX_BUFFER_BIND_ID, 1, &meshes.scene.vertices.buf, offsets); vkCmdBindVertexBuffers(offscreenPass.commandBuffer, VERTEX_BUFFER_BIND_ID, 1, &meshes.scene.vertices.buf, offsets);
vkCmdBindIndexBuffer(offScreenCmdBuffer, meshes.scene.indices.buf, 0, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(offscreenPass.commandBuffer, meshes.scene.indices.buf, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(offScreenCmdBuffer, meshes.scene.indexCount, 1, 0, 0, 0); vkCmdDrawIndexed(offscreenPass.commandBuffer, meshes.scene.indexCount, 1, 0, 0, 0);
vkCmdEndRenderPass(offScreenCmdBuffer); vkCmdEndRenderPass(offscreenPass.commandBuffer);
// Make sure color writes to the framebuffer are finished before using it as transfer source // Make sure color writes to the framebuffer are finished before using it as transfer source
vkTools::setImageLayout( vkTools::setImageLayout(
offScreenCmdBuffer, offscreenPass.commandBuffer,
offScreenFrameBuf.color.image, offscreenPass.color.image,
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
@ -471,8 +472,8 @@ public:
// Put image copy into command buffer // Put image copy into command buffer
vkCmdCopyImage( vkCmdCopyImage(
offScreenCmdBuffer, offscreenPass.commandBuffer,
offScreenFrameBuf.color.image, offscreenPass.color.image,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
shadowCubeMap.image, shadowCubeMap.image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
@ -481,8 +482,8 @@ public:
// Transform framebuffer color attachment back // Transform framebuffer color attachment back
vkTools::setImageLayout( vkTools::setImageLayout(
offScreenCmdBuffer, offscreenPass.commandBuffer,
offScreenFrameBuf.color.image, offscreenPass.color.image,
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
@ -491,24 +492,26 @@ public:
// Command buffer for rendering and copying all cube map faces // Command buffer for rendering and copying all cube map faces
void buildOffscreenCommandBuffer() void buildOffscreenCommandBuffer()
{ {
if (offScreenCmdBuffer == VK_NULL_HANDLE) if (offscreenPass.commandBuffer == VK_NULL_HANDLE)
{ {
offScreenCmdBuffer = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, false); offscreenPass.commandBuffer = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, false);
}
if (offscreenPass.semaphore == VK_NULL_HANDLE)
{
// Create a semaphore used to synchronize offscreen rendering and usage
VkSemaphoreCreateInfo semaphoreCreateInfo = vkTools::initializers::semaphoreCreateInfo();
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &offscreenPass.semaphore));
} }
// Create a semaphore used to synchronize offscreen rendering and usage
VkSemaphoreCreateInfo semaphoreCreateInfo = vkTools::initializers::semaphoreCreateInfo();
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &offscreenSemaphore));
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
VK_CHECK_RESULT(vkBeginCommandBuffer(offScreenCmdBuffer, &cmdBufInfo)); VK_CHECK_RESULT(vkBeginCommandBuffer(offscreenPass.commandBuffer, &cmdBufInfo));
VkViewport viewport = vkTools::initializers::viewport((float)offScreenFrameBuf.width, (float)offScreenFrameBuf.height, 0.0f, 1.0f); VkViewport viewport = vkTools::initializers::viewport((float)offscreenPass.width, (float)offscreenPass.height, 0.0f, 1.0f);
vkCmdSetViewport(offScreenCmdBuffer, 0, 1, &viewport); vkCmdSetViewport(offscreenPass.commandBuffer, 0, 1, &viewport);
VkRect2D scissor = vkTools::initializers::rect2D(offScreenFrameBuf.width, offScreenFrameBuf.height, 0, 0); VkRect2D scissor = vkTools::initializers::rect2D(offscreenPass.width, offscreenPass.height, 0, 0);
vkCmdSetScissor(offScreenCmdBuffer, 0, 1, &scissor); vkCmdSetScissor(offscreenPass.commandBuffer, 0, 1, &scissor);
VkImageSubresourceRange subresourceRange = {}; VkImageSubresourceRange subresourceRange = {};
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@ -518,7 +521,7 @@ public:
// Change image layout for all cubemap faces to transfer destination // Change image layout for all cubemap faces to transfer destination
vkTools::setImageLayout( vkTools::setImageLayout(
offScreenCmdBuffer, offscreenPass.commandBuffer,
shadowCubeMap.image, shadowCubeMap.image,
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
@ -532,14 +535,14 @@ public:
// Change image layout for all cubemap faces to shader read after they have been copied // Change image layout for all cubemap faces to shader read after they have been copied
vkTools::setImageLayout( vkTools::setImageLayout(
offScreenCmdBuffer, offscreenPass.commandBuffer,
shadowCubeMap.image, shadowCubeMap.image,
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
subresourceRange); subresourceRange);
VK_CHECK_RESULT(vkEndCommandBuffer(offScreenCmdBuffer)); VK_CHECK_RESULT(vkEndCommandBuffer(offscreenPass.commandBuffer));
} }
void reBuildCommandBuffers() void reBuildCommandBuffers()
@ -616,7 +619,7 @@ public:
} }
} }
void loadMeshes() void loadAssets()
{ {
loadMesh(getAssetPath() + "models/cube.obj", &meshes.skybox, vertexLayout, 2.0f); loadMesh(getAssetPath() + "models/cube.obj", &meshes.skybox, vertexLayout, 2.0f);
loadMesh(getAssetPath() + "models/shadowscene_fire.dae", &meshes.scene, vertexLayout, 2.0f); loadMesh(getAssetPath() + "models/shadowscene_fire.dae", &meshes.scene, vertexLayout, 2.0f);
@ -836,7 +839,7 @@ public:
renderPassCreateInfo.subpassCount = 1; renderPassCreateInfo.subpassCount = 1;
renderPassCreateInfo.pSubpasses = &subpass; renderPassCreateInfo.pSubpasses = &subpass;
VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCreateInfo, nullptr, &offScreenFrameBuf.renderPass)); VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCreateInfo, nullptr, &offscreenPass.renderPass));
} }
void preparePipelines() void preparePipelines()
@ -925,7 +928,7 @@ public:
shaderStages[1] = loadShader(getAssetPath() + "shaders/shadowmapomni/offscreen.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/shadowmapomni/offscreen.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT;
pipelineCreateInfo.layout = pipelineLayouts.offscreen; pipelineCreateInfo.layout = pipelineLayouts.offscreen;
pipelineCreateInfo.renderPass = offScreenFrameBuf.renderPass; pipelineCreateInfo.renderPass = offscreenPass.renderPass;
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.offscreen)); VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.offscreen));
} }
@ -997,27 +1000,22 @@ public:
{ {
VulkanExampleBase::prepareFrame(); VulkanExampleBase::prepareFrame();
// The scene render command buffer has to wait for the offscreen
// rendering (and transfer) to be finished before using
// the shadow map, so we need to synchronize
// We use an additional semaphore for this
// Offscreen rendering // Offscreen rendering
// Wait for swap chain presentation to finish // Wait for swap chain presentation to finish
submitInfo.pWaitSemaphores = &semaphores.presentComplete; submitInfo.pWaitSemaphores = &semaphores.presentComplete;
// Signal ready with offscreen semaphore // Signal ready with offscreen semaphore
submitInfo.pSignalSemaphores = &offscreenSemaphore; submitInfo.pSignalSemaphores = &offscreenPass.semaphore;
// Submit work // Submit work
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &offScreenCmdBuffer; submitInfo.pCommandBuffers = &offscreenPass.commandBuffer;
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
// Scene rendering // Scene rendering
// Wait for offscreen semaphore // Wait for offscreen semaphore
submitInfo.pWaitSemaphores = &offscreenSemaphore; submitInfo.pWaitSemaphores = &offscreenPass.semaphore;
// Signal ready with render complete semaphpre // Signal ready with render complete semaphpre
submitInfo.pSignalSemaphores = &semaphores.renderComplete; submitInfo.pSignalSemaphores = &semaphores.renderComplete;
@ -1031,7 +1029,7 @@ public:
void prepare() void prepare()
{ {
VulkanExampleBase::prepare(); VulkanExampleBase::prepare();
loadMeshes(); loadAssets();
setupVertexDescriptions(); setupVertexDescriptions();
prepareUniformBuffers(); prepareUniformBuffers();
prepareCubeMap(); prepareCubeMap();