#c #graphics #vulkan
Вопрос:
Я пытаюсь повторно использовать вложение глубины из первого прохода визуализации во второй проход визуализации. но он не загружает значения глубины во втором рендерпассе.
//код, создающий вложения
void VulkanRenderTarget::addAttachment(AttachmentCreateInfo createinfo)
{
auto device = mRenderer->getDevice();
Attachment attachment;
attachment.format = createinfo.format;
VkImageAspectFlags aspectMask = 0;
// Select aspect mask and layout depending on usage
// Color attachment
if (createinfo.usage amp; VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
{
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
// Depth (and/or stencil) attachment
if (createinfo.usage amp; VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
{
if (attachment.hasDepth())
{
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
}
if (attachment.hasStencil())
{
aspectMask = aspectMask | VK_IMAGE_ASPECT_STENCIL_BIT;
}
}
assert(aspectMask > 0);
VkImageCreateInfo image = VulkanInitializers::imageCreateInfo();
image.imageType = VK_IMAGE_TYPE_2D;
image.format = createinfo.format;
image.extent.width = createinfo.width;
image.extent.height = createinfo.height;
image.extent.depth = 1;
image.mipLevels = 1;
image.arrayLayers = createinfo.layerCount;
image.samples = createinfo.imageSampleCount;
image.tiling = createinfo.tiling;
image.usage = createinfo.usage;
VkMemoryAllocateInfo memAlloc = VulkanInitializers::memoryAllocateInfo();
VkMemoryRequirements memReqs;
// Create image for this attachment
VERIFY(vkCreateImage(device, amp;image, nullptr, amp;attachment.image));
vkGetImageMemoryRequirements(device, attachment.image, amp;memReqs);
memAlloc.allocationSize = memReqs.size;
memAlloc.memoryTypeIndex = mRenderer->getMemoryType(memReqs.memoryTypeBits, createinfo.memoryFlag);
VERIFY(vkAllocateMemory(device, amp;memAlloc, nullptr, amp;attachment.memory));
VERIFY(vkBindImageMemory(device, attachment.image, attachment.memory, 0));
attachment.subresourceRange = {};
attachment.subresourceRange.aspectMask = aspectMask;
attachment.subresourceRange.levelCount = 1;
attachment.subresourceRange.layerCount = createinfo.layerCount;
VkImageViewCreateInfo imageView = VulkanInitializers::imageViewCreateInfo();
imageView.viewType = (createinfo.layerCount == 1) ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
imageView.format = createinfo.format;
imageView.subresourceRange = attachment.subresourceRange;
//todo: workaround for depth stencil attachments
imageView.subresourceRange.aspectMask = (attachment.hasDepth()) ? VK_IMAGE_ASPECT_DEPTH_BIT : aspectMask;
imageView.image = attachment.image;
VERIFY(vkCreateImageView(device, amp;imageView, nullptr, amp;attachment.view));
// Fill attachment description
attachment.description = {};
attachment.description.samples = createinfo.imageSampleCount;
attachment.description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachment.description.storeOp = (createinfo.usage amp; 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;
attachment.description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
// Final layout
// If not, final layout depends on attachment type
if (attachment.hasDepth() || attachment.hasStencil())
{
attachment.description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
//attachment.description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
}
else
{
attachment.description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
mAttachments.push_back(attachment);
}
///создание первого прохода визуализации
// Four attachments (3 color, 1 depth)
AttachmentCreateInfo attachmentInfo = {};
attachmentInfo.width = mWidth;
attachmentInfo.height = mHeight;
attachmentInfo.layerCount = 1;
attachmentInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
attachmentInfo.imageSampleCount = mRenderer->getMSAAsamples();
// Color attachments
// Attachment 0: (World space) Positions
//attachmentInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;
attachmentInfo.format = VK_FORMAT_R32G32B32A32_SFLOAT;
addAttachment(attachmentInfo);
// Attachment 1: (World space) Normals
attachmentInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
addAttachment(attachmentInfo);
// Attachment 2: Albedo (color)
attachmentInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
addAttachment(attachmentInfo);
//depth
attachmentInfo.format = mRenderer->getDepthFormat();
attachmentInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
addAttachment(attachmentInfo);
{
//create sampler
VkSamplerCreateInfo samplerInfo = VulkanInitializers::samplerCreateInfo();
samplerInfo.magFilter = VK_FILTER_NEAREST;
samplerInfo.minFilter = VK_FILTER_NEAREST;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 1.0f;
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
VERIFY(vkCreateSampler(device, amp;samplerInfo, nullptr, amp;sampler));
}
//create renderpass and frame buffer
{
std::vector<VkAttachmentDescription> attachmentDescriptions;
for (autoamp; attachment : mAttachments)
{
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 (autoamp; attachment : mAttachments)
{
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 = amp;depthReference;
}
// Use subpass dependencies for attachment layout transitions
std::array<VkSubpassDependency, 2> dependencies;
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_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].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
// 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 = amp;subpass;
renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
renderPassInfo.pDependencies = dependencies.data();
VERIFY(vkCreateRenderPass(device, amp;renderPassInfo, nullptr, amp;mRenderPass));
std::vector<VkImageView> attachmentViews;
for (auto attachment : mAttachments)
{
attachmentViews.push_back(attachment.view);
}
// Find. max number of layers across attachments
uint32_t maxLayers = 0;
for (auto attachment : mAttachments)
{
if (attachment.subresourceRange.layerCount > maxLayers)
{
maxLayers = attachment.subresourceRange.layerCount;
}
}
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = mRenderPass;
framebufferInfo.pAttachments = attachmentViews.data();
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachmentViews.size());
framebufferInfo.width = mWidth;
framebufferInfo.height = mHeight;
framebufferInfo.layers = maxLayers;
mFrameBuffers.clear();
mFrameBuffers.resize(1);
VERIFY(vkCreateFramebuffer(device, amp;framebufferInfo, nullptr, amp;mFrameBuffers[0]));
}
///второй рендерпас
finalImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
std::array<VkAttachmentDescription, 3> attachments = {};
// Multisampled attachment that we render to
attachments[0].format = mRenderer->getSCImageFormat();// swapChain.colorFormat;
attachments[0].samples = mRenderer->getMSAAsamples();// settings.sampleCount;
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
// This is the frame buffer attachment to where the multisampled image
// will be resolved to and which will be presented to the swapchain
attachments[1].format = mRenderer->getSCImageFormat();;
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[1].finalLayout = finalImageLayout;
// Multisampled depth attachment we render to
attachments[2].format = mRenderer->getDepthFormat();// depthFormat;
attachments[2].samples = mRenderer->getMSAAsamples();// settings.sampleCount;
attachments[2].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;// VK_ATTACHMENT_LOAD_OP_LOAD; //VK_ATTACHMENT_LOAD_OP_CLEAR; use depth from deferred renderer
attachments[2].storeOp = VK_ATTACHMENT_STORE_OP_STORE;// VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[2].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference colorReference = {};
colorReference.attachment = 0;
colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference depthReference = {};
depthReference.attachment = 2;
depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
// Resolve attachment reference for the color attachment
VkAttachmentReference resolveReference = {};
resolveReference.attachment = 1;
resolveReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = amp;colorReference;
// Pass our resolve attachments to the sub pass
subpass.pResolveAttachments = amp;resolveReference;
subpass.pDepthStencilAttachment = amp;depthReference;
std::vector<VkSubpassDependency> dependencies;
dependencies.resize(2);
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; // Both stages might have access the depth-buffer, so need both in src/dstStageMask;;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_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;
VkRenderPassCreateInfo renderPassCI = {};
renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassCI.attachmentCount = static_cast<uint32_t>(attachments.size());
renderPassCI.pAttachments = attachments.data();
renderPassCI.subpassCount = 1;
renderPassCI.pSubpasses = amp;subpass;
renderPassCI.dependencyCount = static_cast<uint32_t>(dependencies.size());
renderPassCI.pDependencies = dependencies.data();
VERIFY(vkCreateRenderPass(device, amp;renderPassCI, nullptr, amp;mRenderPass));
VkImageCreateInfo imageCI{};
imageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCI.imageType = VK_IMAGE_TYPE_2D;
imageCI.format = mRenderer->getSCImageFormat();// swapChain.colorFormat;
imageCI.extent.width = mWidth;// width;
imageCI.extent.height = mHeight;
imageCI.extent.depth = 1;
imageCI.mipLevels = 1;
imageCI.arrayLayers = 1;
imageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCI.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCI.samples = mRenderer->getMSAAsamples();// settings.sampleCount;
imageCI.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VERIFY(vkCreateImage(device, amp;imageCI, nullptr, amp;multisampleTarget.color.image));
VkMemoryRequirements memReqs;
vkGetImageMemoryRequirements(device, multisampleTarget.color.image, amp;memReqs);
VkMemoryAllocateInfo memAllocInfo{};
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memAllocInfo.allocationSize = memReqs.size;
VkBool32 lazyMemTypePresent;
memAllocInfo.memoryTypeIndex = mRenderer->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, amp;lazyMemTypePresent);
if (!lazyMemTypePresent) {
memAllocInfo.memoryTypeIndex = mRenderer->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
}
VERIFY(vkAllocateMemory(device, amp;memAllocInfo, nullptr, amp;multisampleTarget.color.memory));
vkBindImageMemory(device, multisampleTarget.color.image, multisampleTarget.color.memory, 0);
// Create image view for the MSAA target
VkImageViewCreateInfo imageViewCI{};
imageViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewCI.image = multisampleTarget.color.image;
imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewCI.format = mRenderer->getSCImageFormat();// swapChain.colorFormat;
imageViewCI.components.r = VK_COMPONENT_SWIZZLE_R;
imageViewCI.components.g = VK_COMPONENT_SWIZZLE_G;
imageViewCI.components.b = VK_COMPONENT_SWIZZLE_B;
imageViewCI.components.a = VK_COMPONENT_SWIZZLE_A;
imageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageViewCI.subresourceRange.levelCount = 1;
imageViewCI.subresourceRange.layerCount = 1;
VERIFY(vkCreateImageView(device, amp;imageViewCI, nullptr, amp;multisampleTarget.color.view));
AttachmentCreateInfo attachmentInfo = {};
attachmentInfo.width = mWidth;
attachmentInfo.height = mHeight;
attachmentInfo.layerCount = 1;
attachmentInfo.imageSampleCount = mRenderer->getMSAAsamples();
attachmentInfo.format = mRenderer->getDepthFormat();
attachmentInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
addAttachment(attachmentInfo);
autoamp; depthAttachment = mAttachments.back();
multisampleTarget.depth.image = depthAttachment.image;
multisampleTarget.depth.view = depthAttachment.view;
multisampleTarget.depth.memory = depthAttachment.memory;
std::vector<VkImageView> attachments;
attachments.emplace_back(multisampleTarget.color.view);
attachments.emplace_back(color.view);
attachments.emplace_back(multisampleTarget.depth.view);
VkFramebufferCreateInfo frameBufferCI{};
frameBufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
frameBufferCI.pNext = NULL;
frameBufferCI.renderPass = mRenderPass;
frameBufferCI.attachmentCount = static_cast<uint32_t>(attachments.size());
frameBufferCI.pAttachments = attachments.data();
frameBufferCI.width = mWidth;
frameBufferCI.height = mHeight;
frameBufferCI.layers = 1;
mFrameBuffers.resize(1);
VERIFY(vkCreateFramebuffer(device, amp;frameBufferCI, nullptr, amp;mFrameBuffers[0]));
В RenderDoc я мог видеть второе вложение глубины рендерпаса как «неопределенный img».
Я предполагаю, что я правильно использую загрузку и хранилища, а также создал зависимости подпространства, которые обеспечивают передачу значений глубины с первого прохода рендеринга на второй. Но!! это не работает. 🙁 Приношу извинения за мой начинающий стиль кодирования. Большинство из них были из примеров Сашавиллема.
Ответ №1:
Во втором проходе, в описании вложения, оно «загружает» изображение в неопределенное состояние:
attachments[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
Основываясь на вашем коде создания вложения, я предполагаю, что это должно быть VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
Комментарии:
1. Это спасло меня. Я пытался понять, почему это не работает.!! теперь я понял. Кроме того, я использовал тот же буфер вложений глубины, созданный в буфере отложенных кадров. Теперь нет необходимости создавать «multisampleTarget.depth.view»