diff --git a/android/radialblur/build.bat b/android/radialblur/build.bat index 1367de8a..a90eb9d3 100644 --- a/android/radialblur/build.bat +++ b/android/radialblur/build.bat @@ -6,13 +6,15 @@ if %ERRORLEVEL% EQU 0 ( mkdir "assets\shaders\base" xcopy "..\..\data\shaders\base\*.spv" "assets\shaders\base" /Y - mkdir "assets\shaders\radialblur" xcopy "..\..\data\shaders\radialblur\*.spv" "assets\shaders\radialblur" /Y mkdir "assets\models" xcopy "..\..\data\models\glowsphere.dae" "assets\models" /Y + + mkdir "assets\textures" + xcopy "..\..\data\textures\particle_gradient_rgba.ktx" "assets\textures" /Y mkdir "res\drawable" xcopy "..\..\android\images\icon.png" "res\drawable" /Y diff --git a/debugmarker/debugmarker.cpp b/debugmarker/debugmarker.cpp index 9db851ea..5c6bd6e3 100644 --- a/debugmarker/debugmarker.cpp +++ b/debugmarker/debugmarker.cpp @@ -215,14 +215,17 @@ public: VkDeviceMemory mem; VkImageView view; }; - struct FrameBuffer { + struct OffscreenPass { int32_t width, height; VkFramebuffer frameBuffer; FrameBufferAttachment color, depth; - vkTools::VulkanTexture textureTarget; - } offScreenFrameBuf; - - VkCommandBuffer offScreenCmdBuffer = VK_NULL_HANDLE; + VkRenderPass renderPass; + 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; // Random tag data struct { @@ -265,106 +268,29 @@ public: vkTools::destroyUniformData(device, &uniformData.vsScene); // Offscreen - // Texture target - textureLoader->destroyTexture(offScreenFrameBuf.textureTarget); - // Frame buffer // Color attachment - vkDestroyImageView(device, offScreenFrameBuf.color.view, nullptr); - vkDestroyImage(device, offScreenFrameBuf.color.image, nullptr); - vkFreeMemory(device, offScreenFrameBuf.color.mem, nullptr); + vkDestroyImageView(device, offscreenPass.color.view, nullptr); + vkDestroyImage(device, offscreenPass.color.image, nullptr); + vkFreeMemory(device, offscreenPass.color.mem, nullptr); + // Depth attachment - vkDestroyImageView(device, offScreenFrameBuf.depth.view, nullptr); - vkDestroyImage(device, offScreenFrameBuf.depth.image, nullptr); - vkFreeMemory(device, offScreenFrameBuf.depth.mem, nullptr); - vkDestroyFramebuffer(device, offScreenFrameBuf.frameBuffer, nullptr); + vkDestroyImageView(device, offscreenPass.depth.view, nullptr); + vkDestroyImage(device, offscreenPass.depth.image, nullptr); + vkFreeMemory(device, offscreenPass.depth.mem, nullptr); + + vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); + vkDestroySampler(device, offscreenPass.sampler, nullptr); + vkDestroyFramebuffer(device, offscreenPass.frameBuffer, nullptr); + + vkFreeCommandBuffers(device, cmdPool, 1, &offscreenPass.commandBuffer); + vkDestroySemaphore(device, offscreenPass.semaphore, nullptr); } // Prepare a texture target and framebuffer for offscreen rendering void prepareOffscreen() { - VkCommandBuffer cmdBuffer = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - - VkFormatProperties formatProperties; - - // Get device properites for the requested texture format - vkGetPhysicalDeviceFormatProperties(physicalDevice, OFFSCREEN_FORMAT, &formatProperties); - // Check if blit destination is supported for the requested format - // Only try for optimal tiling, linear tiling usually won't support blit as destination anyway - assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT); - - // Texture target - - vkTools::VulkanTexture *tex = &offScreenFrameBuf.textureTarget; - - // Prepare blit target texture - tex->width = OFFSCREEN_DIM; - tex->height = OFFSCREEN_DIM; - - VkImageCreateInfo imageCreateInfo = vkTools::initializers::imageCreateInfo(); - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = OFFSCREEN_FORMAT; - imageCreateInfo.extent = { OFFSCREEN_DIM, OFFSCREEN_DIM, 1 }; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - // Texture will be sampled in a shader and is also the blit destination - imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - - VkMemoryAllocateInfo memAllocInfo = vkTools::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; - - VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &tex->image)); - vkGetImageMemoryRequirements(device, tex->image, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &(tex->deviceMemory))); - VK_CHECK_RESULT(vkBindImageMemory(device, tex->image, tex->deviceMemory, 0)); - - // Transform image layout to transfer destination - tex->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vkTools::setImageLayout( - cmdBuffer, - tex->image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - tex->imageLayout); - - // Create sampler - VkSamplerCreateInfo sampler = vkTools::initializers::samplerCreateInfo(); - sampler.magFilter = OFFSCREEN_FILTER; - sampler.minFilter = OFFSCREEN_FILTER; - sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler.addressModeV = sampler.addressModeU; - sampler.addressModeW = sampler.addressModeU; - sampler.mipLodBias = 0.0f; - sampler.maxAnisotropy = 0; - sampler.compareOp = VK_COMPARE_OP_NEVER; - sampler.minLod = 0.0f; - sampler.maxLod = 0.0f; - sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &tex->sampler)); - - // Create image view - VkImageViewCreateInfo view = vkTools::initializers::imageViewCreateInfo(); - view.image = VK_NULL_HANDLE; - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - view.format = OFFSCREEN_FORMAT; - view.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; - view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - view.image = tex->image; - VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &tex->view)); - - // Name for debugging - DebugMarker::setObjectName(device, (uint64_t)tex->image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "Off-screen texture target image"); - DebugMarker::setObjectName(device, (uint64_t)tex->sampler, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, "Off-screen texture target sampler"); - - // Frame buffer - offScreenFrameBuf.width = OFFSCREEN_DIM; - offScreenFrameBuf.height = OFFSCREEN_DIM; + offscreenPass.width = OFFSCREEN_DIM; + offscreenPass.height = OFFSCREEN_DIM; // Find a suitable depth format VkFormat fbDepthFormat; @@ -375,49 +301,64 @@ public: VkImageCreateInfo image = vkTools::initializers::imageCreateInfo(); image.imageType = VK_IMAGE_TYPE_2D; image.format = OFFSCREEN_FORMAT; - image.extent.width = offScreenFrameBuf.width; - image.extent.height = offScreenFrameBuf.height; + image.extent.width = offscreenPass.width; + image.extent.height = offscreenPass.height; image.extent.depth = 1; image.mipLevels = 1; 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 | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image.flags = 0; + // We will sample directly from the color attachment + image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + + VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo(); + VkMemoryRequirements memReqs; + + VK_CHECK_RESULT(vkCreateImage(device, &image, 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)); VkImageViewCreateInfo colorImageView = vkTools::initializers::imageViewCreateInfo(); colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; colorImageView.format = OFFSCREEN_FORMAT; - colorImageView.flags = 0; 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; + colorImageView.image = offscreenPass.color.image; + VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offscreenPass.color.view)); - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offScreenFrameBuf.color.image)); - vkGetImageMemoryRequirements(device, offScreenFrameBuf.color.image, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &offScreenFrameBuf.color.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offScreenFrameBuf.color.image, offScreenFrameBuf.color.mem, 0)); - - vkTools::setImageLayout( - cmdBuffer, - offScreenFrameBuf.color.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - colorImageView.image = offScreenFrameBuf.color.image; - VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &offScreenFrameBuf.color.view)); + // Create sampler to sample from the attachment in the fragment shader + VkSamplerCreateInfo samplerInfo = vkTools::initializers::samplerCreateInfo(); + samplerInfo.magFilter = OFFSCREEN_FILTER; + samplerInfo.minFilter = OFFSCREEN_FILTER; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeV = samplerInfo.addressModeU; + samplerInfo.addressModeW = samplerInfo.addressModeU; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.maxAnisotropy = 0; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = 1.0f; + samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + VK_CHECK_RESULT(vkCreateSampler(device, &samplerInfo, nullptr, &offscreenPass.sampler)); // Depth stencil attachment image.format = fbDepthFormat; image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + 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)); + VkImageViewCreateInfo depthStencilView = vkTools::initializers::imageViewCreateInfo(); depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; depthStencilView.format = fbDepthFormat; @@ -428,50 +369,110 @@ public: depthStencilView.subresourceRange.levelCount = 1; depthStencilView.subresourceRange.baseArrayLayer = 0; depthStencilView.subresourceRange.layerCount = 1; + depthStencilView.image = offscreenPass.depth.image; + VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offscreenPass.depth.view)); - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offScreenFrameBuf.depth.image)); - vkGetImageMemoryRequirements(device, offScreenFrameBuf.depth.image, &memReqs); - memAllocInfo.allocationSize = memReqs.size; - memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &offScreenFrameBuf.depth.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, offScreenFrameBuf.depth.image, offScreenFrameBuf.depth.mem, 0)); + // Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering - vkTools::setImageLayout( - cmdBuffer, - offScreenFrameBuf.depth.image, - VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + std::array attchmentDescriptions = {}; + // Color attachment + attchmentDescriptions[0].format = OFFSCREEN_FORMAT; + attchmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT; + attchmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attchmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attchmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attchmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attchmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attchmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + // Depth attachment + attchmentDescriptions[1].format = fbDepthFormat; + attchmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT; + attchmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attchmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attchmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attchmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attchmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attchmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - depthStencilView.image = offScreenFrameBuf.depth.image; - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &offScreenFrameBuf.depth.view)); + VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; + VkAttachmentReference depthReference = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; + + VkSubpassDescription subpassDescription = {}; + subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpassDescription.colorAttachmentCount = 1; + subpassDescription.pColorAttachments = &colorReference; + subpassDescription.pDepthStencilAttachment = &depthReference; + + // Use subpass dependencies for layout transitions + std::array dependencies; + + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + dependencies[0].dstSubpass = 0; + 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].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].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + // Create the actual renderpass + VkRenderPassCreateInfo renderPassInfo = {}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassInfo.attachmentCount = static_cast(attchmentDescriptions.size()); + renderPassInfo.pAttachments = attchmentDescriptions.data(); + renderPassInfo.subpassCount = 1; + renderPassInfo.pSubpasses = &subpassDescription; + renderPassInfo.dependencyCount = static_cast(dependencies.size()); + renderPassInfo.pDependencies = dependencies.data(); + + VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &offscreenPass.renderPass)); VkImageView attachments[2]; - attachments[0] = offScreenFrameBuf.color.view; - attachments[1] = offScreenFrameBuf.depth.view; + attachments[0] = offscreenPass.color.view; + attachments[1] = offscreenPass.depth.view; VkFramebufferCreateInfo fbufCreateInfo = vkTools::initializers::framebufferCreateInfo(); - fbufCreateInfo.renderPass = renderPass; + fbufCreateInfo.renderPass = offscreenPass.renderPass; fbufCreateInfo.attachmentCount = 2; fbufCreateInfo.pAttachments = attachments; - fbufCreateInfo.width = offScreenFrameBuf.width; - fbufCreateInfo.height = offScreenFrameBuf.height; + fbufCreateInfo.width = offscreenPass.width; + fbufCreateInfo.height = offscreenPass.height; fbufCreateInfo.layers = 1; - VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offScreenFrameBuf.frameBuffer)); - VulkanExampleBase::flushCommandBuffer(cmdBuffer, queue, true); + VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offscreenPass.frameBuffer)); - // Command buffer for offscreen rendering - offScreenCmdBuffer = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, false); + // Fill a descriptor for later use in a descriptor set + offscreenPass.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + offscreenPass.descriptor.imageView = offscreenPass.color.view; + offscreenPass.descriptor.sampler = offscreenPass.sampler; - // Name for debugging - DebugMarker::setObjectName(device, (uint64_t)offScreenFrameBuf.color.image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "Off-screen color framebuffer"); - DebugMarker::setObjectName(device, (uint64_t)offScreenFrameBuf.depth.image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "Off-screen depth framebuffer"); + // Name some objects for debugging + DebugMarker::setObjectName(device, (uint64_t)offscreenPass.color.image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "Off-screen color framebuffer"); + DebugMarker::setObjectName(device, (uint64_t)offscreenPass.depth.image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "Off-screen depth framebuffer"); + DebugMarker::setObjectName(device, (uint64_t)offscreenPass.sampler, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, "Off-screen framebuffer default sampler"); } // Command buffer for rendering color only scene for glow void buildOffscreenCommandBuffer() { + if (offscreenPass.commandBuffer == VK_NULL_HANDLE) + { + 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)); + } + VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); VkClearValue clearValues[2]; @@ -479,107 +480,37 @@ public: clearValues[1].depthStencil = { 1.0f, 0 }; VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo(); - renderPassBeginInfo.renderPass = renderPass; - renderPassBeginInfo.framebuffer = offScreenFrameBuf.frameBuffer; - renderPassBeginInfo.renderArea.extent.width = offScreenFrameBuf.width; - renderPassBeginInfo.renderArea.extent.height = offScreenFrameBuf.height; + renderPassBeginInfo.renderPass = offscreenPass.renderPass; + renderPassBeginInfo.framebuffer = offscreenPass.frameBuffer; + renderPassBeginInfo.renderArea.extent.width = offscreenPass.width; + renderPassBeginInfo.renderArea.extent.height = offscreenPass.height; renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.pClearValues = clearValues; - VK_CHECK_RESULT(vkBeginCommandBuffer(offScreenCmdBuffer, &cmdBufInfo)); + VK_CHECK_RESULT(vkBeginCommandBuffer(offscreenPass.commandBuffer, &cmdBufInfo)); // Start a new debug marker region - DebugMarker::beginRegion(offScreenCmdBuffer, "Off-screen scene rendering", glm::vec4(1.0f, 0.78f, 0.05f, 1.0f)); + DebugMarker::beginRegion(offscreenPass.commandBuffer, "Off-screen scene rendering", glm::vec4(1.0f, 0.78f, 0.05f, 1.0f)); - VkViewport viewport = vkTools::initializers::viewport((float)offScreenFrameBuf.width, (float)offScreenFrameBuf.height, 0.0f, 1.0f); - vkCmdSetViewport(offScreenCmdBuffer, 0, 1, &viewport); + VkViewport viewport = vkTools::initializers::viewport((float)offscreenPass.width, (float)offscreenPass.height, 0.0f, 1.0f); + vkCmdSetViewport(offscreenPass.commandBuffer, 0, 1, &viewport); - VkRect2D scissor = vkTools::initializers::rect2D(offScreenFrameBuf.width, offScreenFrameBuf.height, 0, 0); - vkCmdSetScissor(offScreenCmdBuffer, 0, 1, &scissor); + VkRect2D scissor = vkTools::initializers::rect2D(offscreenPass.width, offscreenPass.height, 0, 0); + vkCmdSetScissor(offscreenPass.commandBuffer, 0, 1, &scissor); - vkCmdBeginRenderPass(offScreenCmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdBeginRenderPass(offscreenPass.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindDescriptorSets(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.scene, 0, NULL); - vkCmdBindPipeline(offScreenCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.color); + vkCmdBindDescriptorSets(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.scene, 0, NULL); + vkCmdBindPipeline(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.color); // Draw glow scene - sceneGlow.draw(offScreenCmdBuffer); + sceneGlow.draw(offscreenPass.commandBuffer); - vkCmdEndRenderPass(offScreenCmdBuffer); + vkCmdEndRenderPass(offscreenPass.commandBuffer); - // Make sure color writes to the framebuffer are finished before using it as transfer source - vkTools::setImageLayout( - offScreenCmdBuffer, - offScreenFrameBuf.color.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + DebugMarker::endRegion(offscreenPass.commandBuffer); - // Transform texture target to transfer destination - vkTools::setImageLayout( - offScreenCmdBuffer, - offScreenFrameBuf.textureTarget.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - // Blit offscreen color buffer to our texture target - VkImageBlit imgBlit; - - imgBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imgBlit.srcSubresource.mipLevel = 0; - imgBlit.srcSubresource.baseArrayLayer = 0; - imgBlit.srcSubresource.layerCount = 1; - - imgBlit.srcOffsets[0] = { 0, 0, 0 }; - imgBlit.srcOffsets[1].x = offScreenFrameBuf.width; - imgBlit.srcOffsets[1].y = offScreenFrameBuf.height; - imgBlit.srcOffsets[1].z = 1; - - imgBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imgBlit.dstSubresource.mipLevel = 0; - imgBlit.dstSubresource.baseArrayLayer = 0; - imgBlit.dstSubresource.layerCount = 1; - - imgBlit.dstOffsets[0] = { 0, 0, 0 }; - imgBlit.dstOffsets[1].x = offScreenFrameBuf.textureTarget.width; - imgBlit.dstOffsets[1].y = offScreenFrameBuf.textureTarget.height; - imgBlit.dstOffsets[1].z = 1; - - // Blit from framebuffer image to texture image - // vkCmdBlitImage does scaling and (if necessary and possible) also does format conversions - vkCmdBlitImage( - offScreenCmdBuffer, - offScreenFrameBuf.color.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - offScreenFrameBuf.textureTarget.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &imgBlit, - VK_FILTER_LINEAR - ); - - // Transform framebuffer color attachment back - vkTools::setImageLayout( - offScreenCmdBuffer, - offScreenFrameBuf.color.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - // Transform texture target back to shader read - // Makes sure that writes to the texture are finished before - // it's accessed in the shader - vkTools::setImageLayout( - offScreenCmdBuffer, - offScreenFrameBuf.textureTarget.image, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - DebugMarker::endRegion(offScreenCmdBuffer); - - VK_CHECK_RESULT(vkEndCommandBuffer(offScreenCmdBuffer)); + VK_CHECK_RESULT(vkEndCommandBuffer(offscreenPass.commandBuffer)); } // Load a model file as separate meshes into a scene @@ -962,12 +893,6 @@ public: VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.scene)); - VkDescriptorImageInfo texDescriptor = - vkTools::initializers::descriptorImageInfo( - offScreenFrameBuf.textureTarget.sampler, - offScreenFrameBuf.textureTarget.view, - VK_IMAGE_LAYOUT_GENERAL); - std::vector writeDescriptorSets = { // Binding 0 : Vertex shader uniform buffer @@ -981,7 +906,7 @@ public: descriptorSets.scene, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, - &texDescriptor) + &offscreenPass.descriptor) }; vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); @@ -1065,25 +990,22 @@ public: // Color only pipeline shaderStages[0] = loadShader(getAssetPath() + "shaders/debugmarker/colorpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/debugmarker/colorpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - + pipelineCreateInfo.renderPass = offscreenPass.renderPass; VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.color)); // Wire frame rendering pipeline rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; rasterizationState.lineWidth = 1.0f; - + pipelineCreateInfo.renderPass = renderPass; VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.wireframe)); // Post processing effect shaderStages[0] = loadShader(getAssetPath() + "shaders/debugmarker/postprocess.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/debugmarker/postprocess.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - depthStencilState.depthTestEnable = VK_FALSE; depthStencilState.depthWriteEnable = VK_FALSE; - rasterizationState.polygonMode = VK_POLYGON_MODE_FILL; rasterizationState.cullMode = VK_CULL_MODE_NONE; - blendAttachmentState.colorWriteMask = 0xF; blendAttachmentState.blendEnable = VK_TRUE; blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; @@ -1092,7 +1014,6 @@ public: blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.postprocess)); // Name shader moduels for debugging @@ -1159,7 +1080,7 @@ public: // todo : use event to ensure that offscreen result is finished bfore render command buffer is started if (glow) { - submitCmdBuffers.push_back(offScreenCmdBuffer); + submitCmdBuffers.push_back(offscreenPass.commandBuffer); } submitCmdBuffers.push_back(drawCmdBuffers[currentBuffer]);