PeekMessage()需要1-2毫秒来检索WM_MOUSEMOVE消息?

时间:2014-10-03 19:19:16

标签: windows directx

我看过很多关于PeekMessage和WM_MOUSEMOVE的帖子,但到目前为止我还没有发现任何与性能有关的帖子。

长话短说;我正在进行PC游戏开发,昨天我注意到我可以将我们的应用程序从稳定的500+ FPS(在菜单中)带到单个数字FPS(低至6),只需快速移动鼠标即可。 / p>

经过几个小时的挖掘和分析,我发现源是PeekMessage()。对于那条消息不是DispatchMessage(),只是偷看。我测量的是单独调用该函数,频率为1-2毫秒(每帧多次)。如果将它与快速鼠标移动相结合,那么抽取消息队列可能会使每帧渲染成本超过1000-2000毫秒。听起来很荒谬,但实际上我从MS下载了一个超级基本的DirectX样本并在那里测试了相同的结果,结果相同。

整个样本太大而无法在此处粘贴,但如果您想尝试,请在以下位置下载示例: http://code.msdn.microsoft.com/Direct3D-Tutorial-Win32-829979ef

并进行以下更改;

typedef unsigned __int64    QWORD;      // 64-bit unsigned.
DOUBLE GSecondsPerCycle;
void appInitTiming(void)
{
    LARGE_INTEGER Frequency;
    QueryPerformanceFrequency(&Frequency);
    GSecondsPerCycle = 1.0 / Frequency.QuadPart;
}

QWORD appCycles()
{
    LARGE_INTEGER Cycles;
    QueryPerformanceCounter(&Cycles);
    return Cycles.QuadPart;
}

int WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow )
{
    UNREFERENCED_PARAMETER( hPrevInstance );
    UNREFERENCED_PARAMETER( lpCmdLine );

    if( FAILED( InitWindow( hInstance, nCmdShow ) ) )
        return 0;

    if( FAILED( InitDevice() ) )
    {
        CleanupDevice();
        return 0;
    }
    appInitTiming();

    // Main message loop
    MSG msg = {0};
    while( WM_QUIT != msg.message )
    {
        QWORD StartCycles = appCycles();
        BOOL hasMsg = PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE );
        const QWORD DeltaCycles = appCycles() - StartCycles;
        double deltaMS = DeltaCycles * GSecondsPerCycle * 1000.0;
        if (deltaMS > 1/* || msg.message == 512*/)
        {
            std::ostringstream os;          
            os << "SlowPeekMsg ID: " << msg.message << ", time: " << deltaMS << "ms" << std::endl;
            std::string buffer(os.str());
            OutputDebugStringA(buffer.c_str());
        }

        if(hasMsg)
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
        else
        {
            Render();
        }
    }

    CleanupDevice();

    return ( int )msg.wParam;
}

1 个答案:

答案 0 :(得分:-1)

放手一搏:

UNREFERENCED_PARAMETER( hPrevInstance );
UNREFERENCED_PARAMETER( lpCmdLine );

if( FAILED( InitWindow( hInstance, nCmdShow ) ) )
    return 0;

if( FAILED( InitDevice() ) )
{
    CleanupDevice();
    return 0;
}
appInitTiming();

// Main message loop
MSG msg = {0};
while( WM_QUIT != msg.message )
{
    QWORD StartCycles = appCycles();
    while(PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE ))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    const QWORD DeltaCycles = appCycles() - StartCycles;

    double deltaMS = DeltaCycles * GSecondsPerCycle * 1000.0;
    if (deltaMS > 1/* || msg.message == 512*/)
    {
        std::ostringstream os;          
        os << "SlowPeekMsg ID: " << msg.message << ", time: " << deltaMS << "ms" << std::endl;
        std::string buffer(os.str());
        OutputDebugStringA(buffer.c_str());
    }

    Render();
}

CleanupDevice();

return ( int )msg.wParam;

它可能只是像上面提到的评论者那样的钩子。