-1

This is an extended question about CreateDIBSection.

I used it to get the bitMap bit value of the same image which drawn using Direct3D, to verify its consistency of Direct3D rendering, i.e. as long as I get the same bitMap bit value every time I run the program (draw the same image), then I consider the Direct3D rendering passed.

However, the weird thing is that I only able to get the same bitMap bit value (from "image" as shown in the code below) for the first 4 times of running the program (that draw the same image), on 5th times onward, the result of the bitMap bit values will start to change slightly (only a small number of bytes changed, most of the remaining bytes still the same), and never get back the same bitMap bit values as the first 4 times.

But, once I restart the computer and start to run my program again, I get back the same pattern: the bitMap bit values which I get during the first 4 times of running the program are exactly the same as the first trial, but the following runs will result in different bitMap bit values.

Two possible reasons which I can think of:

  1. There are some slight inconsistency in the rendering by GPU, means the GPU might contain some defects, but I am not the GPU expert, so I don't really have the confident to conclude it in this way.

  2. I knew the CreateDIBSection will handle the memory allocation on its own, is that possible that the memory is not cleaned properly after the call of DeleteObject and impact some of the bits in the bitMap bit values? (I had followed the freeing memory steps in this discussion, but it doesn't help me to get the consistent bitMap bit values of the same image.)

Question: How can we get the consistent bitMap bit value every time (is that possible?) when we are getting it out of the same image?

Thanks.

Codes:

#include <Windows.h>
#include <cstdint>
HWND m_hwnd;

void GetBitMapInfo(const int& x_Coordinate, const int& y_Coordinate, const int& iWidth, const int& iHeight)
{

DWORD imageSize = iWidth * iHeight * 4;

// Get the display window
HDC displayWindow = GetDC(m_hwnd);
HDC hdc = CreateCompatibleDC(displayWindow);

// Fill in the Bitmap information
BITMAPINFO bmpInfo;
ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = iWidth;
bmpInfo.bmiHeader.biHeight = iHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biSizeImage = 0;
bmpInfo.bmiHeader.biClrUsed = 0;
bmpInfo.bmiHeader.biClrImportant = 0;


// Create the storage for the pixel information
uint8_t* image = nullptr;

// Populate the storage with the BMP pixel information
HBITMAP hBitmap = CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, (void**)(&image), nullptr, NULL);

HGDIOBJ save = SelectObject(hdc, hBitmap);
BitBlt(hdc, x_Coordinate, y_Coordinate, iWidth, iHeight, displayWindow, 0, 0, SRCCOPY);


DeleteObject(SelectObject(hdc, save));
DeleteDC(hdc);
DeleteDC(displayWindow);
DeleteObject(hBitmap);

return;
}

int main()
{
    GetBitMapInfo(0, 0, 1920, 1080);

    return 0;
}
MK 5012
  • 29
  • 1
  • 9
  • We have no idea how you're comparing your values. Maybe you are just doing it wrong. – IInspectable Jan 31 '20 at 16:21
  • **1.)** IMO a possibility. Faulty GPU hardware, faulty driver, etc. Try to update your GPU driver first. Then try to rule out, that the problem isn't actually in the program that creates the image. **2.)** Not very likely. You are overwriting the DIB section memory completely using `BitBlt`, so it doesn't matter what it's previous content was. – zett42 Jan 31 '20 at 18:02
  • Are you grabbing just the window you care about? The code above grabs the desktop window for the primary monitor (up to 1920x1080). Is there anything else changing? Does anything from the desktop show through transparent or translucent portions of your window (e.g., background windows or the time on the task bar)? Are you running a program like f.lux which changes the color rendering of the device throughout the day? – Adrian McCarthy Jan 31 '20 at 18:52
  • The code sample has some GDI resource handling bugs. I doubt they're related to your problem, but it wouldn't be a bad idea to clean them up. `DeleteObject(SelectObject(hdc, save))` is fine, but a couple lines later you call `DeleteObject(hBitmap)`, which is redundant. `DeleteDC(hdc)` is fine because you created the DC, but `DeleteDC(displayWindow)` should be `ReleaseDC(m_hwnd, displayWindow)`. – Adrian McCarthy Jan 31 '20 at 18:55
  • How (and at what point) are you comparing the image you grab to the reference image? Are you checking just the RGB channels and ignoring the fourth byte of each pixel? (BitBlt will likely not preserve the values in the fourth byte because, with one or two tiny exceptions, GDI does not know anything about alpha channels). Have you tried selecting hBitmap out of the DC before inspecting the pixels? In some cases, that might be necessary for synchronization. – Adrian McCarthy Jan 31 '20 at 19:02
  • Have you tried to visualize the differences? How many pixels differ? Are they close to the right values or way off? Which pixels differ? You could change the values of the mismatched pixels to something that would stand out (like magenta) and then render it back to a window to see if it's a clump of pixels, pixels along an edge, pixels corresponding to something outside the Direct3D rendering, etc. – Adrian McCarthy Jan 31 '20 at 19:04
  • @IInspectable I computed CRC for the bitmap bit value which returned from the function and compare it with a reference value, this is the way I used to verify the consistency of the same image rendering. – MK 5012 Feb 03 '20 at 01:53
  • @zett42 Noted and thanks, I will try out your suggestion to update the GPU driver. – MK 5012 Feb 03 '20 at 01:55
  • @AdrianMcCarthy I actually get the rendering in full screen mode and it is not transparent, so I think we can exclude the possibility that rendering contains the difference due to the background changes like the time on the taskbar. – MK 5012 Feb 03 '20 at 02:22
  • @AdrianMcCarthy I changed the DeleteDC(displayWindow) to ReleaseDC(m_hwnd, displayWindow), the returned bitmap bit value still has the same issue, across repeated runs, it returned the consistent bitMap bit values upto first 4 runs, then the following trials will have different values, but those different values are identical from previous repeated run, from the 5th run to about 25th run, but from 26th and above, the bitmap bit values will start to change in different ways. – MK 5012 Feb 03 '20 at 03:53
  • @AdrianMcCarthy I visualized the difference of the bitMap bit values by outputting those bitMap bit values into a text file for each run and compared those different one and realized most of the bytes are the same values, only a few bytes have minor different, e.g. 155 becomes 154. – MK 5012 Feb 03 '20 at 03:56
  • @AdrianMcCarthy even the difference is small, this gives me a significant impact as my test will flag this as failed due to inconsistent CRC, which I used it to compare the rendering consistency based on the returned bitmap bit values. – MK 5012 Feb 03 '20 at 03:59
  • Don't explain what (you think) you're doing. Show the code that does it. If there's a bug in the code, there's no way you are going to tell us about it, because you don't even know. – IInspectable Feb 03 '20 at 09:43
  • If you capture image from desktop, it is possible that two images from two runs are different. Show a mini, complete and reproducible sample with how to save TXT file and compare, so we can do a further investigation. – Rita Han Feb 03 '20 at 10:43

1 Answers1

0

I finally root cause the issue, which is not related to CreateDBSection(), instead it is due to the rotation angle, which I passed it to DirectX::XMMatrixRotationY to control the rotation of the 3D object rendering (under GraphicsClass::Frame() of the tutorial, link below).

The original code is actually setting it in such a way that it will loop thru the 3D object rendering (and rotating) infinitely, until user press escape key to exit, so it makes the rotation angle variable static.

But I only want the 3D object to have one complete rotation. Since the angle is a static variable, the logic goes wrong for my modified program, which only make 1 complete rotation. Consequently, the static angle gets build up from previous run (I loop my modified test multiple times during my validation) and this cause the starting rotation angle is different for the following repeated test run, as the angle is increasing until it resets itself back to 0 degree and start over again.

And due to this little shift, the final rendering frame will stop at different part. The returned bitmap bit values from CreateDBSection() (I use it for my own CRC check purpose to verify the consistency of the 3D object rendering), which is based on the last displayed frame after the rendering done and before the window being destroyed, will of course different than the beginning runs and thus will make my CRC (cyclic redundancy check) keeps changing.

I corrected my code so that every time of the test execution, the rotation will always start at zero degree and end with 360 degree, then exit the test. After that, the returned bitmap bit values are consistent no matter how many loops I repeated run for the test.

Summary:

  1. CreateDBSection() has no issue for the returned bitmap bit values (I am the one got problem for not clearly understand the Direct3D rendering and my poor C++, I will improve myself;))
  2. I had tried out the Graphics driver updates (by checking the driver status via Intel Driver & Support Assistant, although it does not help for my case as after the checking, my graphics driver is up-to-date, it is a helpful debugging step in some situation.

Thanks all for the helps.

MK 5012
  • 29
  • 1
  • 9