无法在Vulkan上创建深度附件的描述符或采样器

时间:2017-06-26 21:36:38

标签: descriptor vulkan depth-buffer

在我的项目中,我试图从第一个渲染过程中获取颜色和深度附件信息,并在第二个渲染过程中将它们用作描述符集以用于其他目的。为了做到这一点,我分别创建了颜色和深度附件的vkDescriptorImageInfo和VkSampler对象来保存它们的信息。但是,颜色取样器和描述符图像信息在管道中成功创建,而深度一个则没有,因为在第二遍中无法读取任何内容。我在下面附上了我的代码,包括第一个渲染过程(opaqueObjectPass)的定义和创建渲染过程的函数。

struct OpaqueObjectsPass
{
    int32_t width, height;
    VkFramebuffer frameBuffer;
    FrameBufferAttachment color, depth;
    VkRenderPass renderPass;
    VkSampler ColorSampler, DepthSampler;
    VkDescriptorImageInfo ColorDescriptor, DepthDescriptor;
    VkCommandBuffer commandBuffer = VK_NULL_HANDLE;

    VkSemaphore semaphore = VK_NULL_HANDLE;
} opaqueObjectPass;



void PrepareOpaqueRendering() 
{
    opaqueObjectPass.width = width;
    opaqueObjectPass.height = height;

    // find a suitable depth format
    VkFormat fbDepthFormat;
    VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat);

    // color attachment
    VkImageCreateInfo l_Image = vks::initializers::imageCreateInfo();
    l_Image.imageType = VK_IMAGE_TYPE_2D;
    l_Image.format = FB_COLOR_FORMAT;
    l_Image.extent.width = opaqueObjectPass.width;
    l_Image.extent.height = opaqueObjectPass.height;
    l_Image.extent.depth = 1;
    l_Image.mipLevels = 1;
    l_Image.arrayLayers = 1;
    l_Image.samples = VK_SAMPLE_COUNT_1_BIT;
    l_Image.tiling = VK_IMAGE_TILING_OPTIMAL;
    // We will sample directly from the color attachment
    l_Image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;

    VkMemoryAllocateInfo l_MemAlloc = vks::initializers::memoryAllocateInfo();
    VkMemoryRequirements l_MemReqs;

    VK_CHECK_RESULT(vkCreateImage(device, &l_Image, nullptr, &opaqueObjectPass.color.image));
    vkGetImageMemoryRequirements(device, opaqueObjectPass.color.image, &l_MemReqs);
    l_MemAlloc.allocationSize = l_MemReqs.size;
    l_MemAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(l_MemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
    VK_CHECK_RESULT(vkAllocateMemory(device, &l_MemAlloc, nullptr, &opaqueObjectPass.color.mem));
    VK_CHECK_RESULT(vkBindImageMemory(device, opaqueObjectPass.color.image, opaqueObjectPass.color.mem, 0));

    VkImageViewCreateInfo l_ColorImageView = vks::initializers::imageViewCreateInfo();
    l_ColorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
    l_ColorImageView.format = FB_COLOR_FORMAT;
    l_ColorImageView.subresourceRange = {};
    l_ColorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    l_ColorImageView.subresourceRange.baseMipLevel = 0;
    l_ColorImageView.subresourceRange.levelCount = 1;
    l_ColorImageView.subresourceRange.baseArrayLayer = 0;
    l_ColorImageView.subresourceRange.layerCount = 1;
    l_ColorImageView.image = opaqueObjectPass.color.image;
    VK_CHECK_RESULT(vkCreateImageView(device, &l_ColorImageView, nullptr, &opaqueObjectPass.color.view));

    // Create sampler to sample from the attachment in the fragment shader
    VkSamplerCreateInfo l_SamplerInfo = vks::initializers::samplerCreateInfo();
    l_SamplerInfo.magFilter = VK_FILTER_LINEAR;
    l_SamplerInfo.minFilter = VK_FILTER_LINEAR;
    l_SamplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
    l_SamplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
    l_SamplerInfo.addressModeV = l_SamplerInfo.addressModeU;
    l_SamplerInfo.addressModeW = l_SamplerInfo.addressModeU;
    l_SamplerInfo.mipLodBias = 0.0f;
    l_SamplerInfo.maxAnisotropy = 0;
    l_SamplerInfo.minLod = 0.0f;
    l_SamplerInfo.maxLod = 1.0f;
    l_SamplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
    VK_CHECK_RESULT(vkCreateSampler(device, &l_SamplerInfo, nullptr, &opaqueObjectPass.ColorSampler));

    // Depth stencil attachment
    l_Image.format = fbDepthFormat;
    l_Image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
    //l_Image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;

    VK_CHECK_RESULT(vkCreateImage(device, &l_Image, nullptr, &opaqueObjectPass.depth.image));
    vkGetImageMemoryRequirements(device, opaqueObjectPass.depth.image, &l_MemReqs);
    l_MemAlloc.allocationSize = l_MemReqs.size;
    l_MemAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(l_MemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
    VK_CHECK_RESULT(vkAllocateMemory(device, &l_MemAlloc, nullptr, &opaqueObjectPass.depth.mem));
    VK_CHECK_RESULT(vkBindImageMemory(device, opaqueObjectPass.depth.image, opaqueObjectPass.depth.mem, 0));

    VkImageViewCreateInfo l_DepthStencilView = vks::initializers::imageViewCreateInfo();
    l_DepthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D;
    l_DepthStencilView.format = fbDepthFormat;
    l_DepthStencilView.flags = 0;
    l_DepthStencilView.subresourceRange = {};
    l_DepthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
    l_DepthStencilView.subresourceRange.baseMipLevel = 0;
    l_DepthStencilView.subresourceRange.levelCount = 1;
    l_DepthStencilView.subresourceRange.baseArrayLayer = 0;
    l_DepthStencilView.subresourceRange.layerCount = 1;
    l_DepthStencilView.image = opaqueObjectPass.depth.image;
    VK_CHECK_RESULT(vkCreateImageView(device, &l_DepthStencilView, nullptr, &opaqueObjectPass.depth.view));

    // create a sampler of depth buffer
    VK_CHECK_RESULT(vkCreateSampler(device, &l_SamplerInfo, nullptr, &opaqueObjectPass.DepthSampler));

    // Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering

    std::array<VkAttachmentDescription, 2> l_AttchmentDescriptions = {};
    // Color attachment
    l_AttchmentDescriptions[0].format = FB_COLOR_FORMAT;
    l_AttchmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT;
    l_AttchmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
    l_AttchmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
    l_AttchmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
    l_AttchmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
    l_AttchmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    l_AttchmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
    // Depth attachment
    l_AttchmentDescriptions[1].format = fbDepthFormat;
    l_AttchmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT;
    l_AttchmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
    l_AttchmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
    l_AttchmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
    l_AttchmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
    l_AttchmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    l_AttchmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

    VkAttachmentReference l_ColorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
    VkAttachmentReference l_DepthReference = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };

    VkSubpassDescription subpassDescription = {};
    subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
    subpassDescription.colorAttachmentCount = 1;
    subpassDescription.pColorAttachments = &l_ColorReference;
    subpassDescription.pDepthStencilAttachment = &l_DepthReference;

    // Use subpass dependencies for layout transitions
    std::array<VkSubpassDependency, 2> l_Dependencies;

    l_Dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
    l_Dependencies[0].dstSubpass = 0;
    l_Dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
    l_Dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    l_Dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    l_Dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    l_Dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

    l_Dependencies[1].srcSubpass = 0;
    l_Dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
    l_Dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    l_Dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
    l_Dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    l_Dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    l_Dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

    // Create the actual renderpass
    VkRenderPassCreateInfo l_RenderPassInfo = {};
    l_RenderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
    l_RenderPassInfo.attachmentCount = static_cast<uint32_t>(l_AttchmentDescriptions.size());
    l_RenderPassInfo.pAttachments = l_AttchmentDescriptions.data();
    l_RenderPassInfo.subpassCount = 1;
    l_RenderPassInfo.pSubpasses = &subpassDescription;
    l_RenderPassInfo.dependencyCount = static_cast<uint32_t>(l_Dependencies.size());
    l_RenderPassInfo.pDependencies = l_Dependencies.data();

    VK_CHECK_RESULT(vkCreateRenderPass(device, &l_RenderPassInfo, nullptr, &opaqueObjectPass.renderPass));

    VkImageView l_Attachments[2];
    l_Attachments[0] = opaqueObjectPass.color.view;
    l_Attachments[1] = opaqueObjectPass.depth.view;

    VkFramebufferCreateInfo l_fbufCreateInfo = vks::initializers::framebufferCreateInfo();
    l_fbufCreateInfo.renderPass = opaqueObjectPass.renderPass;
    l_fbufCreateInfo.attachmentCount = 2;
    l_fbufCreateInfo.pAttachments = l_Attachments;
    l_fbufCreateInfo.width = opaqueObjectPass.width;
    l_fbufCreateInfo.height = opaqueObjectPass.height;
    l_fbufCreateInfo.layers = 1;

    VK_CHECK_RESULT(vkCreateFramebuffer(device, &l_fbufCreateInfo, nullptr, &opaqueObjectPass.frameBuffer));

    // Fill a descriptor for later use in a descriptor set 
    opaqueObjectPass.ColorDescriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
    opaqueObjectPass.ColorDescriptor.imageView = opaqueObjectPass.color.view;
    opaqueObjectPass.ColorDescriptor.sampler = opaqueObjectPass.ColorSampler;

    opaqueObjectPass.DepthDescriptor.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
    opaqueObjectPass.DepthDescriptor.imageView = opaqueObjectPass.depth.view;
    opaqueObjectPass.DepthDescriptor.sampler = opaqueObjectPass.DepthSampler;
}


void PrepareOpaquePipeline() 
{
    VkPipelineInputAssemblyStateCreateInfo l_InputAssemblyState =
        vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE);

    VkPipelineRasterizationStateCreateInfo l_RasterizationState =
        vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_FRONT_BIT, VK_FRONT_FACE_CLOCKWISE, 0);

    VkPipelineColorBlendAttachmentState l_BlendAttachmentState =
        vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE);

    VkPipelineColorBlendStateCreateInfo l_ColorBlendState =
        vks::initializers::pipelineColorBlendStateCreateInfo(1, &l_BlendAttachmentState);

    VkPipelineDepthStencilStateCreateInfo l_DepthStencilState =
        vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL);

    VkPipelineViewportStateCreateInfo l_ViewportState =
        vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0);

    VkPipelineMultisampleStateCreateInfo l_MultisampleState =
        vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0);

    std::vector<VkDynamicState> l_DynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
    VkPipelineDynamicStateCreateInfo l_DynamicState =
        vks::initializers::pipelineDynamicStateCreateInfo(l_DynamicStateEnables.data(), l_DynamicStateEnables.size(), 0);

    // Solid rendering pipeline
    // Load shaders
    std::array<VkPipelineShaderStageCreateInfo, 2> l_ShaderStages;

    l_ShaderStages[0] = loadShader(getAssetPath() + "shaders/offscreen/opaque.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
    l_ShaderStages[1] = loadShader(getAssetPath() + "shaders/offscreen/opaque.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);

    VkGraphicsPipelineCreateInfo l_PipelineCreateInfo =
        vks::initializers::pipelineCreateInfo(pipelineLayouts.opaque, opaqueObjectPass.renderPass, 0);

    l_PipelineCreateInfo.pVertexInputState = &vertices.inputState;
    l_PipelineCreateInfo.pInputAssemblyState = &l_InputAssemblyState;
    l_PipelineCreateInfo.pRasterizationState = &l_RasterizationState;
    l_PipelineCreateInfo.pColorBlendState = &l_ColorBlendState;
    l_PipelineCreateInfo.pMultisampleState = &l_MultisampleState;
    l_PipelineCreateInfo.pViewportState = &l_ViewportState;
    l_PipelineCreateInfo.pDepthStencilState = &l_DepthStencilState;
    l_PipelineCreateInfo.pDynamicState = &l_DynamicState;
    l_PipelineCreateInfo.stageCount = l_ShaderStages.size();
    l_PipelineCreateInfo.pStages = l_ShaderStages.data();

    // create graphics pipeline of opaque
    VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &l_PipelineCreateInfo, nullptr, &pipelines.opaque));

}

可能我不正确地设置了一对属性标志,我感谢任何有关正确属性设置的建议,并使描述符集在第二个渲染过程中工作。

1 个答案:

答案 0 :(得分:1)

其中一个问题出在您的深度图像创建代码中。您为彩色图像(颜色附件+采样)设置了有效的使用标记,但没有为深度图像设置(仅限深度附件):

// Depth stencil attachment
l_Image.format = fbDepthFormat;
l_Image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;

这种方式您只能将深度数据渲染到图像中,但您无法读取它。将VK_IMAGE_USAGE_SAMPLED_BIT标志添加到用法并检查问题是否仍然存在。如果是,那么其他地方也会出现另一个问题。