diff --git a/deferred/deferred.cpp b/deferred/deferred.cpp index 1ba16b0c..90585d67 100644 --- a/deferred/deferred.cpp +++ b/deferred/deferred.cpp @@ -133,6 +133,7 @@ public: rotation = { 0.0f, 0.0f, 0.0f }; width = 1024; height = 1024; + enableTextOverlay = true; title = "Vulkan Example - Deferred shading"; } @@ -222,15 +223,12 @@ public: VkMemoryAllocateInfo memAllocInfo = vkTools::initializers::memoryAllocateInfo(); VkMemoryRequirements memReqs; - err = vkCreateImage(device, &imageCreateInfo, nullptr, &target->image); - assert(!err); + VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &target->image)); vkGetImageMemoryRequirements(device, target->image, &memReqs); memAllocInfo.allocationSize = memReqs.size; - getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAllocInfo.memoryTypeIndex); - err = vkAllocateMemory(device, &memAllocInfo, nullptr, &target->deviceMemory); - assert(!err); - err = vkBindImageMemory(device, target->image, target->deviceMemory, 0); - assert(!err); + memAllocInfo.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &target->deviceMemory)); + VK_CHECK_RESULT(vkBindImageMemory(device, target->image, target->deviceMemory, 0)); // Image memory barrier // Set initial layout for the offscreen texture to shader read @@ -255,10 +253,9 @@ public: sampler.maxAnisotropy = 0; sampler.compareOp = VK_COMPARE_OP_NEVER; sampler.minLod = 0.0f; - sampler.maxLod = 0.0f; + sampler.maxLod = 1.0f; sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - err = vkCreateSampler(device, &sampler, nullptr, &target->sampler); - assert(!err); + VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &target->sampler)); // Create image view VkImageViewCreateInfo view = {}; @@ -270,8 +267,7 @@ public: 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 = target->image; - err = vkCreateImageView(device, &view, nullptr, &target->view); - assert(!err); + VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &target->view)); } void prepareTextureTargets() @@ -314,6 +310,7 @@ public: image.format = format; image.extent.width = offScreenFrameBuf.width; image.extent.height = offScreenFrameBuf.height; + image.extent.depth = 1; image.mipLevels = 1; image.arrayLayers = 1; image.samples = VK_SAMPLE_COUNT_1_BIT; @@ -321,6 +318,21 @@ public: image.usage = usage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo(); + VkMemoryRequirements memReqs; + + VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &attachment->image)); + vkGetImageMemoryRequirements(device, attachment->image, &memReqs); + memAlloc.allocationSize = memReqs.size; + getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAlloc.memoryTypeIndex); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &attachment->mem)); + VK_CHECK_RESULT(vkBindImageMemory(device, attachment->image, attachment->mem, 0)); + + vkTools::setImageLayout( + setupCmdBuffer, + attachment->image, + aspectMask, + VK_IMAGE_LAYOUT_UNDEFINED, + imageLayout); VkImageViewCreateInfo imageView = vkTools::initializers::imageViewCreateInfo(); imageView.viewType = VK_IMAGE_VIEW_TYPE_2D; @@ -331,30 +343,8 @@ public: imageView.subresourceRange.levelCount = 1; imageView.subresourceRange.baseArrayLayer = 0; imageView.subresourceRange.layerCount = 1; - - VkMemoryRequirements memReqs; - - VkResult err = vkCreateImage(device, &image, nullptr, &attachment->image); - assert(!err); - vkGetImageMemoryRequirements(device, attachment->image, &memReqs); - memAlloc.allocationSize = memReqs.size; - getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAlloc.memoryTypeIndex); - err = vkAllocateMemory(device, &memAlloc, nullptr, &attachment->mem); - assert(!err); - - err = vkBindImageMemory(device, attachment->image, attachment->mem, 0); - assert(!err); - - vkTools::setImageLayout( - setupCmdBuffer, - attachment->image, - aspectMask, - VK_IMAGE_LAYOUT_UNDEFINED, - imageLayout); - imageView.image = attachment->image; - err = vkCreateImageView(device, &imageView, nullptr, &attachment->view); - assert(!err); + VK_CHECK_RESULT(vkCreateImageView(device, &imageView, nullptr, &attachment->view)); } // Prepare a new framebuffer for offscreen rendering @@ -365,8 +355,6 @@ public: offScreenFrameBuf.width = FB_DIM; offScreenFrameBuf.height = FB_DIM; - VkResult err; - // Color attachments // (World space) Positions @@ -452,8 +440,7 @@ public: renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpass; - err = vkCreateRenderPass(device, &renderPassInfo, nullptr, &offScreenFrameBuf.renderPass); - assert(!err); + VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &offScreenFrameBuf.renderPass)); std::array attachments; attachments[0] = offScreenFrameBuf.position.view; @@ -472,8 +459,7 @@ public: fbufCreateInfo.height = offScreenFrameBuf.height; fbufCreateInfo.layers = 1; - err = vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offScreenFrameBuf.frameBuffer); - assert(!err); + VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &offScreenFrameBuf.frameBuffer)); flushSetupCommandBuffer(); createSetupCommandBuffer(); @@ -565,8 +551,6 @@ public: // and blitting it to the different texture targets void buildDeferredCommandBuffer() { - VkResult err; - // Create separate command buffer for offscreen // rendering if (offScreenCmdBuffer == VK_NULL_HANDLE) @@ -575,8 +559,7 @@ public: cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); - VkResult vkRes = vkAllocateCommandBuffers(device, &cmd, &offScreenCmdBuffer); - assert(!vkRes); + VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmd, &offScreenCmdBuffer)); } VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); @@ -596,8 +579,7 @@ public: renderPassBeginInfo.clearValueCount = clearValues.size(); renderPassBeginInfo.pClearValues = clearValues.data(); - err = vkBeginCommandBuffer(offScreenCmdBuffer, &cmdBufInfo); - assert(!err); + VK_CHECK_RESULT(vkBeginCommandBuffer(offScreenCmdBuffer, &cmdBufInfo)); vkCmdBeginRenderPass(offScreenCmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); @@ -629,8 +611,7 @@ public: blit(offScreenFrameBuf.normal.image, textureTargets.normal.image); blit(offScreenFrameBuf.albedo.image, textureTargets.albedo.image); - err = vkEndCommandBuffer(offScreenCmdBuffer); - assert(!err); + VK_CHECK_RESULT(vkEndCommandBuffer(offScreenCmdBuffer)); } void loadTextures() @@ -668,15 +649,12 @@ public: renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.pClearValues = clearValues; - VkResult err; - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { // Set target frame buffer renderPassBeginInfo.framebuffer = frameBuffers[i]; - err = vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo); - assert(!err); + VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); @@ -717,42 +695,10 @@ public: vkCmdEndRenderPass(drawCmdBuffers[i]); - err = vkEndCommandBuffer(drawCmdBuffers[i]); - assert(!err); + VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); } } - void draw() - { - VkResult err; - - // Get next image in the swap chain (back/front buffer) - err = swapChain.acquireNextImage(semaphores.presentComplete, ¤tBuffer); - assert(!err); - - submitPostPresentBarrier(swapChain.buffers[currentBuffer].image); - - // Gather command buffers to be sumitted to the queue - std::vector submitCmdBuffers = { - offScreenCmdBuffer, - drawCmdBuffers[currentBuffer], - }; - submitInfo.commandBufferCount = submitCmdBuffers.size(); - submitInfo.pCommandBuffers = submitCmdBuffers.data(); - - // Submit to queue - err = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); - assert(!err); - - submitPrePresentBarrier(swapChain.buffers[currentBuffer].image); - - err = swapChain.queuePresent(queue, currentBuffer, semaphores.renderComplete); - assert(!err); - - err = vkQueueWaitIdle(queue); - assert(!err); - } - void loadMeshes() { loadMesh(getAssetPath() + "models/armor/armor.dae", &meshes.example, vertexLayout, 1.0f); @@ -877,8 +823,7 @@ public: poolSizes.data(), 2); - VkResult vkRes = vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool); - assert(!vkRes); + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); } void setupDescriptorSetLayout() @@ -918,20 +863,17 @@ public: setLayoutBindings.data(), setLayoutBindings.size()); - VkResult err = vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout); - assert(!err); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = vkTools::initializers::pipelineLayoutCreateInfo( &descriptorSetLayout, 1); - err = vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayouts.deferred); - assert(!err); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayouts.deferred)); // Offscreen (scene) rendering pipeline layout - err = vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayouts.offscreen); - assert(!err); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayouts.offscreen)); } void setupDescriptorSet() @@ -943,8 +885,7 @@ public: &descriptorSetLayout, 1); - VkResult vkRes = vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet); - assert(!vkRes); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); // Image descriptor for the offscreen texture targets VkDescriptorImageInfo texDescriptorPosition = @@ -1002,8 +943,7 @@ public: vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); // Offscreen (scene) - vkRes = vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.offscreen); - assert(!vkRes); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.offscreen)); VkDescriptorImageInfo texDescriptorSceneColormap = vkTools::initializers::descriptorImageInfo( @@ -1101,14 +1041,12 @@ public: pipelineCreateInfo.stageCount = shaderStages.size(); pipelineCreateInfo.pStages = shaderStages.data(); - VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.deferred); - assert(!err); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.deferred)); // Debug display pipeline shaderStages[0] = loadShader(getAssetPath() + "shaders/deferred/debug.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/deferred/debug.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.debug); - assert(!err); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.debug)); // Offscreen pipeline shaderStages[0] = loadShader(getAssetPath() + "shaders/deferred/mrt.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); @@ -1132,9 +1070,7 @@ public: colorBlendState.attachmentCount = blendAttachmentStates.size(); colorBlendState.pAttachments = blendAttachmentStates.data(); - err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.offscreen); - assert(!err); - + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.offscreen)); } // Prepare and initialize uniform buffer containing shader uniforms @@ -1143,8 +1079,9 @@ public: // Fullscreen vertex shader createBuffer( VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, sizeof(uboVS), - &uboVS, + nullptr, &uniformData.vsFullScreen.buffer, &uniformData.vsFullScreen.memory, &uniformData.vsFullScreen.descriptor); @@ -1152,8 +1089,9 @@ public: // Deferred vertex shader createBuffer( VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, sizeof(uboOffscreenVS), - &uboOffscreenVS, + nullptr, &uniformData.vsOffscreen.buffer, &uniformData.vsOffscreen.memory, &uniformData.vsOffscreen.descriptor); @@ -1161,8 +1099,9 @@ public: // Deferred fragment shader createBuffer( VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, sizeof(uboFragmentLights), - &uboFragmentLights, + nullptr, &uniformData.fsLights.buffer, &uniformData.fsLights.memory, &uniformData.fsLights.descriptor); @@ -1186,8 +1125,7 @@ public: uboVS.model = glm::mat4(); uint8_t *pData; - VkResult err = vkMapMemory(device, uniformData.vsFullScreen.memory, 0, sizeof(uboVS), 0, (void **)&pData); - assert(!err); + VK_CHECK_RESULT(vkMapMemory(device, uniformData.vsFullScreen.memory, 0, sizeof(uboVS), 0, (void **)&pData)); memcpy(pData, &uboVS, sizeof(uboVS)); vkUnmapMemory(device, uniformData.vsFullScreen.memory); } @@ -1196,16 +1134,15 @@ public: { uboOffscreenVS.projection = glm::perspective(glm::radians(45.0f), (float)width / (float)height, 0.1f, 256.0f); uboOffscreenVS.view = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, zoom)); - uboOffscreenVS.view = glm::rotate(uboOffscreenVS.view, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); - uboOffscreenVS.view = glm::rotate(uboOffscreenVS.view, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - uboOffscreenVS.view = glm::rotate(uboOffscreenVS.view, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); uboOffscreenVS.model = glm::mat4(); - uboOffscreenVS.model = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.25f, 0.0f)); + uboOffscreenVS.model = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.25f, 0.0f) + cameraPos); + uboOffscreenVS.model = glm::rotate(uboOffscreenVS.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); + uboOffscreenVS.model = glm::rotate(uboOffscreenVS.model, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); + uboOffscreenVS.model = glm::rotate(uboOffscreenVS.model, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); uint8_t *pData; - VkResult err = vkMapMemory(device, uniformData.vsOffscreen.memory, 0, sizeof(uboOffscreenVS), 0, (void **)&pData); - assert(!err); + VK_CHECK_RESULT(vkMapMemory(device, uniformData.vsOffscreen.memory, 0, sizeof(uboOffscreenVS), 0, (void **)&pData)); memcpy(pData, &uboOffscreenVS, sizeof(uboOffscreenVS)); vkUnmapMemory(device, uniformData.vsOffscreen.memory); } @@ -1248,12 +1185,29 @@ public: uboFragmentLights.viewPos = glm::vec4(0.0f, 0.0f, -zoom, 0.0f); uint8_t *pData; - VkResult err = vkMapMemory(device, uniformData.fsLights.memory, 0, sizeof(uboFragmentLights), 0, (void **)&pData); - assert(!err); + VK_CHECK_RESULT(vkMapMemory(device, uniformData.fsLights.memory, 0, sizeof(uboFragmentLights), 0, (void **)&pData)); memcpy(pData, &uboFragmentLights, sizeof(uboFragmentLights)); vkUnmapMemory(device, uniformData.fsLights.memory); } + void draw() + { + VulkanExampleBase::prepareFrame(); + + // Submit offscreen rendering command buffer + // todo : use event to ensure that offscreen result is finished bfore render command buffer is started + std::vector submitCmdBuffers = { + offScreenCmdBuffer, + drawCmdBuffers[currentBuffer], + }; + submitCmdBuffers.push_back(drawCmdBuffers[currentBuffer]); + submitInfo.commandBufferCount = submitCmdBuffers.size(); + submitInfo.pCommandBuffers = submitCmdBuffers.data(); + + VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); + + VulkanExampleBase::submitFrame(); + } void prepare() { @@ -1278,9 +1232,7 @@ public: { if (!prepared) return; - vkDeviceWaitIdle(device); draw(); - vkDeviceWaitIdle(device); } virtual void viewChanged() @@ -1294,6 +1246,35 @@ public: reBuildCommandBuffers(); updateUniformBuffersScreen(); } + + virtual void keyPressed(uint32_t keyCode) + { + switch (keyCode) + { + case 0x44: + case GAMEPAD_BUTTON_A: + toggleDebugDisplay(); + updateTextOverlay(); + break; + } + } + + virtual void getOverlayText(VulkanTextOverlay *textOverlay) + { +#if defined(__ANDROID__) + textOverlay->addText("Press \"Button A\" to toggle render targets", 5.0f, 85.0f, VulkanTextOverlay::alignLeft); +#else + textOverlay->addText("Press \"d\" to to toggle render targets", 5.0f, 85.0f, VulkanTextOverlay::alignLeft); +#endif + // Render targets + if (debugDisplay) + { + textOverlay->addText("World Position", (float)width * 0.25f, (float)height * 0.5f - 25.0f, VulkanTextOverlay::alignCenter); + textOverlay->addText("World normals", (float)width * 0.75f, (float)height * 0.5f - 25.0f, VulkanTextOverlay::alignCenter); + textOverlay->addText("Color", (float)width * 0.25f, (float)height - 25.0f, VulkanTextOverlay::alignCenter); + textOverlay->addText("Final image", (float)width * 0.75f, (float)height - 25.0f, VulkanTextOverlay::alignCenter); + } + } }; VulkanExample *vulkanExample; @@ -1304,15 +1285,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (vulkanExample != NULL) { vulkanExample->handleMessages(hWnd, uMsg, wParam, lParam); - if (uMsg == WM_KEYDOWN) - { - switch (wParam) - { - case 0x44: - vulkanExample->toggleDebugDisplay(); - break; - } - } } return (DefWindowProc(hWnd, uMsg, wParam, lParam)); }