如何理解CopyResource的异步?

How to understand the asynchrony of CopyResource?

        virtual void STDMETHODCALLTYPE CopyResource(
        /* [annotation] */
        _In_ ID3D11Resource *pDstResource,
        /* [annotation] */
        _In_ ID3D11Resource *pSrcResource);

Can I ensure that every time pDstResource is a newly rendered image instead of black_color?

与 Direct3D 12 等 lower-level API 不同,在 10 和 11 中,GPU 驱动程序会自动处理。通常做得很好。

如果调用 CopyResource,然后更新源纹理,新的更改将不会在副本中可见。如果您调用 CopyResource 然后以某种方式从目标纹理读取(渲染或移动到系统内存),GPU 驱动程序将首先等待复制完成。

但是,在某些情况下,此工作流会中断。其中之一是 DXGI 表面共享。如果您使用该机制跨图形 API 或跨进程共享纹理,您可能会得到不完整的渲染或其他工件。

由于您的其中一个纹理被命名为 pDstResource_shared,我认为这就是您正在做的事情。

要解决此问题,请等待复制完成,然后再通过表面共享将目标纹理传递给其他人。方法如下。

  1. 启动时,创建 ID3D11Query 对象,类型为 D3D11_QUERY_EVENT

  2. 调用 ID3D11DeviceContext.CopyResource 后,调用 ID3D11DeviceContext.Flush,然后调用 ID3D11DeviceContext.End,传递该查询。

  3. 您现在需要等待 ID3D11DeviceContext.GetData 方法到 return S_OK 该查询。当 GPU 完成 ID3D11DeviceContext.End 之前提交的所有命令时,就会发生这种情况,将所有待处理的更新应用到所有资源。

最终,MS 实现了等待 GPU 的正确方法,使用栅栏而不是查询,ID3D11Fence::SetEventOnCompletion 可以在 GPU 完成工作后发出事件信号,然后您可以使用 [= 使线程休眠20=] 或类似的。但是,这需要足够新的 Windows 10 版本。不记得是哪个版本了,但我认为要么是 2016 年的周年纪念更新,要么是 2017 年的创作者更新。查询更加兼容,它们适用于所有版本的 Win10,甚至 Windows 7 或 8.