从 Direct3D 纹理和表面进行读回
我需要弄清楚如何将 D3D 纹理和表面的数据返回到系统内存。 做这些事情最快的方法是什么以及如何做?
另外,如果我只需要一个子矩形,如何才能只读回该部分,而不必将整个内容读回系统内存?
简而言之,我正在寻找有关如何将以下内容复制到系统内存的简明描述:
- 纹理
- 纹理的子集
- 表面
- 表面的子集
- D3DUSAGE_RENDERTARGET纹理
- 子集 > D3DUSAGE_RENDERTARGET 纹理
这是 Direct3D 9,但有关较新版本的 D3D 的答案也将不胜感激。
I need to figure out how to get the data from D3D textures and surfaces back to system memory. What's the fastest way to do such things and how?
Also if I only need one subrect, how can one read back only that portion without having to read back the entire thing to system memory?
In short I'm looking for concise descriptions of how to copy the following to system memory:
- a texture
- a subset of a texture
- a surface
- a subset of a surface
- a D3DUSAGE_RENDERTARGET texture
- a subset of a D3DUSAGE_RENDERTARGET texture
This is Direct3D 9, but answers about newer versions of D3D would be appreciated too.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
最涉及的部分是从视频内存(“默认池”)中的某个表面读取。 这通常是渲染目标。
让我们首先了解简单的部分:
现在我们已经在视频内存中留下了表面(“默认池”)。 这可以是标记为渲染目标的任何表面/纹理,或者您在默认池中创建的任何常规表面/纹理,或者后台缓冲区本身。 这里复杂的部分是你无法锁定它。
简短的答案是:D3D 设备上的 GetRenderTargetData 方法。
更长的答案(下面的代码的粗略轮廓):
更长的答案(从我正在处理的代码库粘贴)如下。 这个不会直接编译,因为它使用了代码库其余部分中的一些类、函数、宏和实用程序; 但它应该让你开始。 我还省略了大部分错误检查(例如给定的宽度/高度是否超出范围)。 我还省略了读取实际像素并可能将它们转换为合适的目标格式的部分(这很容易,但可能会很长,具体取决于您想要支持的格式转换的数量)。
上面代码中的 SurfacePointer 是一个指向 COM 对象的智能指针(它在赋值或析构函数时释放对象)。 大大简化了错误处理。 这与 Visual C++ 中的
_comptr_t
非常相似。上面的代码读回整个表面。 如果您只想有效地读取其中的一部分,那么我相信最快的方法大致是:
事实上,这与上面处理多重采样表面的代码非常相似。 我认为,如果您只想获取多重采样表面的一部分,您可以进行多重采样解析并在一个 StretchRect 中获取其中的一部分。
编辑:删除了实际读取像素和格式转换的代码段。 与问题没有直接关系,而且代码很长。
编辑:更新以匹配编辑的问题。
The most involved part is reading from some surface that is in video memory ("default pool"). This is most often render targets.
Let's get the easy parts first:
So now we have left surfaces that are in video memory ("default pool"). This would be any surface/texture marked as render target, or any regular surface/texture that you have created in default pool, or the backbuffer itself. The complex part here is that you can't lock it.
Short answer is: GetRenderTargetData method on D3D device.
Longer answer (a rough outline of the code that will be below):
Even longer answer (paste from the codebase I'm working on) follows. This will not compile out of the box, because it uses some classes, functions, macros and utilities from the rest of codebase; but it should get you started. I also ommitted most of error checking (e.g. whether given width/height is out of bounds). I also omitted the part that reads actual pixels and possibly converts them into suitable destination format (that is quite easy, but can get long, depending on number of format conversions you want to support).
SurfacePointer
in the code above is a smart pointer to a COM object (it releases object on assignment or destructor). Simplifies error handling a lot. This is very similar to_comptr_t
things in Visual C++.The code above reads back whole surface. If you want to read just a part of it efficiently, then I believe fastest way is roughly:
In fact this is quite similar to what code above does to handle multi-sampled surfaces. If you want to get just a part of a multi-sampled surface, you can do a multisample resolve and get part of it in one StretchRect, I think.
Edit: removed piece of code that does actual read of pixels and format conversions. Was not directly related to question, and the code was long.
Edit: updated to match edited question.