6

Any ideas/workarounds on how to improve my BitBlt() reliability when running it in VMware? I have a timer that measures the time spent:

SmartTimer debugTimer = SmartTimer();
debugTimer.restart();
int ms1 = debugTimer.elapsedTimeMs();
POINT origin = { rect.left, rect.top };
int ms2 = debugTimer.elapsedTimeMs();
ClientToScreen(win_hwnd, &origin);
int ms3 = debugTimer.elapsedTimeMs();
BitBlt(hMemoryDC, 0, 0, (rect.right - rect.left) + 1, (rect.bottom - rect.top) + 1, hScreenDC, origin.x, origin.y, SRCCOPY); // SRCCOPY
int ms4 = debugTimer.elapsedTimeMs();
if (ms1 > 150 || ms2 > 150 || ms3 > 150 || ms4 > 150) {
    logs(std::format("getPixelData took very long: {} {} {} {}", ms1, ms2, ms3, ms4));
}

I have observed in the logs, often it says "0, 0, 0, 420" (or similar) indicating that BitBlt() took a very long time, even in cases where I only BitBlt() one pixel.

I know that for reading one pixel, there is GetPixel(), but for some reason this was very buggy for me when reading from a game. It would at times get pixel value 255, 255, 255 for everything, but when I switched to BitBlt(), the bug stopped happening.

It also seems like BitBlt() is usually very fast, but sometimes it is very slow.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
pete
  • 1,878
  • 2
  • 23
  • 43
  • Try disabling the 3D support in VMWare, lately I've found this is very buggy. – Jonathan Potter Nov 27 '21 at 09:47
  • How do you run games in VMware without 3D support? won't the performance be too slow? – pete Nov 27 '21 at 09:54
  • Bit block copy between devices? that does not sound like a light operation. Depending what is the origin, the destination, if devices are ready, the size of the rectangle... – Adrian Maire Dec 07 '21 at 10:41
  • I'm not doing anything between devices. Just a program inside a VM doing bitblt, sometimes 2 VM's simultaneously but they are separate and isolated from each other. Nothing cross-device nor cross-VM. I also noticed that if I click to watch a different VM in VMWare, it will log the message that bitblt took a long time. Similar deal for if I do too much strenuous work on the host machine. I understand doing stuff on the host machine will lower performance somewhat but I would not expect so much lag for a tiny one-pixel bitblt. – pete Dec 07 '21 at 12:15
  • 1
    @pete you could try to check how much time your thread actually spent executing by calling [`GetThreadTimes`](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadtimes) at the beginning and end and then comparing the change of `lpKernelTime` & `lpUserTime`. If the time you get using this method is a lot smaller than the time your `SmartTimer` reports, then your thread simply got preempted (potentially multiple times) during that code fragment. – Turtlefight Dec 10 '21 at 19:29
  • If preemption is the problem you can try to increase the priority of your vm in relation to your host (that depends on which virtualization provider you're using - [maybe this](https://www.vmware.com/support/ws5/doc/ws_learning_prefs_priority.html)) and / or increase the process / thread priority of your `BitBlt()`-process with [`SetPriorityClass()`](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setpriorityclass) / [`SetThreadPriority()`](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadpriority) – Turtlefight Dec 12 '21 at 18:07
  • Beware though that very high priority levels (especially realtime priority) can result in your vm becoming completely unresponsive until the high-priority thread yields. [Required Raymond Link](https://devblogs.microsoft.com/oldnewthing/20100610-00/?p=13753) – Turtlefight Dec 12 '21 at 18:12

0 Answers0