如何在大窗口(DWM)上有效地渲染Direct3D / C ++中的小精灵?

时间:2014-08-07 23:21:44

标签: c++ directx direct3d directx-9 dwm

我在DirectX / C ++中实现自定义光标,该游标在桌面顶部的透明窗口上绘制。

我已将其剥离为basic example。在DWM上执行Direct3D的魔力基于此article on Code Project

问题在于,当使用非常大的窗口(例如2560x1440)作为DirectX渲染的基础时,根据GPU-Z,它将提供高达40%的GPU负载。即使我展示的唯一东西是静态的128x128精灵,或者根本没有。如果我使用像256x256这样的区域,GPU负载大约为1-3%。

基本上这个循环会让GPU在一个大窗户上疯狂,而它在一个小窗口上顺利航行:

while(true) {
    g_pD3DDevice->PresentEx(NULL, NULL, NULL, NULL, NULL);
    Sleep(10);
}

所以它似乎重新呈现整个屏幕是否有任何变化,我是对的吗?我可以告诉Direct3D只重新渲染需要更新的特定部分吗?

编辑: 我找到了一种通过向PresentEx提供RGNDATA Dirty区域信息来告诉Direct3D渲染特定部分的方法。它现在是1%GPU负载而不是20-40%。

    std::vector<RECT> dirtyRects;

    //Fill dirtyRects with previous and new cursor boundaries

    DWORD size = dirtyRects.size() * sizeof(RECT)+sizeof(RGNDATAHEADER);

    RGNDATA *rgndata = NULL;

    rgndata = (RGNDATA *)HeapAlloc(GetProcessHeap(), 0, size);


    RECT* pRectInitial = (RECT*)rgndata->Buffer;
    RECT rectBounding = dirtyRects[0];

    for (int i = 0; i < dirtyRects.size(); i++)
    {
        RECT rectCurrent = dirtyRects[i];
        rectBounding.left = min(rectBounding.left, rectCurrent.left);
        rectBounding.right = max(rectBounding.right, rectCurrent.right);
        rectBounding.top = min(rectBounding.top, rectCurrent.top);
        rectBounding.bottom = max(rectBounding.bottom, rectCurrent.bottom);

        *pRectInitial = dirtyRects[i];
        pRectInitial++;
    }

    //preparing rgndata header
    RGNDATAHEADER  header;
    header.dwSize = sizeof(RGNDATAHEADER);
    header.iType = RDH_RECTANGLES;
    header.nCount = dirtyRects.size();
    header.nRgnSize = dirtyRects.size() * sizeof(RECT);
    header.rcBound.left = rectBounding.left;
    header.rcBound.top = rectBounding.top;
    header.rcBound.right = rectBounding.right;
    header.rcBound.bottom = rectBounding.bottom;

    rgndata->rdh = header;

    // Update display
    g_pD3DDevice->PresentEx(NULL, NULL, NULL, rgndata, 0);

但这是我不明白的事情。如果我添加以下

,它将只提供1%的GPU负载
    SetLayeredWindowAttributes(hWnd, 0, 180, LWA_ALPHA);

我还是希望它透明,所以它很好,但过了一段时间我会得到一些奇怪的撕裂效果。我移动光标的速度越快越明显。那是什么来的?它看起来像提供的图像。我确信我已经完全准确地设置了脏物。

tearing

上述撕裂似乎因计算机而异。

0 个答案:

没有答案