Aurimas
August 9th, 2008, 02:24 PM
C# and C++ (Is standalone C++ project in VS managed?) here are both managed (VS).
For time measurements using high resolution C++ timer.
Used capture screen.
These two functions creates in-memory bitmaps. C# variant returns instance of Bitmap and C++ - array of bits. Both of these need the same routine to get called, creating HDC's and HBITMAP.
The 1st question is about GetDIBits first argument, it requires HDC and if I put hDC or hMemDC the result is the same, both gives the same. So which one should be used?
The 2nd question. Both of these functions has same working time ~15ms (res 1280x800x32), when they are copying from Windows (for example Desktop). But as tried DirectX application C# working time was 7-10ms same in C++. But if counting all routine (not just this function call), in Windows it's take ~17ms to take bitmap and in DirectX app it's about ~30-35ms. Can DX app have such a big impact even on dual core (as i use)?
[Edited] Also it looks that screen capturing into memory is very dependent on DX app, more processor time consuming (I think the reason is that game is multi-threading) game took about 50-120ms to save picture in-memory using C++ while C# took about 100-120ms. [Edited] GDI32.BitBlt calling time is not constant: in Windows it takes only 0.2ms, in game menu 20ms (maybe game loop makes it so large?), in game action it takes >100ms. Is there any chance to decrease this time?
The 3rd question. GetDIBits used to produce lines of bitmap in reverse, MSDN said that if u want correct, pass in a negative bitmap height. So it works correct now. Another thing is format: C# Color struct saves color as ARGB and C++ function produces DWORDs as BGRA quad. Is there any not time consuming solution to reverse it on C++ side or C#'s side?
The 4th question. The bitmap data produced by these functions differs in some alpha bytes. For example C# function always produces 255, but C++ for DirectX application took ~95% of 255 and the rest values were between 128 and 255. In Windows C++ produces only 0 for alpha. Is there any why to make C++ variant always produce 255 for alpha also? And why this happens? [Edited] The simplest replace for this in C++ takes 1.5ms without checking value and ~1-1.7ms with checking value.
The 5th question. Also i would like to have fast access to bitmap data, as I tested with C# (Color val = bitmap.GetPixel(i, j); ) i got ~750 reads per ms, and C++ (int val = *((int*)lpBits + i * 800 + j); ) gave me ~250000 (yes 250k) reads per ms ([Edited] as this accessed via C# code it gives 58k)!! If i move C++ from managed environment to unmanaged one, would i gain a noticeable performance? Would be GCC compiler the best choice?
[Edited] Just noticed another weird thing: taking into account all initialization routine (creating HDC's, copying, etc.) C# working time is increasing only by 1-2ms, but for C++ it adds huge amount about 50-60ms. I'll have to check why this happens. [Edited] That has happened because C# calls to USER32.GetSystemMetrics functions took <1ms, but somehow C++ manages to get it called in 50-60ms. Is there a solution for this? [Edited] GetDeviceCaps solved it.
Sorry, for my not accurate English.
---------------------------------------------------------------------------------------------
[Edited] Finally managed to make it work correctly.
The above C++ realization was unmanaged as managed means managed by garbage collector and classes in C++ are declared as ref class.
Now I have managed C++ class that calls WIN32 API functions and this C++ class is directly used by C#.
The answer to the 1st question is that it should be hMemDC as first parameter, because couldn't get it work with hDC in managed environment.
For the second answer: in managed environment average times now are (tested 100 times):
Windows ~23ms
Game Menu ~34ms
Game Action ~38ms (oh it lagged, I think this time is still optional)
Btw these times are for 1280x800x32, which means ~4MB, repeating all routines: getting, releasing, deleting objects and in-memory bitmaps.
The 3rd answer: somehow in managed environment it works as it should, but I don't understand how Color.FromArgb(int arg) takes BGRA quad and handles it, however it just works(Is C# Color BGRA also?).
Answer number 4th: it's still a problem, i have changes alpha values by hand.
The 5th: Here are numbers for accesses per ms:
Windows ~85k
Game ~54k-70k
So I think it's quite good result for managed environment.
For time measurements using high resolution C++ timer.
Used capture screen.
These two functions creates in-memory bitmaps. C# variant returns instance of Bitmap and C++ - array of bits. Both of these need the same routine to get called, creating HDC's and HBITMAP.
The 1st question is about GetDIBits first argument, it requires HDC and if I put hDC or hMemDC the result is the same, both gives the same. So which one should be used?
The 2nd question. Both of these functions has same working time ~15ms (res 1280x800x32), when they are copying from Windows (for example Desktop). But as tried DirectX application C# working time was 7-10ms same in C++. But if counting all routine (not just this function call), in Windows it's take ~17ms to take bitmap and in DirectX app it's about ~30-35ms. Can DX app have such a big impact even on dual core (as i use)?
[Edited] Also it looks that screen capturing into memory is very dependent on DX app, more processor time consuming (I think the reason is that game is multi-threading) game took about 50-120ms to save picture in-memory using C++ while C# took about 100-120ms. [Edited] GDI32.BitBlt calling time is not constant: in Windows it takes only 0.2ms, in game menu 20ms (maybe game loop makes it so large?), in game action it takes >100ms. Is there any chance to decrease this time?
The 3rd question. GetDIBits used to produce lines of bitmap in reverse, MSDN said that if u want correct, pass in a negative bitmap height. So it works correct now. Another thing is format: C# Color struct saves color as ARGB and C++ function produces DWORDs as BGRA quad. Is there any not time consuming solution to reverse it on C++ side or C#'s side?
The 4th question. The bitmap data produced by these functions differs in some alpha bytes. For example C# function always produces 255, but C++ for DirectX application took ~95% of 255 and the rest values were between 128 and 255. In Windows C++ produces only 0 for alpha. Is there any why to make C++ variant always produce 255 for alpha also? And why this happens? [Edited] The simplest replace for this in C++ takes 1.5ms without checking value and ~1-1.7ms with checking value.
The 5th question. Also i would like to have fast access to bitmap data, as I tested with C# (Color val = bitmap.GetPixel(i, j); ) i got ~750 reads per ms, and C++ (int val = *((int*)lpBits + i * 800 + j); ) gave me ~250000 (yes 250k) reads per ms ([Edited] as this accessed via C# code it gives 58k)!! If i move C++ from managed environment to unmanaged one, would i gain a noticeable performance? Would be GCC compiler the best choice?
[Edited] Just noticed another weird thing: taking into account all initialization routine (creating HDC's, copying, etc.) C# working time is increasing only by 1-2ms, but for C++ it adds huge amount about 50-60ms. I'll have to check why this happens. [Edited] That has happened because C# calls to USER32.GetSystemMetrics functions took <1ms, but somehow C++ manages to get it called in 50-60ms. Is there a solution for this? [Edited] GetDeviceCaps solved it.
Sorry, for my not accurate English.
---------------------------------------------------------------------------------------------
[Edited] Finally managed to make it work correctly.
The above C++ realization was unmanaged as managed means managed by garbage collector and classes in C++ are declared as ref class.
Now I have managed C++ class that calls WIN32 API functions and this C++ class is directly used by C#.
The answer to the 1st question is that it should be hMemDC as first parameter, because couldn't get it work with hDC in managed environment.
For the second answer: in managed environment average times now are (tested 100 times):
Windows ~23ms
Game Menu ~34ms
Game Action ~38ms (oh it lagged, I think this time is still optional)
Btw these times are for 1280x800x32, which means ~4MB, repeating all routines: getting, releasing, deleting objects and in-memory bitmaps.
The 3rd answer: somehow in managed environment it works as it should, but I don't understand how Color.FromArgb(int arg) takes BGRA quad and handles it, however it just works(Is C# Color BGRA also?).
Answer number 4th: it's still a problem, i have changes alpha values by hand.
The 5th: Here are numbers for accesses per ms:
Windows ~85k
Game ~54k-70k
So I think it's quite good result for managed environment.