Added sampler and (default) render pass creation functions to framebuffer class
This commit is contained in:
parent
8b785a539f
commit
47bd9d62e2
1 changed files with 153 additions and 13 deletions
|
|
@ -27,6 +27,8 @@ namespace vk
|
||||||
VkImageView view;
|
VkImageView view;
|
||||||
VkFormat format;
|
VkFormat format;
|
||||||
VkImageSubresourceRange subresourceRange;
|
VkImageSubresourceRange subresourceRange;
|
||||||
|
VkAttachmentDescription description;
|
||||||
|
VkImageLayout initialLayout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns true if the attachment has a depth component
|
* @brief Returns true if the attachment has a depth component
|
||||||
|
|
@ -59,6 +61,15 @@ namespace vk
|
||||||
};
|
};
|
||||||
return std::find(formats.begin(), formats.end(), format) != std::end(formats);
|
return std::find(formats.begin(), formats.end(), format) != std::end(formats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if the attachment is a depth and/or stencil attachment
|
||||||
|
*/
|
||||||
|
bool isDepthStencil()
|
||||||
|
{
|
||||||
|
return(hasDepth() || hasStencil());
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -69,10 +80,7 @@ namespace vk
|
||||||
uint32_t width, height;
|
uint32_t width, height;
|
||||||
uint32_t layerCount;
|
uint32_t layerCount;
|
||||||
VkFormat format;
|
VkFormat format;
|
||||||
// todo: could be derived from format
|
|
||||||
VkImageUsageFlags usage;
|
VkImageUsageFlags usage;
|
||||||
// todo: rename
|
|
||||||
bool sample;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -101,19 +109,20 @@ namespace vk
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy and free resources used for the framebuffer and all of it's attachments
|
* Destroy and free Vulkan resources used for the framebuffer and all of it's attachments
|
||||||
*/
|
*/
|
||||||
void FreeResources(VkDevice device)
|
~Framebuffer()
|
||||||
{
|
{
|
||||||
|
assert(vulkanDevice);
|
||||||
for (auto attachment : attachments)
|
for (auto attachment : attachments)
|
||||||
{
|
{
|
||||||
vkDestroyImage(device, attachment.image, nullptr);
|
vkDestroyImage(vulkanDevice->device, attachment.image, nullptr);
|
||||||
vkDestroyImageView(device, attachment.view, nullptr);
|
vkDestroyImageView(vulkanDevice->device, attachment.view, nullptr);
|
||||||
vkFreeMemory(device, attachment.memory, nullptr);
|
vkFreeMemory(vulkanDevice->device, attachment.memory, nullptr);
|
||||||
}
|
}
|
||||||
vkDestroySampler(device, sampler, nullptr);
|
vkDestroySampler(vulkanDevice->device, sampler, nullptr);
|
||||||
vkDestroyRenderPass(device, renderPass, nullptr);
|
vkDestroyRenderPass(vulkanDevice->device, renderPass, nullptr);
|
||||||
vkDestroyFramebuffer(device, framebuffer, nullptr);
|
vkDestroyFramebuffer(vulkanDevice->device, framebuffer, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -134,12 +143,16 @@ namespace vk
|
||||||
VkImageLayout imageLayout;
|
VkImageLayout imageLayout;
|
||||||
|
|
||||||
// Select aspect mask and layout depending on usage
|
// Select aspect mask and layout depending on usage
|
||||||
|
|
||||||
|
// Color attachment
|
||||||
if (createinfo.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
|
if (createinfo.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
|
||||||
{
|
{
|
||||||
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
imageLayout = createinfo.sample ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
imageLayout = (createinfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Depth (and/or stencil) attachment
|
||||||
if (createinfo.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
if (createinfo.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
||||||
{
|
{
|
||||||
if (attachment.hasDepth())
|
if (attachment.hasDepth())
|
||||||
|
|
@ -150,7 +163,8 @@ namespace vk
|
||||||
{
|
{
|
||||||
aspectMask = aspectMask | VK_IMAGE_ASPECT_STENCIL_BIT;
|
aspectMask = aspectMask | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
}
|
}
|
||||||
imageLayout = createinfo.sample ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
attachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
imageLayout = (createinfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(aspectMask > 0);
|
assert(aspectMask > 0);
|
||||||
|
|
@ -202,9 +216,135 @@ namespace vk
|
||||||
imageView.image = attachment.image;
|
imageView.image = attachment.image;
|
||||||
VK_CHECK_RESULT(vkCreateImageView(vulkanDevice->device, &imageView, nullptr, &attachment.view));
|
VK_CHECK_RESULT(vkCreateImageView(vulkanDevice->device, &imageView, nullptr, &attachment.view));
|
||||||
|
|
||||||
|
// Fill attachment description
|
||||||
|
attachment.description = {};
|
||||||
|
attachment.description.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
attachment.description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
|
attachment.description.storeOp = (createinfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
attachment.description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
attachment.description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
attachment.description.format = createinfo.format;
|
||||||
|
if (attachment.hasDepth() || attachment.hasStencil())
|
||||||
|
{
|
||||||
|
attachment.description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
attachment.description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attachment.description.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
attachment.description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
}
|
||||||
|
|
||||||
attachments.push_back(attachment);
|
attachments.push_back(attachment);
|
||||||
|
|
||||||
return static_cast<uint32_t>(attachments.size() - 1);
|
return static_cast<uint32_t>(attachments.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a default sampler for sampling from any of the framebuffer attachments
|
||||||
|
* Applications are free to create their own samplers for different use cases
|
||||||
|
*
|
||||||
|
* @param magFilter Magnification filter for lookups
|
||||||
|
* @param minFilter Minification filter for lookups
|
||||||
|
* @param adressMode Adressing mode for the U,V and W coordinates
|
||||||
|
*
|
||||||
|
* @return VkResult for the sampler creation
|
||||||
|
*/
|
||||||
|
VkResult createSampler(VkFilter magFilter, VkFilter minFilter, VkSamplerAddressMode adressMode)
|
||||||
|
{
|
||||||
|
VkSamplerCreateInfo samplerInfo = vkTools::initializers::samplerCreateInfo();
|
||||||
|
samplerInfo.magFilter = magFilter;
|
||||||
|
samplerInfo.minFilter = minFilter;
|
||||||
|
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||||
|
samplerInfo.addressModeU = adressMode;
|
||||||
|
samplerInfo.addressModeV = adressMode;
|
||||||
|
samplerInfo.addressModeW = adressMode;
|
||||||
|
samplerInfo.mipLodBias = 0.0f;
|
||||||
|
samplerInfo.maxAnisotropy = 0;
|
||||||
|
samplerInfo.minLod = 0.0f;
|
||||||
|
samplerInfo.maxLod = 1.0f;
|
||||||
|
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||||
|
return vkCreateSampler(vulkanDevice->device, &samplerInfo, nullptr, &sampler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a default render pass setup with one sub pass
|
||||||
|
*
|
||||||
|
* @return VK_SUCCESS if all resources have been created successfully
|
||||||
|
*/
|
||||||
|
VkResult createRenderPass()
|
||||||
|
{
|
||||||
|
std::vector<VkAttachmentDescription> attachmentDescriptions;
|
||||||
|
for (auto& attachment : attachments)
|
||||||
|
{
|
||||||
|
attachmentDescriptions.push_back(attachment.description);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Collect attachment references
|
||||||
|
std::vector<VkAttachmentReference> colorReferences;
|
||||||
|
VkAttachmentReference depthReference = {};
|
||||||
|
bool hasDepth = false;
|
||||||
|
bool hasColor = false;
|
||||||
|
|
||||||
|
uint32_t attachmentIndex = 0;
|
||||||
|
|
||||||
|
for (auto& attachment : attachments)
|
||||||
|
{
|
||||||
|
if (attachment.isDepthStencil())
|
||||||
|
{
|
||||||
|
// Only one depth attachment allowed
|
||||||
|
assert(!hasDepth);
|
||||||
|
depthReference.attachment = attachmentIndex;
|
||||||
|
depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
hasDepth = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colorReferences.push_back({ attachmentIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
|
||||||
|
hasColor = true;
|
||||||
|
}
|
||||||
|
attachmentIndex++;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Default render pass setup uses only one subpass
|
||||||
|
VkSubpassDescription subpass = {};
|
||||||
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
|
if (hasColor)
|
||||||
|
{
|
||||||
|
subpass.pColorAttachments = colorReferences.data();
|
||||||
|
subpass.colorAttachmentCount = static_cast<uint32_t>(colorReferences.size());
|
||||||
|
}
|
||||||
|
if (hasDepth)
|
||||||
|
{
|
||||||
|
subpass.pDepthStencilAttachment = &depthReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create render pass
|
||||||
|
VkRenderPassCreateInfo renderPassInfo = {};
|
||||||
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
|
renderPassInfo.pAttachments = attachmentDescriptions.data();
|
||||||
|
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachmentDescriptions.size());
|
||||||
|
renderPassInfo.subpassCount = 1;
|
||||||
|
renderPassInfo.pSubpasses = &subpass;
|
||||||
|
VK_CHECK_RESULT(vkCreateRenderPass(vulkanDevice->device, &renderPassInfo, nullptr, &renderPass));
|
||||||
|
|
||||||
|
std::vector<VkImageView> attachmentViews;
|
||||||
|
for (auto attachment : attachments)
|
||||||
|
{
|
||||||
|
attachmentViews.push_back(attachment.view);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkFramebufferCreateInfo framebufferInfo = {};
|
||||||
|
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||||
|
framebufferInfo.renderPass = renderPass;
|
||||||
|
framebufferInfo.pAttachments = attachmentViews.data();
|
||||||
|
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachmentViews.size());
|
||||||
|
framebufferInfo.width = width;
|
||||||
|
framebufferInfo.height = height;
|
||||||
|
framebufferInfo.layers = 1;
|
||||||
|
VK_CHECK_RESULT(vkCreateFramebuffer(vulkanDevice->device, &framebufferInfo, nullptr, &framebuffer));
|
||||||
|
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue