修复 Windows 7 上的 DirectX 7 延迟?

Posted

技术标签:

【中文标题】修复 Windows 7 上的 DirectX 7 延迟?【英文标题】:Fix for DirectX 7 latency on Windows 7? 【发布时间】:2013-05-17 23:02:05 【问题描述】:

我们有一个针对 DirextX 7 SDK 编程的软件(即代码使用 LPDIRECTDRAWSURFACE7 等)并全屏运行。主要任务是以可靠的方式在屏幕上放置一些东西以响应外部触发。这在 Windows XP 上表现得非常好:基本上,软件等待某个触发,当触发时,创建一个新帧,将其放入后缓冲区,然后告诉 DX 翻转缓冲区。结果是触发和帧在屏幕上有效显示之间的近似延迟,取决于显卡和驱动程序,对于 60Hz 屏幕,为 3 帧或 50 毫秒。这是在各种运行 NVidia 卡的系统上进行测试的。在一些具有高端卡的系统上,我们甚至可以得到 2 帧。

但是,在 Windows 7 上运行相同的软件(根本没有安装其他软件)时,我们不能低于 5 帧。这意味着在管道中的某个地方,操作系统或驱动程序或两者都吃掉了 2 个额外的帧,这对于应用程序来说几乎是不可接受的。我们尝试禁用航空/桌面组合/不同的驱动程序版本/不同的视频卡,但无济于事。

这是从哪里来的?这在某处有记录吗? 有没有简单的修复方法?我知道 DirectX 7 很旧,但是升级到重新编译一个更新的版本可能需要大量的工作,所以另一种类型的修复会很好。也许可以在代码中设置一些标志?

编辑这是一些似乎相关的代码:

创建前/后表面:

ddraw7->SetCooperativeLevel( GetSafeHwnd(),
  DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_MULTITHREADED )

DDSURFACEDESC2 desc;
ZeroMemory( &desc, sizeof(desc) );
desc.dwSize = sizeof( desc );
desc.dwFlags =  DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
                      DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE |
                      DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
desc.dwBackBufferCount = 1;
ddraw7->CreateSurface( &desc, &primsurf, 0 )

DDSCAPS2 surfcaps;
ZeroMemory( &surfcaps,sizeof( surfcaps ) );
surfcaps.dwCaps = DDSCAPS_BACKBUFFER;
primsurf->GetAttachedSurface( &surfcaps, &backsurf );

在帧被绘制之前创建用于渲染帧的表面:

DDSURFACEDESC2 desc;
ZeroMemory( &desc, sizeof(desc) );
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS ;
desc.dwWidth = w;
desc.dwHeight = h;
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
desc.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8;

LPDIRECTDRAWSURFACE7 surf;
HRESULT r=ddraw7->CreateSurface( &desc, &surf, 0 )

渲染循环,在OnIdle:

//clear surface
DDBLTFX bltfx;
ZeroMemory( &bltfx, sizeof(bltfx) );
bltfx.dwSize = sizeof( bltfx );
bltfx.dwFillColor = RGBtoPixel( r, g, b );
backsurf->Blt( rect, 0, 0, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx )

//blit some prerendered surface onto it, x/y/rect etc are calculated properly)
backsurf->BltFast( x, y, sourceSurf, s&sourceRect, DDBLTFAST_WAIT );

primsurf->Flip( 0, DDFLIP_WAIT )

primsurf->Blt(&drect,backsurf,&srect,DDBLT_WAIT,0);

【问题讨论】:

想解释一下为什么这被否决了吗?例如,如果它不属于这里,至少说明原因。 在***上问它,因为这是一个编码问题。 是的,我不确定,这可能只是一些配置问题 - 无论如何投票决定关闭以移至 SO 这可能是驱动问题 - 较新的显卡/驱动使用 DX9/10 模拟 DX7,这可能会导致延迟。 @Rushyo 查看编辑.. 我花了将近一个小时来提取这个,仅这一点就充分表明我们可能最好从头开始重写这个东西 【参考方案1】:

我认为 Windows XP 是一个红鲱鱼。上一个直接运行 DirectX 7 的 Windows 版本是 Windows 2000。Windows XP 只是在 DX9 中模拟 DX7,与 Windows 7 一样。

我大胆猜测您的应用程序使用调色纹理,并且当 DX 模拟该功能(因为它在 DX7 之后被删除)时,它使用索引颜色生成纹理。您可以尝试使用 GPUView 对应用程序进行分析,以查看将纹理推送到 GPU 是否存在延迟。例如,可能是 Win7 驱动程序先对其进行压缩?

【讨论】:

我们没有使用调色纹理,或任何其他特殊的 DX 功能:所有内容都直接逐个像素地写入表面内存。但是感谢您提到 GPUView,虽然不知道但它似乎非常有趣。 @stijn 你在运行任何着色器吗? 没有;没有代码 atm 但渲染循环只是在表面中设置一些像素,将表面 blits 到后缓冲表面上并调用 Flip()

以上是关于修复 Windows 7 上的 DirectX 7 延迟?的主要内容,如果未能解决你的问题,请参考以下文章

DirectX修复工具使用技巧之三——命令行与配置文件参数介绍

如何在使用 cx_Freeze 6.0b1 冻结的 Linux 上修复 python 3.7.3 脚本上的 numpy 依赖项路径?

Windows 上的 MySQL 安装 - 以及如何修复丢失的 mysql.user?

AnkhSVN 在 Windows 7(64 位)上的 VS 2008 中未显示为源代码控制插件

Windows 8.1 上的 DirectX 11 缺少 SDK 组件

Python3 在 DirectX 游戏中移动鼠标