如何解决Vulkan-异步纹理上传-图像过渡问题
我正在使用传输队列将数据上传到GPU本地内存,以供图形队列使用。我相信我需要3个障碍,一个要从传输队列释放纹理对象,一个要在图形队列上获取它,并且一个要从TRANSFER_DST_OPTIMAL过渡到SHADER_READ_ONLY_OPTIMAL。我认为我的障碍是不正确的,因为这是我得到的错误,而且我在Nvidia硬件上看到正确的渲染输出。是否缺少同步?
UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout(ERROR / SPEC): msgNum: 1303270965 -
Validation Error: [ UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout ] Object 0:
handle = 0x562696461ca0,type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0x4dae5635 |
Submitted command buffer expects VkImage 0x1c000000001c[] (subresource: aspectMask 0x1 array
layer 0,mip level 0) to be in layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL--instead,current layout is VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
我认为我做错了没有正确指定stageMasks
VkImageMemoryBarrier tex_barrier = {0};
/* layout transition - UNDEFINED -> TRANSFER_DST */
tex_barrier.srcAccessMask = 0;
tex_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
tex_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
tex_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
tex_barrier.srcQueueFamilyIndex = -1;
tex_barrier.dstQueueFamilyIndex = -1;
tex_barrier.subresourceRange = (VkImageSubresourceRange) { VK_IMAGE_ASPECT_COLOR_BIT,1,1 };
vkCmdPipelineBarrier(transfer_cmdbuffs[0],VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,VK_PIPELINE_STAGE_TRANSFER_BIT,NULL,&tex_barrier);
/* queue ownership transfer */
tex_barrier.srcAccessMask = 0;
tex_barrier.dstAccessMask = 0;
tex_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
tex_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
tex_barrier.srcQueueFamilyIndex = device.transfer_queue_family_index;
tex_barrier.dstQueueFamilyIndex = device.graphics_queue_family_index;
vkCmdPipelineBarrier(transfer_cmdbuffs[0],&tex_barrier);
tex_barrier.srcAccessMask = 0;
tex_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
tex_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
tex_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
tex_barrier.srcQueueFamilyIndex = device.transfer_queue_family_index;
tex_barrier.dstQueueFamilyIndex = device.graphics_queue_family_index;
vkCmdPipelineBarrier(transfer_cmdbuffs[0],VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,&tex_barrier);
解决方法
进行所有权转移是一个双向过程:转移的来源必须释放资源,而接收者必须获取资源。我所说的“源”和“接收者”本身就是“队列”。您不能仅仅让队列获取资源所有权;该队列必须发出命令以声明所有权。
您需要在源队列上提交释放屏障操作。它必须指定源队列族以及目标队列族。然后,您必须使用相同的源和目标在接收队列上提交获取屏障操作。并且您必须通过信号量确保这些操作的顺序。因此,vkQueueSubmit
的获取请求必须等待释放操作提交后的信号量(时间轴信号量也可以工作)。
现在,由于这些是管道/内存屏障,因此您还可以自由指定布局过渡。您不需要第三个障碍即可更改布局,但是两个障碍都必须为获取/发布操作指定相同的源/目标布局。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。