windows 如何有效地调整 DirectX 窗口的大小?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8764013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 18:48:21  来源:igfitidea点击:

How to resize DirectX window efficiently?

c++windowsvisual-c++directx

提问by Rookie

I looked at this site example: http://www.codesampler.com/dx9src/dx9src_6.htm

我看了这个网站的例子:http: //www.codesampler.com/dx9src/dx9src_6.htm

But the code is rather weird: it frees every texture, vertex buffer, everything! and then builds them up again: loads the model from disk ... i dont think that is very efficient! OpenGL can do window resizing on fly with no such limitations. How can i do the same as OpenGL does: efficient window resize with no need to free every resource in my program?

但是代码很奇怪:它释放了每个纹理,顶点缓冲区,一切!然后再次构建它们:从磁盘加载模型......我认为这不是很有效!OpenGL 可以在没有此类限制的情况下动态调整窗口大小。我该如何做与 OpenGL 相同的事情:有效地调整窗口大小而无需释放程序中的每个资源?

I tried the code in the above link example, without those invalidateDeviceObjects/restoreDeviceObjects function calls, but it didnt work.. so i guess it must be done? I hope not, or window resizing would be a pain on larger apps where you have hundreds of megabytes of data allocated in textures, models etc.

我尝试了上面链接示例中的代码,没有那些 invalidateDeviceObjects/restoreDeviceObjects 函数调用,但它不起作用..所以我想它必须完成?我希望不会,否则窗口大小调整对于在纹理、模型等中分配了数百兆字节数据的大型应用程序来说会很痛苦。

回答by bobobobo

This is a consequence of how d3d9 was designed. Resizing a d3d9 window requires a call to IDirect3DDevice9::Reset, and from the docs:

这是 d3d9 设计方式的结果。调整 d3d9 窗口的大小需要调用IDirect3DDevice9::Reset,并且来自文档:

Calling IDirect3DDevice9::Reset causes all texture memory surfaces to be lost, managed textures to be flushed from video memory, and all state information to be lost.
调用 IDirect3DDevice9::Reset 会导致所有纹理内存表面丢失,托管纹理从视频内存中刷新,并且所有状态信息丢失。

So it is what it is. You don't actually customarily changethe resolution of the display, at all, ever, from game start to game end. Usually you set the resolution on game start, allow resetting in some special settings screen.

所以就是这样。实际上,从游戏开始到游戏结束,您实际上根本不会更改显示器的分辨率。通常您在游戏开始时设置分辨率,允许在某些特殊设置屏幕中重置。

Now I should add, if you are using D3D9, there is a special resource allocation flag you can use (D3DPOOL_MANAGED) that will actually take care of re-loading resources for you. So a local (system memory) copy of all textures, vertex buffers, etc is automaticallymaintained in system memory, and when the GPU is reset, those textures etc are automatically copied back down to the GPU.

现在我应该补充一点,如果您使用的是 D3D9,您可以使用一个特殊的资源分配标志 ( D3DPOOL_MANAGED),它实际上会为您重新加载资源。因此,所有纹理、顶点缓冲区等的本地(系统内存)副本会自动保存在系统内存中,当 GPU 重置时,这些纹理等会自动复制回 GPU。

Keep in mind D3DPOOL_MANAGEDisn't allowed if you're using the newer IDirect3DDevice9Ex.

请记住,D3DPOOL_MANAGED如果您使用的是较新的IDirect3DDevice9Ex.

回答by Mark Taylor

In a non-game business application where frequent resizing windows was an important part of the UI, I worked around this issue by creating the D3D device as a memory device at the detected full-screen resolution, then used StretchBlt in the CWnd::OnDraw(...) to resize the memory bitmap as it was being written from the backbuffer to the screen. This isn't a good solution for high frame rate animation, but in a relatively static view situation where the user's actions control the object/view motion it works better than the tear-down and recreate approach.

在频繁调整窗口大小是 UI 的重要组成部分的非游戏业务应用程序中,我通过在检测到的全屏分辨率下创建 D3D 设备作为内存设备来解决这个问题,然后在 CWnd::OnDraw 中使用 StretchBlt (...) 调整内存位图的大小,因为它是从后台缓冲区写入屏幕的。对于高帧率动画来说,这不是一个好的解决方案,但在相对静态的视图情况下,用户的动作控制对象/视图运动,它比拆卸和重新创建方法更有效。

回答by Dwedit

Create the back buffer to be the monitor's max resolution, and use SWAPEFFECT_COPY.

创建后台缓冲区作为显示器的最大分辨率,并使用SWAPEFFECT_COPY.

When drawing, have your code draw to the current window size.

绘制时,让您的代码绘制到当前窗口大小。

When calling Present, provide the window size for the source and destination rectangles.

调用时Present,提供源矩形和目标矩形的窗口大小。

Then you have a resizable window that doesn't need to recreate the D3D device when the window size changes.

然后你就有了一个可调整大小的窗口,当窗口大小改变时,它不需要重新创建 D3D 设备。