简体   繁体   English

具有DirectX桌面框架的消费者-生产者线程

[英]Consumer-Producer threads with DirectX desktop frames

I'm writing a DirectX application with two threads: 我正在编写具有两个线程的DirectX应用程序:

  • Producer thread grabs desktop frames with DirectX (as in the Desktop Duplication DirectX sample ) 生产者线程使用DirectX捕获桌面框架(如“ 桌面复制DirectX示例”中一样

     IDXGIResource* DesktopResource = nullptr; ID3D11Texture2D *m_AcquiredDesktopImage = nullptr; HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &DesktopResource); hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&m_AcquiredDesktopImage)); DesktopResource->Release(); // The texture pointer I'm interested is m_AcquiredDesktopImage 
  • Consumer thread performs image processing operations on the GPU. 使用者线程在GPU上执行图像处理操作。

To avoid copies I'd like to keep everything on the GPU as much as possible. 为了避免复制,我想将所有内容尽可能保留在GPU上。 From ReleaseFrame 's documentation I kinda get that I should call ReleaseFrame on the desktop duplication interface as soon as I'm done processing the frame. ReleaseFrame的文档中可以得知,一旦完成处理帧,就应该在桌面复制界面上调用ReleaseFrame

My question: should I copy the m_AcquiredDesktopImage texture into another one and call ReleaseFrame as soon as the copy is finished and return that new texture to the producer thread for processing or can I just get away with returning the m_AcquiredDesktopImage texture pointer to the consumer thread? 我的问题:我应该将m_AcquiredDesktopImage纹理复制到另一个纹理中,并在复制完成后立即调用ReleaseFrame并将新纹理返回给生产者线程进行处理,还是可以将m_AcquiredDesktopImage纹理指针返回给消费者线程而m_AcquiredDesktopImage Is this a copy of the framebuffer texture or is it the framebuffer texture and I might generate a data race by returning it? 这是帧缓冲区纹理的副本还是帧缓冲区纹理,我可能会通过返回它来生成数据竞争?

Which one is the correct way to handle a producer of grabbed frames and a consumer of GPU textures? 哪一种是处理抓取帧的生成者和GPU纹理的消费者的正确方法?

The MSDN documentation on ReleaseFrame is a little convoluted. ReleaseFrame上的MSDN文档有些复杂。 It specifically states you need to release the current frame before processing the next one, and that the surface state is "invalid" after release, which would indicate it is either not a copy, or not a copy that your process owns (which would yield the same effective result). 它特别指出您需要在处理下一帧之前释放当前帧,并且释放后表面状态为“无效”,这表明它不是副本,也不是您的进程拥有的副本(这将产生相同的有效结果)。 It also states you should delay the call to ReleaseFrame until right before you call AcquireNextFrame for performance reasons, which can make for some interesting timing issues, especially with the threading model you're using. 它还指出,出于性能原因,应延迟对ReleaseFrame的调用,直到调用AcquireNextFrame之前,这可能会引起一些有趣的计时问题,尤其是在使用的线程模型时。

I think you'd be better off making a copy (so ReleaseFrame from the previous capture, AcquireNextFrame , CopyResource ). 我认为您最好制作一个副本( AcquireNextFrame ,上一个捕获的ReleaseFrame AcquireNextFrameCopyResource )。 Unless you're using fences you don't have any guarantees the GPU will be consuming the resource before your producer thread has called ReleaseFrame , which could give you undefined results. 除非您使用围墙,否则您无法保证在生产者线程调用ReleaseFrame之前,GPU会消耗资源,这可能会给您带来不确定的结果。 And if you are using fences, and the AcquireNextFrame call is delayed until the GPU has finished consuming the previous frame's data, you'll introduce stalls and lose a lot of the benefits of the CPU being able to run ahead of the GPU. 如果使用围栏,并AcquireNextFrame调用将被延迟,直到GPU完成消费前一帧的数据,你会介绍摊位,失去了很多的CPU能够领先于GPU上运行的好处。

I'm curious why you're going with this threading model, when the work is done on the GPU. 我很好奇为什么在GPU上完成工作时为什么要使用这种线程模型。 I suspect it makes life a little more complicated. 我怀疑这会使生活变得更加复杂。 Although making a copy of the texture would remove a lot of those complications. 尽管复制纹理可以消除很多复杂性。

...should I copy the m_AcquiredDesktopImage texture into another one and call ReleaseFrame as soon as the copy is finished and return that new texture to the producer thread for processing or... ...我应该将m_AcquiredDesktopImage纹理复制到另一个纹理中,并在复制完成后立即调用ReleaseFrame并将新纹理返回给生产者线程进行处理或...

Yes, this is the way. 是的,这就是方法。 You got your texture, you are finished with it and you release it because the data is no longer valid after the release. 获得纹理,完成纹理并释放它,因为发布后数据不再有效。

...can I just get away with returning the m_AcquiredDesktopImage texture pointer to the consumer thread? ...我可以逃避将m_AcquiredDesktopImage纹理指针返回给使用者线程吗? Is this a copy of the framebuffer texture or is it the framebuffer texture and I might generate a data race by returning it? 这是帧缓冲区纹理的副本还是帧缓冲区纹理,我可能会通过返回它来生成数据竞争?

The API keeps updating this texture. API会不断更新此纹理。 You are promised that between successful return from AcquireNextFrame and your ReleaseFrame call the API does not touch the texture and you are free to use it. 您可以保证,从AcquireNextFrame成功返回到您的ReleaseFrame调用之间,API不会接触纹理,您可以自由使用它。 If you cannot complete your use between the mentioned calls (which is your case, after all you created a consumer thread to run asynchronously to capture) you copy data and ReleaseFrame . 如果您无法在上述调用之间完成使用(这是您的情况,毕竟您创建了一个消费线程以异步方式运行以捕获),请复制数据和ReleaseFrame Once you released it, the API resumes the updating. 释放它后,API将继续更新。

An attempt to use the texture after ReleaseFrame will result in concurrent access to the texture, your and the API's further updates. ReleaseFrame之后尝试使用纹理将导致并发访问纹理,您和API的进一步更新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM