diff --git a/examples/deferred/deferred.cpp b/examples/deferred/deferred.cpp index f7e03692..06129643 100644 --- a/examples/deferred/deferred.cpp +++ b/examples/deferred/deferred.cpp @@ -36,12 +36,12 @@ public: vkglTF::Model floor; } models; - struct { + struct UniformDataOffscreen { glm::mat4 projection; glm::mat4 model; glm::mat4 view; glm::vec4 instancePos[3]; - } uboOffscreenVS; + } uniformDataOffscreen; struct Light { glm::vec4 position; @@ -49,11 +49,11 @@ public: float radius; }; - struct { + struct UniformDataComposition { Light lights[6]; glm::vec4 viewPos; int debugDisplayTarget = 0; - } uboComposition; + } uniformDataComposition; struct { vks::Buffer offscreen{ VK_NULL_HANDLE }; @@ -583,8 +583,8 @@ public: void preparePipelines() { // Pipeline layout - VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); // Pipelines VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); @@ -648,19 +648,19 @@ public: void prepareUniformBuffers() { // Offscreen vertex shader - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.offscreen, sizeof(uboOffscreenVS))); + VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.offscreen, sizeof(UniformDataOffscreen))); // Deferred fragment shader - VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.composition, sizeof(uboComposition))); + VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.composition, sizeof(UniformDataComposition))); // Map persistent VK_CHECK_RESULT(uniformBuffers.offscreen.map()); VK_CHECK_RESULT(uniformBuffers.composition.map()); // Setup instanced model positions - uboOffscreenVS.instancePos[0] = glm::vec4(0.0f); - uboOffscreenVS.instancePos[1] = glm::vec4(-4.0f, 0.0, -4.0f, 0.0f); - uboOffscreenVS.instancePos[2] = glm::vec4(4.0f, 0.0, -4.0f, 0.0f); + uniformDataOffscreen.instancePos[0] = glm::vec4(0.0f); + uniformDataOffscreen.instancePos[1] = glm::vec4(-4.0f, 0.0, -4.0f, 0.0f); + uniformDataOffscreen.instancePos[2] = glm::vec4(4.0f, 0.0, -4.0f, 0.0f); // Update updateUniformBufferOffscreen(); @@ -670,64 +670,64 @@ public: // Update matrices used for the offscreen rendering of the scene void updateUniformBufferOffscreen() { - uboOffscreenVS.projection = camera.matrices.perspective; - uboOffscreenVS.view = camera.matrices.view; - uboOffscreenVS.model = glm::mat4(1.0f); - memcpy(uniformBuffers.offscreen.mapped, &uboOffscreenVS, sizeof(uboOffscreenVS)); + uniformDataOffscreen.projection = camera.matrices.perspective; + uniformDataOffscreen.view = camera.matrices.view; + uniformDataOffscreen.model = glm::mat4(1.0f); + memcpy(uniformBuffers.offscreen.mapped, &uniformDataOffscreen, sizeof(UniformDataOffscreen)); } // Update lights and parameters passed to the composition shaders void updateUniformBufferComposition() { // White - uboComposition.lights[0].position = glm::vec4(0.0f, 0.0f, 1.0f, 0.0f); - uboComposition.lights[0].color = glm::vec3(1.5f); - uboComposition.lights[0].radius = 15.0f * 0.25f; + uniformDataComposition.lights[0].position = glm::vec4(0.0f, 0.0f, 1.0f, 0.0f); + uniformDataComposition.lights[0].color = glm::vec3(1.5f); + uniformDataComposition.lights[0].radius = 15.0f * 0.25f; // Red - uboComposition.lights[1].position = glm::vec4(-2.0f, 0.0f, 0.0f, 0.0f); - uboComposition.lights[1].color = glm::vec3(1.0f, 0.0f, 0.0f); - uboComposition.lights[1].radius = 15.0f; + uniformDataComposition.lights[1].position = glm::vec4(-2.0f, 0.0f, 0.0f, 0.0f); + uniformDataComposition.lights[1].color = glm::vec3(1.0f, 0.0f, 0.0f); + uniformDataComposition.lights[1].radius = 15.0f; // Blue - uboComposition.lights[2].position = glm::vec4(2.0f, -1.0f, 0.0f, 0.0f); - uboComposition.lights[2].color = glm::vec3(0.0f, 0.0f, 2.5f); - uboComposition.lights[2].radius = 5.0f; + uniformDataComposition.lights[2].position = glm::vec4(2.0f, -1.0f, 0.0f, 0.0f); + uniformDataComposition.lights[2].color = glm::vec3(0.0f, 0.0f, 2.5f); + uniformDataComposition.lights[2].radius = 5.0f; // Yellow - uboComposition.lights[3].position = glm::vec4(0.0f, -0.9f, 0.5f, 0.0f); - uboComposition.lights[3].color = glm::vec3(1.0f, 1.0f, 0.0f); - uboComposition.lights[3].radius = 2.0f; + uniformDataComposition.lights[3].position = glm::vec4(0.0f, -0.9f, 0.5f, 0.0f); + uniformDataComposition.lights[3].color = glm::vec3(1.0f, 1.0f, 0.0f); + uniformDataComposition.lights[3].radius = 2.0f; // Green - uboComposition.lights[4].position = glm::vec4(0.0f, -0.5f, 0.0f, 0.0f); - uboComposition.lights[4].color = glm::vec3(0.0f, 1.0f, 0.2f); - uboComposition.lights[4].radius = 5.0f; + uniformDataComposition.lights[4].position = glm::vec4(0.0f, -0.5f, 0.0f, 0.0f); + uniformDataComposition.lights[4].color = glm::vec3(0.0f, 1.0f, 0.2f); + uniformDataComposition.lights[4].radius = 5.0f; // Yellow - uboComposition.lights[5].position = glm::vec4(0.0f, -1.0f, 0.0f, 0.0f); - uboComposition.lights[5].color = glm::vec3(1.0f, 0.7f, 0.3f); - uboComposition.lights[5].radius = 25.0f; + uniformDataComposition.lights[5].position = glm::vec4(0.0f, -1.0f, 0.0f, 0.0f); + uniformDataComposition.lights[5].color = glm::vec3(1.0f, 0.7f, 0.3f); + uniformDataComposition.lights[5].radius = 25.0f; // Animate the lights if (!paused) { - uboComposition.lights[0].position.x = sin(glm::radians(360.0f * timer)) * 5.0f; - uboComposition.lights[0].position.z = cos(glm::radians(360.0f * timer)) * 5.0f; + uniformDataComposition.lights[0].position.x = sin(glm::radians(360.0f * timer)) * 5.0f; + uniformDataComposition.lights[0].position.z = cos(glm::radians(360.0f * timer)) * 5.0f; - uboComposition.lights[1].position.x = -4.0f + sin(glm::radians(360.0f * timer) + 45.0f) * 2.0f; - uboComposition.lights[1].position.z = 0.0f + cos(glm::radians(360.0f * timer) + 45.0f) * 2.0f; + uniformDataComposition.lights[1].position.x = -4.0f + sin(glm::radians(360.0f * timer) + 45.0f) * 2.0f; + uniformDataComposition.lights[1].position.z = 0.0f + cos(glm::radians(360.0f * timer) + 45.0f) * 2.0f; - uboComposition.lights[2].position.x = 4.0f + sin(glm::radians(360.0f * timer)) * 2.0f; - uboComposition.lights[2].position.z = 0.0f + cos(glm::radians(360.0f * timer)) * 2.0f; + uniformDataComposition.lights[2].position.x = 4.0f + sin(glm::radians(360.0f * timer)) * 2.0f; + uniformDataComposition.lights[2].position.z = 0.0f + cos(glm::radians(360.0f * timer)) * 2.0f; - uboComposition.lights[4].position.x = 0.0f + sin(glm::radians(360.0f * timer + 90.0f)) * 5.0f; - uboComposition.lights[4].position.z = 0.0f - cos(glm::radians(360.0f * timer + 45.0f)) * 5.0f; + uniformDataComposition.lights[4].position.x = 0.0f + sin(glm::radians(360.0f * timer + 90.0f)) * 5.0f; + uniformDataComposition.lights[4].position.z = 0.0f - cos(glm::radians(360.0f * timer + 45.0f)) * 5.0f; - uboComposition.lights[5].position.x = 0.0f + sin(glm::radians(-360.0f * timer + 135.0f)) * 10.0f; - uboComposition.lights[5].position.z = 0.0f - cos(glm::radians(-360.0f * timer - 45.0f)) * 10.0f; + uniformDataComposition.lights[5].position.x = 0.0f + sin(glm::radians(-360.0f * timer + 135.0f)) * 10.0f; + uniformDataComposition.lights[5].position.z = 0.0f - cos(glm::radians(-360.0f * timer - 45.0f)) * 10.0f; } // Current view position - uboComposition.viewPos = glm::vec4(camera.position, 0.0f) * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f); + uniformDataComposition.viewPos = glm::vec4(camera.position, 0.0f) * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f); - uboComposition.debugDisplayTarget = debugDisplayTarget; + uniformDataComposition.debugDisplayTarget = debugDisplayTarget; - memcpy(uniformBuffers.composition.mapped, &uboComposition, sizeof(uboComposition)); + memcpy(uniformBuffers.composition.mapped, &uniformDataComposition, sizeof(UniformDataComposition)); } void prepare() diff --git a/examples/deferredmultisampling/deferredmultisampling.cpp b/examples/deferredmultisampling/deferredmultisampling.cpp index 25b3c024..bc83546c 100644 --- a/examples/deferredmultisampling/deferredmultisampling.cpp +++ b/examples/deferredmultisampling/deferredmultisampling.cpp @@ -1,7 +1,9 @@ /* * Vulkan Example - Multi sampling with explicit resolve for deferred shading example * -* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de +* This sample adds hardware accelerated multi sampling to the deferred rendering sample +* +* Copyright (C) 2023 by Sascha Willems - www.saschawillems.de * * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) */ @@ -10,14 +12,6 @@ #include "VulkanFrameBuffer.hpp" #include "VulkanglTFModel.h" - -#if defined(__ANDROID__) -// Use max. screen dimension as deferred framebuffer size -#define FB_DIM std::max(width,height) -#else -#define FB_DIM 2048 -#endif - class VulkanExample : public VulkanExampleBase { public: @@ -42,12 +36,12 @@ public: vkglTF::Model background; } models; - struct { + struct UniformDataOffscreen { glm::mat4 projection; glm::mat4 model; glm::mat4 view; glm::vec4 instancePos[3]; - } uboOffscreenVS; + } uniformDataOffscreen; struct Light { glm::vec4 position; @@ -55,39 +49,39 @@ public: float radius; }; - struct { + struct UniformDataComposition { Light lights[6]; glm::vec4 viewPos; int32_t debugDisplayTarget = 0; - } uboComposition; + } uniformDataComposition; struct { - vks::Buffer offscreen; - vks::Buffer composition; + vks::Buffer offscreen{ VK_NULL_HANDLE }; + vks::Buffer composition{ VK_NULL_HANDLE }; } uniformBuffers; struct { - VkPipeline deferred; // Deferred lighting calculation - VkPipeline deferredNoMSAA; // Deferred lighting calculation with explicit MSAA resolve - VkPipeline offscreen; // (Offscreen) scene rendering (fill G-Buffers) - VkPipeline offscreenSampleShading; // (Offscreen) scene rendering (fill G-Buffers) with sample shading rate enabled + VkPipeline deferred{ VK_NULL_HANDLE }; // Deferred lighting calculation + VkPipeline deferredNoMSAA{ VK_NULL_HANDLE }; // Deferred lighting calculation with explicit MSAA resolve + VkPipeline offscreen{ VK_NULL_HANDLE }; // (Offscreen) scene rendering (fill G-Buffers) + VkPipeline offscreenSampleShading{ VK_NULL_HANDLE }; // (Offscreen) scene rendering (fill G-Buffers) with sample shading rate enabled } pipelines; - VkPipelineLayout pipelineLayout; + VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; struct { - VkDescriptorSet model; - VkDescriptorSet background; - } descriptorSets; + VkDescriptorSet model{ VK_NULL_HANDLE }; + VkDescriptorSet background{ VK_NULL_HANDLE }; + VkDescriptorSet composition{ VK_NULL_HANDLE }; + } descriptorSets{ VK_NULL_HANDLE }; - VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; + VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - vks::Framebuffer* offscreenframeBuffers; + vks::Framebuffer* offscreenframeBuffers{}; - VkCommandBuffer offScreenCmdBuffer = VK_NULL_HANDLE; + VkCommandBuffer offScreenCmdBuffer{ VK_NULL_HANDLE }; // Semaphore used to synchronize between offscreen and final scene rendering - VkSemaphore offscreenSemaphore = VK_NULL_HANDLE; + VkSemaphore offscreenSemaphore{ VK_NULL_HANDLE }; VulkanExample() : VulkanExampleBase() { @@ -105,34 +99,32 @@ public: ~VulkanExample() { - // Clean up used Vulkan resources - // Note : Inherited destructor cleans up resources stored in base class + if (device) { + // Frame buffers + if (offscreenframeBuffers) { + delete offscreenframeBuffers; + } - // Frame buffers - if (offscreenframeBuffers) - { - delete offscreenframeBuffers; + vkDestroyPipeline(device, pipelines.deferred, nullptr); + vkDestroyPipeline(device, pipelines.deferredNoMSAA, nullptr); + vkDestroyPipeline(device, pipelines.offscreen, nullptr); + vkDestroyPipeline(device, pipelines.offscreenSampleShading, nullptr); + + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + + // Uniform buffers + uniformBuffers.offscreen.destroy(); + uniformBuffers.composition.destroy(); + + textures.model.colorMap.destroy(); + textures.model.normalMap.destroy(); + textures.background.colorMap.destroy(); + textures.background.normalMap.destroy(); + + vkDestroySemaphore(device, offscreenSemaphore, nullptr); } - - vkDestroyPipeline(device, pipelines.deferred, nullptr); - vkDestroyPipeline(device, pipelines.deferredNoMSAA, nullptr); - vkDestroyPipeline(device, pipelines.offscreen, nullptr); - vkDestroyPipeline(device, pipelines.offscreenSampleShading, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - // Uniform buffers - uniformBuffers.offscreen.destroy(); - uniformBuffers.composition.destroy(); - - textures.model.colorMap.destroy(); - textures.model.normalMap.destroy(); - textures.background.colorMap.destroy(); - textures.background.normalMap.destroy(); - - vkDestroySemaphore(device, offscreenSemaphore, nullptr); } // Enable physical device features required for this example @@ -153,13 +145,19 @@ public: { offscreenframeBuffers = new vks::Framebuffer(vulkanDevice); - offscreenframeBuffers->width = FB_DIM; - offscreenframeBuffers->height = FB_DIM; +#if defined(__ANDROID__) + // Use max. screen dimension as deferred framebuffer size + offscreenframeBuffers->width = std::max(width, height); + offscreenframeBuffers->height = std::max(width, height); +#else + offscreenframeBuffers->width = 2048; + offscreenframeBuffers->height = 2048; +#endif // Four attachments (3 color, 1 depth) vks::AttachmentCreateInfo attachmentInfo = {}; - attachmentInfo.width = FB_DIM; - attachmentInfo.height = FB_DIM; + attachmentInfo.width = offscreenframeBuffers->width; + attachmentInfo.height = offscreenframeBuffers->height; attachmentInfo.layerCount = 1; attachmentInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; attachmentInfo.imageSampleCount = sampleCount; @@ -281,7 +279,7 @@ public: VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.composition, 0, nullptr); // Final composition as full screen quad // Note: Also used for debug display if debugDisplayTarget > 0 @@ -307,19 +305,17 @@ public: textures.background.normalMap.loadFromFile(getAssetPath() + "textures/stonefloor02_normal_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); } - void setupDescriptorPool() + void setupDescriptors() { + // Pool std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 8), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 9) }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - } - void setupDescriptorSetLayout() - { + // Layout // Deferred shading layout std::vector setLayoutBindings = { // Binding 0 : Vertex shader uniform buffer @@ -333,17 +329,10 @@ public: // Binding 4 : Fragment shader uniform buffer vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 4), }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - // Shared pipeline layout used by all pipelines - VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - } - - void setupDescriptorSet() - { + // Sets std::vector writeDescriptorSets; VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); @@ -367,18 +356,18 @@ public: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); // Deferred composition - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.composition)); writeDescriptorSets = { // Binding 1: World space position texture - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &texDescriptorPosition), + vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &texDescriptorPosition), // Binding 2: World space normals texture - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &texDescriptorNormal), + vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &texDescriptorNormal), // Binding 3: Albedo texture - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3, &texDescriptorAlbedo), + vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3, &texDescriptorAlbedo), // Binding 4: Fragment shader uniform buffer - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4, &uniformBuffers.composition.descriptor), + vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4, &uniformBuffers.composition.descriptor), }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); + vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); // Offscreen (scene) @@ -409,6 +398,11 @@ public: void preparePipelines() { + // Layout + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + + // Pipelines VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); @@ -502,91 +496,79 @@ public: void prepareUniformBuffers() { // Offscreen vertex shader - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.offscreen, - sizeof(uboOffscreenVS))); - + VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.offscreen, sizeof(UniformDataOffscreen))); // Deferred fragment shader - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.composition, - sizeof(uboComposition)));; - + VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.composition, sizeof(UniformDataComposition)));; // Map persistent VK_CHECK_RESULT(uniformBuffers.offscreen.map()); VK_CHECK_RESULT(uniformBuffers.composition.map()); // Init some values - uboOffscreenVS.instancePos[0] = glm::vec4(0.0f); - uboOffscreenVS.instancePos[1] = glm::vec4(-4.0f, 0.0, -4.0f, 0.0f); - uboOffscreenVS.instancePos[2] = glm::vec4(4.0f, 0.0, -4.0f, 0.0f); + uniformDataOffscreen.instancePos[0] = glm::vec4(0.0f); + uniformDataOffscreen.instancePos[1] = glm::vec4(-4.0f, 0.0, -4.0f, 0.0f); + uniformDataOffscreen.instancePos[2] = glm::vec4(4.0f, 0.0, -4.0f, 0.0f); // Update - updateUniformBufferOffscreen(); - updateUniformBufferDeferredLights(); + updateUniformBufferDeferred(); } void updateUniformBufferOffscreen() { - uboOffscreenVS.projection = camera.matrices.perspective; - uboOffscreenVS.view = camera.matrices.view; - uboOffscreenVS.model = glm::mat4(1.0f); - memcpy(uniformBuffers.offscreen.mapped, &uboOffscreenVS, sizeof(uboOffscreenVS)); + uniformDataOffscreen.projection = camera.matrices.perspective; + uniformDataOffscreen.view = camera.matrices.view; + uniformDataOffscreen.model = glm::mat4(1.0f); + memcpy(uniformBuffers.offscreen.mapped, &uniformDataOffscreen, sizeof(UniformDataOffscreen)); } - // Update fragment shader light position uniform block - void updateUniformBufferDeferredLights() + // Update deferred composition fragment shader light position andparameters uniform block + void updateUniformBufferDeferred() { // White - uboComposition.lights[0].position = glm::vec4(0.0f, 0.0f, 1.0f, 0.0f); - uboComposition.lights[0].color = glm::vec3(1.5f); - uboComposition.lights[0].radius = 15.0f * 0.25f; + uniformDataComposition.lights[0].position = glm::vec4(0.0f, 0.0f, 5.0f, 0.0f); + uniformDataComposition.lights[0].color = glm::vec3(1.5f); + uniformDataComposition.lights[0].radius = 15.0f * 0.25f; // Red - uboComposition.lights[1].position = glm::vec4(-2.0f, 0.0f, 0.0f, 0.0f); - uboComposition.lights[1].color = glm::vec3(1.0f, 0.0f, 0.0f); - uboComposition.lights[1].radius = 15.0f; + uniformDataComposition.lights[1].position = glm::vec4(-2.30f, 0.0f, 1.05f, 0.0f); + uniformDataComposition.lights[1].color = glm::vec3(1.0f, 0.0f, 0.0f); + uniformDataComposition.lights[1].radius = 15.0f; // Blue - uboComposition.lights[2].position = glm::vec4(2.0f, -1.0f, 0.0f, 0.0f); - uboComposition.lights[2].color = glm::vec3(0.0f, 0.0f, 2.5f); - uboComposition.lights[2].radius = 5.0f; + uniformDataComposition.lights[2].position = glm::vec4(4.0f, -1.0f, 2.0f, 0.0f); + uniformDataComposition.lights[2].color = glm::vec3(0.0f, 0.0f, 2.5f); + uniformDataComposition.lights[2].radius = 5.0f; // Yellow - uboComposition.lights[3].position = glm::vec4(0.0f, -0.9f, 0.5f, 0.0f); - uboComposition.lights[3].color = glm::vec3(1.0f, 1.0f, 0.0f); - uboComposition.lights[3].radius = 2.0f; + uniformDataComposition.lights[3].position = glm::vec4(0.0f, -0.9f, 0.5f, 0.0f); + uniformDataComposition.lights[3].color = glm::vec3(1.0f, 1.0f, 0.0f); + uniformDataComposition.lights[3].radius = 2.0f; // Green - uboComposition.lights[4].position = glm::vec4(0.0f, -0.5f, 0.0f, 0.0f); - uboComposition.lights[4].color = glm::vec3(0.0f, 1.0f, 0.2f); - uboComposition.lights[4].radius = 5.0f; + uniformDataComposition.lights[4].position = glm::vec4(5.0f, -0.5f, -3.53f, 0.0f); + uniformDataComposition.lights[4].color = glm::vec3(0.0f, 1.0f, 0.2f); + uniformDataComposition.lights[4].radius = 5.0f; // Yellow - uboComposition.lights[5].position = glm::vec4(0.0f, -1.0f, 0.0f, 0.0f); - uboComposition.lights[5].color = glm::vec3(1.0f, 0.7f, 0.3f); - uboComposition.lights[5].radius = 25.0f; - - uboComposition.lights[0].position.x = sin(glm::radians(360.0f * timer)) * 5.0f; - uboComposition.lights[0].position.z = cos(glm::radians(360.0f * timer)) * 5.0f; - - uboComposition.lights[1].position.x = -4.0f + sin(glm::radians(360.0f * timer) + 45.0f) * 2.0f; - uboComposition.lights[1].position.z = 0.0f + cos(glm::radians(360.0f * timer) + 45.0f) * 2.0f; - - uboComposition.lights[2].position.x = 4.0f + sin(glm::radians(360.0f * timer)) * 2.0f; - uboComposition.lights[2].position.z = 0.0f + cos(glm::radians(360.0f * timer)) * 2.0f; - - uboComposition.lights[4].position.x = 0.0f + sin(glm::radians(360.0f * timer + 90.0f)) * 5.0f; - uboComposition.lights[4].position.z = 0.0f - cos(glm::radians(360.0f * timer + 45.0f)) * 5.0f; - - uboComposition.lights[5].position.x = 0.0f + sin(glm::radians(-360.0f * timer + 135.0f)) * 10.0f; - uboComposition.lights[5].position.z = 0.0f - cos(glm::radians(-360.0f * timer - 45.0f)) * 10.0f; + uniformDataComposition.lights[5].position = glm::vec4(7.07f, -1.0f, 7.07f, 0.0f); + uniformDataComposition.lights[5].color = glm::vec3(1.0f, 0.7f, 0.3f); + uniformDataComposition.lights[5].radius = 25.0f; // Current view position - uboComposition.viewPos = glm::vec4(camera.position, 0.0f) * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f); - uboComposition.debugDisplayTarget = debugDisplayTarget; + uniformDataComposition.viewPos = glm::vec4(camera.position, 0.0f) * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f); + uniformDataComposition.debugDisplayTarget = debugDisplayTarget; - memcpy(uniformBuffers.composition.mapped, &uboComposition, sizeof(uboComposition)); + memcpy(uniformBuffers.composition.mapped, &uniformDataComposition, sizeof(UniformDataComposition)); } + void prepare() + { + VulkanExampleBase::prepare(); + sampleCount = getMaxUsableSampleCount(); + loadAssets(); + deferredSetup(); + prepareUniformBuffers(); + setupDescriptors(); + preparePipelines(); + buildCommandBuffers(); + buildDeferredCommandBuffer(); + prepared = true; + } + void draw() { VulkanExampleBase::prepareFrame(); @@ -617,44 +599,19 @@ public: VulkanExampleBase::submitFrame(); } - void prepare() - { - VulkanExampleBase::prepare(); - sampleCount = getMaxUsableSampleCount(); - loadAssets(); - deferredSetup(); - prepareUniformBuffers(); - setupDescriptorSetLayout(); - preparePipelines(); - setupDescriptorPool(); - setupDescriptorSet(); - buildCommandBuffers(); - buildDeferredCommandBuffer(); - prepared = true; - } - virtual void render() { if (!prepared) return; - draw(); - if (camera.updated) - { - updateUniformBufferOffscreen(); - } - } - - virtual void viewChanged() - { updateUniformBufferOffscreen(); + draw(); } virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { - if (overlay->comboBox("Display", &debugDisplayTarget, { "Final composition", "Position", "Normals", "Albedo", "Specular" })) - { - updateUniformBufferDeferredLights(); + if (overlay->comboBox("Display", &debugDisplayTarget, { "Final composition", "Position", "Normals", "Albedo", "Specular" })) { + updateUniformBufferDeferred(); } if (overlay->checkBox("MSAA", &useMSAA)) { buildCommandBuffers(); @@ -671,9 +628,7 @@ public: VkSampleCountFlagBits getMaxUsableSampleCount() { VkSampleCountFlags counts = std::min(deviceProperties.limits.framebufferColorSampleCounts, deviceProperties.limits.framebufferDepthSampleCounts); - if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; } - if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; } - if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; } + // Note: Vulkan offers up to 64 bits, but we don't want to go higher than 8xMSAA in this sample) if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; } if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; } if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }