使用 Vulkan Android 时使用 MSAA 的黑屏

Black Screen with MSAA on Android with Vulkan

我在 Android 上设置 MSAA 时遇到问题。在任何经过​​测试的台式机(Intel、NVIDIA)上,我得到一个正确的解析帧缓冲区和渲染通道(我目前有一个空的渲染通道,我只清除背景颜色)并且屏幕呈现简单的灰色(期望)但是在 android屏幕是黑色的。

我没有收到任何验证错误。代码只是 "works" 但它对我来说似乎不正确。

这是我的 Renderpass 代码:

VkSampleCountFlagBits sampleCount = GetMaxUsableSampleCount();

VkAttachmentDescription colorResolveAttachment = {};
colorResolveAttachment.format = mSwapchainImageFormat;
colorResolveAttachment.samples = sampleCount;
colorResolveAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorResolveAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorResolveAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorResolveAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorResolveAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorResolveAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

VkAttachmentDescription colorAttachment = {};
colorAttachment.format = mSwapchainImageFormat;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = (mSamples != 0) ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;

VkAttachmentDescription depthResolveAttachment = {};
depthResolveAttachment.format = mDepthImageFormat;
depthResolveAttachment.samples = sampleCount;
depthResolveAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthResolveAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthResolveAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthResolveAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthResolveAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthResolveAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

VkAttachmentDescription depthAttachment = {};
depthAttachment.format = mDepthImageFormat;
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = (mSamples != 0) ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

VkAttachmentReference colorAttachmentRef = {};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

VkAttachmentReference depthAttachmentRef = {};
depthAttachmentRef.attachment = (mSamples != 0) ? 2 : 1;
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

VkAttachmentReference colorAttachmentResolveRef = {};
colorAttachmentResolveRef.attachment = 1;
colorAttachmentResolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
subpass.pDepthStencilAttachment = &depthAttachmentRef;
if(mSamples != 0)
{
    subpass.pResolveAttachments = &colorAttachmentResolveRef;
}

std::vector<VkSubpassDependency> dependencies;

if(mSamples != 0)
{
    std::array<VkSubpassDependency, 2> dependency;

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

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

    dependencies.push_back(dependency[0]);
    dependencies.push_back(dependency[1]);
}
else
{
    VkSubpassDependency dependency = {};
    dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
    dependency.dstSubpass = 0;
    dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.srcAccessMask = 0;
    dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

    dependencies.push_back(dependency);
}

std::vector<VkAttachmentDescription> attachments;

if(mSamples != 0)
{
    attachments.push_back(colorResolveAttachment);
    attachments.push_back(colorAttachment);
    attachments.push_back(depthResolveAttachment);
    attachments.push_back(depthAttachment);
}
else
{
    attachments.push_back(colorAttachment);
    attachments.push_back(depthAttachment);
}

VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
renderPassInfo.pDependencies = dependencies.data();

if(vkCreateRenderPass(mDevice, &renderPassInfo, nullptr, &mRenderPass) != VK_SUCCESS)
{
    Console::FatalError("Failed to create render pass!");
    return false;
}

return true;

这是我的 Freambuffer 代码:

if(!CreateMultiSampleTargets())
    return false;

mSwapchainFramebuffers.resize(mSwapchainImageViews.size());

for(size_t i = 0u; i < mSwapchainImageViews.size(); i++)
{
    std::vector<VkImageView> attachments;

    if(mSamples != 0)
    {
        attachments.push_back(mMultiSampleColorImageView);
        attachments.push_back(mSwapchainImageViews[i]);
        attachments.push_back(mMultiSampleDepthImageView);
        attachments.push_back(mDepthImageView);
    }
    else
    {
        attachments.push_back(mSwapchainImageViews[i]);
        attachments.push_back(mDepthImageView);
    }

    VkFramebufferCreateInfo framebufferInfo = {};
    framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
    framebufferInfo.renderPass = mRenderPass;
    framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
    framebufferInfo.pAttachments = attachments.data();
    framebufferInfo.width = mSwapchainExtent.width;
    framebufferInfo.height = mSwapchainExtent.height;
    framebufferInfo.layers = 1;

    if(vkCreateFramebuffer(mDevice, &framebufferInfo, nullptr, &mSwapchainFramebuffers[i]) != VK_SUCCESS)
    {
        Console::FatalError("Failed to create framebuffer!");
        return false;
    }
}

我应该提到我的代码很大程度上基于此:https://github.com/SaschaWillems/Vulkan/blob/master/multisampling/multisampling.cpp

解决方案是将我的 Oneplus 3 升级到 android 8 以获得更新的驱动程序版本,而不会出现此问题。我想这是一个驱动程序错误。