我正在使用 Vulkan 为 Android 编写游戏。对于游戏,我需要将深度缓冲区信息写入离屏帧缓冲区。我最终希望通过CPU读取此深度信息,但现在我将其绘制在四边形上以对其进行调试。我在图像中仅获得1.0的清晰深度值,因此我尝试简化该问题。首先,我决定使用颜色和深度附件,以防仅深度附件出现问题。然后我做了以下事情:
(1)设置一个渲染通道,该渲染通道使用颜色和深度附件并将其分别清除为绿色和{1.0,0},
(2)使用的帧缓冲区不使用交换链图像或普通深度缓冲区,而是专门为此屏幕外帧缓冲区创建的图像,
(3)转换布局,以便可以通过渲染过程将其写入
(4)绘制一个蓝色四边形,它将整个屏幕占据到帧缓冲区中,
(5)结束命令缓冲区,等待图形队列空闲,
(6)转换颜色附件的布局,以便着色器可以读取它,
(7)在不同的命令缓冲区中使用交换链图像开始新的渲染过程,
(8)使用其四边形绘制纹理,四边形是上一次渲染过程(颜色附加)的结果,
(9)结束命令缓冲区并提交到图形队列。
我看到的是一个绿色矩形(第一次渲染过程中的透明颜色),其中有一些蓝色正方形(蓝色是第一次渲染过程中绘制的四边形的颜色)。我希望看到整个屏幕由一个蓝色四边形占据。
我觉得我在某个地方缺少障碍物,篱笆或信号灯。但我不知道在哪里。我在提交每个命令(用于调试)之后在图形队列中等待,我添加了一个信号量,以使每组命令都发出下一组信号来表明已完成操作。因此,人们会认为渲染过程有问题,但是我将此渲染过程用于我的常规绘制操作(在交换链图像中完成并发送到当前队列),没有任何问题。
让我知道您需要查看代码的哪一部分。很长。
我启用了 Vulkan验证层,但没有收到任何投诉。我通过强迫它进行投诉来确保它正在工作。
我在OpenGL中做过同样的事情,而且效果很好。
我的加载和存储操作如下:
colorAttachment.loadOp = 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;
depthAttachment.loadOp = 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;
对于布局过渡,我在绘制之前对颜色附件图像执行以下过渡:
vkBeginCommandBuffer(...);
VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = colorImage;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
vkCmdPipelineBarrier(
cmdBuffer,
sourceStage, destinationStage,
0,
0, nullptr,
0, nullptr,
1, &barrier
);
vkEndCommandBuffer(...);
vkQueueSubmit(...);
vkQueueWaitIdle(graphicsQueue);
在渲染过程中,我将布局转换为VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,以便可以从着色器读取它。
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkAttachmentReference colorAttachmentRef = {};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.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;
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;
我的最终目标是拥有一个渲染过程,不包含颜色附件,而仅包含深度附件。颜色附件仅用于调试目的。
答案 0 :(得分:0)
我对这个问题的想法是,这是一个驱动程序错误。该代码可在几台不同的Linux PC和Pixel 4XL android设备上正常工作。我进行了测试,看是否能为已知模型得到正确的结果。如果答案不正确,我将退回到OpenGL。