我正在制作一个Vulkan(LWJGL)应用程序,该应用程序将直接绘制到帧缓冲区图像上。没有顶点或片段着色器,只有一些计算着色器来构建图像,我直接将其着色为FrameBuffer图像。一切正常。
现在,我尝试在此之上渲染UI(imgui),但我认为我有一些同步麻烦:UI有时会闪烁(blit可能尚未结束?)。该渲染在几秒钟内将是完美的,但迟早UI可能会在一帧内消失。我只生成一次渲染过程,对于此测试,我不会多次记录命令缓冲区,因此我认为问题是在记录命令缓冲区时发生的。
问题可能出在UI开始绘制时vkCmdBlitImage仍在运行吗? 我试图在blit和UI渲染之间添加一些障碍,但是问题仍然存在。
我想我真的很想念什么,所以我请求您的帮助。我在这里放置了我认为相关的代码,但请随时询问更多代码。
CommandBuffer的记录:
for (int i = 0; i < commandBuffers.size(); i++)
{
RenderCommandBuffer commandBuffer = commandBuffers.get(i);
ImageView imageView = configuration.imageViewManager.getImageViews().get(i);
commandBuffer.startCommand();
copyPixelBufferToFB(commandBuffer, imageView);
commandBuffer.startRenderPass();
imGui.drawFrame(commandBuffer.getVkCommandBuffer());
commandBuffer.endRenderPass();
commandBuffer.endCommand();
}
copyPixelBufferToFB方法:
Extent2D extent = context.swapChainManager.getExtent();
ImageView dstImageView = context.imageViewManager.getImageViews().get(commandBuffer.id);
// Intend to blit from this image, set the layout accordingly
// Prepare transfer from Image to Frambuffer
ImageBarrier barrier = new ImageBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT);
barrier.addImageBarrier(srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_ACCESS_TRANSFER_READ_BIT);
barrier.addImageBarrier(dstImageView.getImageId(), dstImageView.getImageFormat(), 1, 0,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT);
barrier.execute(commandBuffer.getVkCommandBuffer());
long bltSrcImage = srcImage.getId();
long bltDstImage = dstImageView.getImageId();
VkImageBlit.Buffer region = VkImageBlit.calloc(1);
region.srcSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT);
region.srcSubresource().mipLevel(0);
region.srcSubresource().baseArrayLayer(0);
region.srcSubresource().layerCount(1);
region.srcOffsets(0).x(0);
region.srcOffsets(0).y(0);
region.srcOffsets(0).z(0);
region.srcOffsets(1).x(srcImage.getWidth());
region.srcOffsets(1).y(srcImage.getHeight());
region.srcOffsets(1).z(1);
region.dstSubresource().aspectMask(VK_IMAGE_ASPECT_COLOR_BIT);
region.dstSubresource().mipLevel(0);
region.dstSubresource().baseArrayLayer(0);
region.dstSubresource().layerCount(1);
region.dstOffsets(0).x(0);
region.dstOffsets(0).y(0);
region.dstOffsets(0).z(0);
region.dstOffsets(1).x(extent.getWidth());
region.dstOffsets(1).y(extent.getHeight());
region.dstOffsets(1).z(1);
vkCmdBlitImage(commandBuffer.getVkCommandBuffer(), bltSrcImage,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bltDstImage,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, region, VK_FILTER_NEAREST);
// Change layout again before render pass.
ImageBarrier barrierEnd = new ImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
barrierEnd.addImageBarrier(srcImage, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_WRITE_BIT);
barrierEnd.addImageBarrier(dstImageView.getImageId(), dstImageView.getImageFormat(), 1,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT);
barrierEnd.execute(commandBuffer.getVkCommandBuffer());
我如何提交CommandBuffer,诸如此类:
bWaitSemaphores.put(waitSemaphore.getId());
bwaitStage.put(VK_PIPELINE_STAGE_TRANSFER_BIT);
pCommandBuffers.put(commandBuffer.getVkCommandBuffer());
submitInfo = VkSubmitInfo.calloc();
submitInfo.sType(VK_STRUCTURE_TYPE_SUBMIT_INFO);
submitInfo.waitSemaphoreCount(bWaitSemaphores.size());
submitInfo.pWaitSemaphores(bWaitSemaphores);
submitInfo.pWaitDstStageMask(bwaitStage);
submitInfo.pCommandBuffers(pCommandBuffers);
[...]
vkQueueSubmit(queue, submitInfo, VK_NULL_HANDLE);
RenderPass的创建:
VkAttachmentDescription colorAttachment = VkAttachmentDescription.calloc();
colorAttachment.format(context.swapChainManager.getColorDomain().getColorFormat());
colorAttachment.samples(VK_SAMPLE_COUNT_1_BIT);
colorAttachment.loadOp(VK_ATTACHMENT_LOAD_OP_LOAD);
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_COLOR_ATTACHMENT_OPTIMAL);
colorAttachment.finalLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
VkAttachmentReference.Buffer colorAttachmentRef = VkAttachmentReference.calloc(1);
colorAttachmentRef.attachment(0);
colorAttachmentRef.layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkSubpassDescription.Buffer subpass = VkSubpassDescription.calloc(1);
subpass.pipelineBindPoint(VK_PIPELINE_BIND_POINT_GRAPHICS);
subpass.colorAttachmentCount(1);
subpass.pColorAttachments(colorAttachmentRef);
VkSubpassDependency.Buffer dependency = VkSubpassDependency.calloc(1);
dependency.srcSubpass(VK_SUBPASS_EXTERNAL);
dependency.dstSubpass(0);
dependency.srcStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
dependency.dstStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
dependency.srcAccessMask(0);
dependency.dstAccessMask(
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
int attachmentCount = 1;
VkAttachmentDescription.Buffer attachments = VkAttachmentDescription
.calloc(attachmentCount);
attachments.put(colorAttachment);
attachments.flip();
VkRenderPassCreateInfo renderPassInfo = VkRenderPassCreateInfo.calloc();
renderPassInfo.sType(VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
renderPassInfo.pAttachments(attachments);
renderPassInfo.pSubpasses(subpass);
renderPassInfo.pDependencies(dependency);
long[] aRenderPass = new long[1];
if (vkCreateRenderPass(logicalDevice.getVkDevice(), renderPassInfo, null,
aRenderPass) != VK_SUCCESS)
{
throw new AssertionError("Failed to create render pass!");
}
renderPass = aRenderPass[0];
编辑12/12/2018:
上面的代码中的imGui.drawFrame()
无关紧要,我将gui从ImGui更改为Nuklear,并完全重写了gui管道。不幸的是,出现了同样的问题。
但是,我仍在使用vkCmdDrawIndexed
来绘制它。