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

Vulkan - 如何显示在没有同步的情况下执行两个命令会创建损坏的数据?

如何解决Vulkan - 如何显示在没有同步的情况下执行两个命令会创建损坏的数据?

我写了一个简单的测试,它会通过并行执行两个复制命令来创建同步问题,因此我可以有一种方法添加同步技术,以熟悉和体验。 不幸的是,似乎有一个隐式的 sync ,因为在没有任何同步机制的情况下一切正常。

测试执行以下操作:

  1. (sync) 用 cpu 的数据更新缓冲区 A。
  2. (异步)将缓冲区 A 复制到 B
  3. (异步)将缓冲区 B 复制到 C
  4. 等待设备空闲
  5. (sync) 由 cpu 读取缓冲区 C 数据

步骤 (2) 和 (3) 是在没有同步的情况下完成的,所以我希望将数据从 B 传输到 C 会发生,而数据仍然从 A 写入 B,这样会损坏 C 中的数据。但是读 C 到 cpu 总是显示正确的结果,它总是等于写入 A 的数据。

将缓冲区大小更改为 1G 无济于事,它仍然有完美的结果(在这种情况下并不完美 :))

硬件:Quadro RTX 5000 with Max-Q Design api版本:4202651 驱动程序:1938276352

        // Given:      
        // VkCommandPool cp;
        // VkDevice device;
        // VkQueue queue;
        // VkBuffer bufferA; 1G stage buffer (updated by cpu,has gpu src transfer usage)
        // VkBuffer bufferB; 1G buffer (has gpu src and gpu dst transfer usage)
        // VkBuffer bufferC; 1G stage buffer (read by cpu,has gpu dst transfer usage)

        // create command buffer
        VkCommandBufferAllocateInfo cbai = {};
        cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
        cbai.pNext = 0;
        cbai.commandBufferCount = 1;
        cbai.level = VkCommandBufferLevel::VK_COMMAND_BUFFER_LEVEL_PRIMARY;
        cbai.commandPool = cp;
        std::vector<VkCommandBuffer> cbs(1);
        vkAllocateCommandBuffers(device,&cbai,cbs.data());

        // set copy info
        VkCommandBufferBeginInfo cbbi = {};
        cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
        cbbi.pNext = 0;
        cbbi.pInheritanceInfo = 0;

        VkBuffercopy copyRegion = {};
        copyRegion.srcOffset = 0;
        copyRegion.dstOffset = 0;
        copyRegion.size = 1024 * 1024 * 1024;

        // record copy commands 
        vkBeginCommandBuffer(cbs[0],&cbbi);
        vkCmdcopyBuffer(cbs[0],bufferA,bufferB,1,&copyRegion);
        vkCmdcopyBuffer(cbs[0],bufferC,&copyRegion);
        vkEndCommandBuffer(cbs[0]);

        // execution of command buffer
        VkSubmitInfo si = {};
        si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
        si.commandBufferCount = 1;
        si.pCommandBuffers = cbs.data();
        vkQueueSubmit(queue,&si,VK_NULL_HANDLE);

        // wait execution finished
        vkDeviceWaitIdle(device);

        // free command buffers
        vkFreeCommandBuffers(device,cp,cbs.data());

解决方法

未定义行为未定义。您不能编写任何保证跨实现具有任何特定行为的 UB 代码。包括特别错误的行为。

也许存在隐式同步。或者 GPU 可能一次只能在该队列上执行一个传输操作。或者是其他东西。关键是代码有 UB,但你不能以某种方式使 UB 显化。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。