微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Vulkan-异步纹理上传-图像过渡问题

如何解决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 举报,一经查实,本站将立刻删除。