Properly resize attachments and update descriptor sets

Refs #414
Refs #659
This commit is contained in:
Sascha Willems 2020-02-05 20:49:18 +01:00
parent 825227a067
commit 3977935d94

View file

@ -33,7 +33,6 @@
#include "VulkanTexture.hpp" #include "VulkanTexture.hpp"
#include "VulkanModel.hpp" #include "VulkanModel.hpp"
#define VERTEX_BUFFER_BIND_ID 0
#define ENABLE_VALIDATION false #define ENABLE_VALIDATION false
#define NUM_LIGHTS 64 #define NUM_LIGHTS 64
@ -112,13 +111,15 @@ public:
// G-Buffer framebuffer attachments // G-Buffer framebuffer attachments
struct FrameBufferAttachment { struct FrameBufferAttachment {
VkImage image; VkImage image = VK_NULL_HANDLE;
VkDeviceMemory mem; VkDeviceMemory mem = VK_NULL_HANDLE;
VkImageView view; VkImageView view = VK_NULL_HANDLE;
VkFormat format; VkFormat format;
}; };
struct Attachments { struct Attachments {
FrameBufferAttachment position, normal, albedo; FrameBufferAttachment position, normal, albedo;
int32_t width;
int32_t height;
} attachments; } attachments;
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
@ -140,19 +141,6 @@ public:
{ {
// Clean up used Vulkan resources // Clean up used Vulkan resources
// Note : Inherited destructor cleans up resources stored in base class // Note : Inherited destructor cleans up resources stored in base class
vkDestroyImageView(device, attachments.position.view, nullptr);
vkDestroyImage(device, attachments.position.image, nullptr);
vkFreeMemory(device, attachments.position.mem, nullptr);
vkDestroyImageView(device, attachments.normal.view, nullptr);
vkDestroyImage(device, attachments.normal.image, nullptr);
vkFreeMemory(device, attachments.normal.mem, nullptr);
vkDestroyImageView(device, attachments.albedo.view, nullptr);
vkDestroyImage(device, attachments.albedo.image, nullptr);
vkFreeMemory(device, attachments.albedo.mem, nullptr);
vkDestroyPipeline(device, pipelines.offscreen, nullptr); vkDestroyPipeline(device, pipelines.offscreen, nullptr);
vkDestroyPipeline(device, pipelines.composition, nullptr); vkDestroyPipeline(device, pipelines.composition, nullptr);
vkDestroyPipeline(device, pipelines.transparent, nullptr); vkDestroyPipeline(device, pipelines.transparent, nullptr);
@ -165,6 +153,10 @@ public:
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.composition, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.composition, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.transparent, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.transparent, nullptr);
clearAttachment(&attachments.position);
clearAttachment(&attachments.normal);
clearAttachment(&attachments.albedo);
textures.glass.destroy(); textures.glass.destroy();
models.scene.destroy(); models.scene.destroy();
models.transparent.destroy(); models.transparent.destroy();
@ -191,9 +183,20 @@ public:
} }
}; };
void clearAttachment(FrameBufferAttachment* attachment)
{
vkDestroyImageView(device, attachment->view, nullptr);
vkDestroyImage(device, attachment->image, nullptr);
vkFreeMemory(device, attachment->mem, nullptr);
}
// Create a frame buffer attachment // Create a frame buffer attachment
void createAttachment(VkFormat format, VkImageUsageFlags usage, FrameBufferAttachment *attachment) void createAttachment(VkFormat format, VkImageUsageFlags usage, FrameBufferAttachment *attachment)
{ {
if (attachment->image != VK_NULL_HANDLE) {
clearAttachment(attachment);
}
VkImageAspectFlags aspectMask = 0; VkImageAspectFlags aspectMask = 0;
VkImageLayout imageLayout; VkImageLayout imageLayout;
@ -215,14 +218,15 @@ public:
VkImageCreateInfo image = vks::initializers::imageCreateInfo(); VkImageCreateInfo image = vks::initializers::imageCreateInfo();
image.imageType = VK_IMAGE_TYPE_2D; image.imageType = VK_IMAGE_TYPE_2D;
image.format = format; image.format = format;
image.extent.width = width; image.extent.width = attachments.width;
image.extent.height = height; image.extent.height = attachments.height;
image.extent.depth = 1; image.extent.depth = 1;
image.mipLevels = 1; image.mipLevels = 1;
image.arrayLayers = 1; image.arrayLayers = 1;
image.samples = VK_SAMPLE_COUNT_1_BIT; image.samples = VK_SAMPLE_COUNT_1_BIT;
image.tiling = VK_IMAGE_TILING_OPTIMAL; image.tiling = VK_IMAGE_TILING_OPTIMAL;
image.usage = usage | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; // VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT flag is required for input attachments; // VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT flag is required for input attachments
image.usage = usage | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo(); VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo();
@ -256,15 +260,37 @@ public:
createAttachment(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &attachments.albedo); // Albedo (color) createAttachment(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &attachments.albedo); // Albedo (color)
} }
// Override framebuffer setup from base class // Override framebuffer setup from base class, will automatically be called upon setup and if a window is resized
// Deferred components will be used as frame buffer attachments
void setupFrameBuffer() void setupFrameBuffer()
{ {
// If the window is resized, all the framebuffers/attachments used in our composition passes need to be recreated
if (attachments.width != width || attachments.height != height) {
attachments.width = width;
attachments.height = height;
createGBufferAttachments();
// Since the framebuffers/attachments are referred in the descriptor sets, these need to be updated too
// Composition pass
std::vector< VkDescriptorImageInfo> descriptorImageInfos = {
vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.position.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.normal.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.albedo.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
};
std::vector<VkWriteDescriptorSet> writeDescriptorSets;
for (size_t i = 0; i < descriptorImageInfos.size(); i++) {
writeDescriptorSets.push_back(vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, i, &descriptorImageInfos[i]));
}
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
// Forward pass
writeDescriptorSets = {
vks::initializers::writeDescriptorSet(descriptorSets.transparent, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, &descriptorImageInfos[0]),
};
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
}
VkImageView attachments[5]; VkImageView attachments[5];
VkFramebufferCreateInfo frameBufferCreateInfo = {}; VkFramebufferCreateInfo frameBufferCreateInfo = {};
frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
frameBufferCreateInfo.pNext = NULL;
frameBufferCreateInfo.renderPass = renderPass; frameBufferCreateInfo.renderPass = renderPass;
frameBufferCreateInfo.attachmentCount = 5; frameBufferCreateInfo.attachmentCount = 5;
frameBufferCreateInfo.pAttachments = attachments; frameBufferCreateInfo.pAttachments = attachments;
@ -288,6 +314,9 @@ public:
// Override render pass setup from base class // Override render pass setup from base class
void setupRenderPass() void setupRenderPass()
{ {
attachments.width = width;
attachments.height = height;
createGBufferAttachments(); createGBufferAttachments();
std::array<VkAttachmentDescription, 5> attachments{}; std::array<VkAttachmentDescription, 5> attachments{};
@ -483,7 +512,7 @@ public:
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.offscreen); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.offscreen);
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.offscreen, 0, 1, &descriptorSets.scene, 0, NULL); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.offscreen, 0, 1, &descriptorSets.scene, 0, NULL);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &models.scene.vertices.buffer, offsets); vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &models.scene.vertices.buffer, offsets);
vkCmdBindIndexBuffer(drawCmdBuffers[i], models.scene.indices.buffer, 0, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(drawCmdBuffers[i], models.scene.indices.buffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(drawCmdBuffers[i], models.scene.indexCount, 1, 0, 0, 0); vkCmdDrawIndexed(drawCmdBuffers[i], models.scene.indexCount, 1, 0, 0, 0);
@ -513,7 +542,7 @@ public:
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.transparent); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.transparent);
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.transparent, 0, 1, &descriptorSets.transparent, 0, NULL); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.transparent, 0, 1, &descriptorSets.transparent, 0, NULL);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &models.transparent.vertices.buffer, offsets); vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &models.transparent.vertices.buffer, offsets);
vkCmdBindIndexBuffer(drawCmdBuffers[i], models.transparent.indices.buffer, 0, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(drawCmdBuffers[i], models.transparent.indices.buffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(drawCmdBuffers[i], models.transparent.indexCount, 1, 0, 0, 0); vkCmdDrawIndexed(drawCmdBuffers[i], models.transparent.indexCount, 1, 0, 0, 0);
@ -552,7 +581,7 @@ public:
// Binding description // Binding description
vertices.bindingDescriptions = { vertices.bindingDescriptions = {
vks::initializers::vertexInputBindingDescription( vks::initializers::vertexInputBindingDescription(
VERTEX_BUFFER_BIND_ID, 0,
vertexLayout.stride(), vertexLayout.stride(),
VK_VERTEX_INPUT_RATE_VERTEX), VK_VERTEX_INPUT_RATE_VERTEX),
}; };
@ -560,29 +589,13 @@ public:
// Attribute descriptions // Attribute descriptions
vertices.attributeDescriptions = { vertices.attributeDescriptions = {
// Location 0: Position // Location 0: Position
vks::initializers::vertexInputAttributeDescription( vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0),
VERTEX_BUFFER_BIND_ID,
0,
VK_FORMAT_R32G32B32_SFLOAT,
0),
// Location 1: Color // Location 1: Color
vks::initializers::vertexInputAttributeDescription( vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3),
VERTEX_BUFFER_BIND_ID,
1,
VK_FORMAT_R32G32B32_SFLOAT,
sizeof(float) * 3),
// Location 2: Normal // Location 2: Normal
vks::initializers::vertexInputAttributeDescription( vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 6),
VERTEX_BUFFER_BIND_ID,
2,
VK_FORMAT_R32G32B32_SFLOAT,
sizeof(float) * 6),
// Location 3: UV // Location 3: UV
vks::initializers::vertexInputAttributeDescription( vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32_SFLOAT, sizeof(float) * 9),
VERTEX_BUFFER_BIND_ID,
3,
VK_FORMAT_R32G32_SFLOAT,
sizeof(float) * 9),
}; };
vertices.inputState = vks::initializers::pipelineVertexInputStateCreateInfo(); vertices.inputState = vks::initializers::pipelineVertexInputStateCreateInfo();
@ -796,49 +809,19 @@ public:
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.composition)); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.composition));
// Image descriptors for the offscreen color attachments // Image descriptors for the offscreen color attachments
VkDescriptorImageInfo texDescriptorPosition = VkDescriptorImageInfo texDescriptorPosition = vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.position.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
vks::initializers::descriptorImageInfo( VkDescriptorImageInfo texDescriptorNormal = vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.normal.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
VK_NULL_HANDLE, VkDescriptorImageInfo texDescriptorAlbedo = vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, attachments.albedo.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
attachments.position.view,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
VkDescriptorImageInfo texDescriptorNormal =
vks::initializers::descriptorImageInfo(
VK_NULL_HANDLE,
attachments.normal.view,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
VkDescriptorImageInfo texDescriptorAlbedo =
vks::initializers::descriptorImageInfo(
VK_NULL_HANDLE,
attachments.albedo.view,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
std::vector<VkWriteDescriptorSet> writeDescriptorSets = { std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
// Binding 0: Position texture target // Binding 0: Position texture target
vks::initializers::writeDescriptorSet( vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 0, &texDescriptorPosition),
descriptorSets.composition,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
0,
&texDescriptorPosition),
// Binding 1: Normals texture target // Binding 1: Normals texture target
vks::initializers::writeDescriptorSet( vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, &texDescriptorNormal),
descriptorSets.composition,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
1,
&texDescriptorNormal),
// Binding 2: Albedo texture target // Binding 2: Albedo texture target
vks::initializers::writeDescriptorSet( vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2, &texDescriptorAlbedo),
descriptorSets.composition,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
2,
&texDescriptorAlbedo),
// Binding 4: Fragment shader lights // Binding 4: Fragment shader lights
vks::initializers::writeDescriptorSet( vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3, &uniformBuffers.lights.descriptor),
descriptorSets.composition,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
3,
&uniformBuffers.lights.descriptor),
}; };
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);