Я реализую пользовательский курсор в DirectX / C ++, который рисуется в прозрачном окне в верхней части рабочего стола.
Я раздели его до основной пример. Магия выполнения Direct3D на DWM основана на этом статья о проекте Code
Проблема состоит в том, что при использовании очень большого окна (например, 2560×1440) в качестве основы для визуализации DirectX, оно будет давать до 40% загрузки графического процессора в соответствии с GPU-Z. Даже если я показываю только статический спрайт 128×128 или вообще ничего. Если я использую область, такую как 256×256, загрузка графического процессора составляет около 1-3%.
По сути, этот цикл заставит GPU сходить с ума по большому окну, в то время как он плавно движется по маленькому окну:
while(true) {
g_pD3DDevice->PresentEx(NULL, NULL, NULL, NULL, NULL);
Sleep(10);
}
Похоже, что он перерисовывает весь экран независимо от того, что-то меняется или нет, я прав? Могу ли я сказать Direct3D перерисовывать только те детали, которые необходимо обновить?
РЕДАКТИРОВАТЬ:
Я нашел способ сообщить Direct3D для рендеринга определенной части, предоставив информацию о грязном регионе RGNDATA для PresentEx. Теперь загрузка графического процессора составляет 1% вместо 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% загрузки графического процессора, если я добавлю следующее
SetLayeredWindowAttributes(hWnd, 0, 180, LWA_ALPHA);
В любом случае, я хочу, чтобы он был прозрачным, и это хорошо, но вместо этого через некоторое время я получаю некоторые странные эффекты. Чем заметнее, тем быстрее я двигаю курсор. Откуда это? Это выглядит как изображение. Я уверен, что я установил грязные каноны совершенно точно.
Вышеупомянутые разрывы, кажется, отличаются от компьютера к компьютеру.
Задача ещё не решена.