【问题标题】:Why are the D3D12 samples using WM_PAINT?为什么 D3D12 样本使用 WM_PAINT?
【发布时间】:2021-10-14 11:51:15
【问题描述】:

如果您正在尝试对游戏进行编程,您真的不应该等待来自操作系统的WM_PAINT 信号来绘制。您应该尽快重复绘制。

为什么在 D3D 示例代码中是rendering happening in WM_PAINT?

如何在不等待来自操作系统的WM_PAINT 信号的情况下重新处理 D3D12 示例以尽快渲染

【问题讨论】:

    标签: direct3d12


    【解决方案1】:

    GitHub: DirectX-Graphics-Samples 上的“Hello, World”DirectX 12 示例依赖于这样一个事实:如果您调用 PeekMessage 并且没有其他可用消息,它创建一条 WM_PAINT 消息:

    MSG msg = {};
    while (msg.message != WM_QUIT)
    {
        // Process any messages in the queue.
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    

    Microsoft Docs

    通常游戏渲染循环不依赖于“神奇的 WM_PAINT”行为,而我在 GitHub: directx-vs-templates 中所拥有的:

    MSG msg = {};
    while (WM_QUIT != msg.message)
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            g_game->Tick();
        }
    }
    
    g_game.reset();
    

    WM_PAINT 唯一要做的就是清除屏幕——对调整大小进行特殊处理:

    case WM_PAINT:
        if (s_in_sizemove && game)
        {
            game->Tick();
        }
        else
        {
            PAINTSTRUCT ps;
            (void)BeginPaint(hWnd, &ps);
            EndPaint(hWnd, &ps);
        }
        break;
    

    这里Tick 是一个执行UpdateRender 的方法,但根据StepTimer 的模式,它可能每帧调用Update 不止一次。

    最终,两个 Win32 的“消息泵”实现了基本相同的目标。

    【讨论】:

    • 实际上,我只记得您应该致电BeginPaint/EndPaint 以向Win O/S 发出您已绘制窗口的信号。我认为正在发生的事情是WM_PAINT 消息被一遍又一遍地重新发送,因为客户区没有得到验证,因为对BeginPaint/EndPaint 的调用丢失了
    猜你喜欢
    • 2014-04-21
    • 2020-12-23
    • 2014-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-22
    • 1970-01-01
    相关资源
    最近更新 更多