I managed to get access to the video card rasterizer, hope it works on other cards too.
Next step is to implement a nanotimer interrupt and sync it with the monitor refresh rate and vertical blank so we can blit the backbuffer to the frontbuffer inside the vertical blank period. ( prevent tearing )
Made a small test proggy to see if it gets data back from the video rasterizer.
Simple test with (Sleep,20) as timer used here, thus no synchronization yet.
Have to learn more about GDI also.
Can you guys give me some feedback if the rasterizer gives data back to the screen?
Does the "Inside Vertical Blank" flip to 1 now and then and is the "ScanLine number" running?
Arrgh! Another one.
(https://i.imgur.com/oOPIyN8.png)
Do you UPX your exe's also?
No, didn't use a resource. :biggrin: but it's safe :t
Quote from: Siekmanski on April 16, 2018, 11:13:06 AM
No, didn't use a resource. :biggrin: but it's safe :t
This is what it shows for me
(https://i.imgur.com/BnGZzMK.png)
On a side note, I wonder if you built using the latest libs whether you'd bypass the virus flagging issue.
I used to build all my programs with VS2003 until a few years back. But people were reporting false positives. After I switched to a newer version of VS the warnings went away, even though I was using the same source code.
No, the Masm32 libs.
Did you see the "Inside Vertical Blank" flip to 1 now and then and is the "ScanLine number" running?
Yeah scanline number is incrementing rapidly.
Not catching any change with the vertical blank number. Maybe it's happening too quick to see?
Yes I think so, will see.
Hi Marinus,
Scan lines seem to run up to 9.??? (too fast to know)
Eventually, there is a flicker in the letters, and occasionally Inside Vert blank flips into 1, but very briefly and then returns to 0
Thanks guys.
Hello, here is what I have proved, all of them with TinyC:
- FloorWC01. Bucle con GetMessage and SetTimer(20)
- FloorWC01b. Bucle con PeekMessage and SetTimer(20)
- FloorWc01c. Bucle con PeekMessage and GetTickCount and boolProcessing.
- FloorWc01d. Bucle con PeekMessage and WINMM timer and boolProcessing.
I cannot see any difference between them regarding flickering :lol:, but the first one is much more light weight than the others, so I can not see any reason for using PeekMessage.
I guess that one can not achieve 100% of flickerless in any system. It depends on the demo presented and the the system load at every moment. Of course is mandatory that the sucesives frames join well, otherwise you will get flickering with no doubt.
I have thought on using parallel threads to have data prepared when required with the hope of reducing the elapsed times between free buffer and data filling that could produce flickering, but I do not want to keep on trying, I prefer the first version.
Hi Alfonso,
Sad to say, the demos won't run on my Win8.1 machine.
QuoteI guess that one can not achieve 100% of flickerless in any system. It depends on the demo presented and the the system load at every moment. Of course is mandatory that the sucesives frames join well, otherwise you will get flickering with no doubt.
I don't know exactly how the graphics pipeline works in GDI.
It seems to me that the painting procedures are stored in some kind of an event queue or something, controlled by BeginPaint and EndPaint. ( don't know enough of GDI yet, still have some reading todo. )
If I'm right and we own the window (like in DX9), you can paint immediatly using the window hdc and skip BeginPaint and EndPaint.
But, blitting to the window must be in sync with the monitors refresh rate, this is the thing to tackle, prevent tearing. ( preventing tearing, I think this is the task for BeginPaint and EndPaint )
Alfonso, you are using a timer routine, that does the blitting to the window every 20 milliseconds.
This is out of sync by 3.333 milliseconds with a 60 Hz monitor refresh rate what causes the stutters because now and then you'll skip frame updates.
Just to prove this for yourself, try 33 milliseconds in your timer and see if the stutters are less frequently or not.
Yes, you will skip every second frame but it is more in sync with the monitor at 30.303 Hz, this is of course only a test case.
My ideas to prevent stutters in GDI are these steps:
1. Start a 16.666666 millisecond ( if the monitor refresh rate is 60 Hz ) nanotimer interrupt thread.
2. Wait for the Vertical blank period to start. ( think I got that covered, still have to prove it behaves well )
3. Switch buffer pointers. ( I will use 2 backbuffers )
4. Send an event to the routines thread ( on another core if possible ) so you can start immediately with your routines again, hence the 2 backbuffers.
5. Blit the finished backbuffer to the window. ( we are inside the Vertical blank period, there will be no screen tearing if the blit finishes within the Vertical blank period. )
6. Adjust the nanotimer interrupt with 100 nano seconds slices up or down for the next interrupt. ( synchronize it with the Vertical blank. )
7. Clear the just blitted backbuffer if necessary.
8. Goto step 2.
If this all works out, GDI drawing will be as smooth as DirectX and OpenGL I hope.
Guys, I'm following this discussion.
And if any of you manages to get a nice gameloop routine to achieve this 60FPS please share with me. I made one but didn't seem to work as expected. I wouldn't mind getting one as a friendly help, so I can carry on.
If it works 100% correct, I will post the sources.
Quote from: Siekmanski on April 21, 2018, 02:47:39 PM
If it works 100% correct, I will post the sources.
Thank you my friend. By the way, mine was that one where I mixed integers in registers and FPU. We've been through that
Hi Marinus, that would be nice. I looked for information about the GDI vertical sync, but it seemed that there wasn't. If you have any way, please tell me :biggrin:.
I will check it out with masm code, will see.
@LordAdef
I will help you if I can, maybe it would be nice any example from you of what you need.
Quote from: caballero on April 21, 2018, 06:50:57 PM
Hi Marinus, that would be nice. I looked for information about the GDI vertical sync, but it seemed that there wasn't. If you have any way, please tell me :biggrin: .
I will check it out with masm code, will see.
@LordAdef
I will help you if I can, maybe it would be nice any example from you of what you need.
Hi Caballero, thank you! I will post what I have so far and will explain it too.
Sounds like quite a challenging task.
Do you detect the systems refresh rate first and take that into account?
Even 60hz screens aren't always created equal.
I have one that is true 60hz and another that is 59.95hz. Which I would imagine would throw the timings out and introduce flicker if you were hard coding for 60hz.
Changing the blitting rate maybe is not a bad idea. Here is a masm program to do so on the fly:
- key 1. Each 20 milliseconds
- key 2. Each 33 milliseconds
- key +/- Increase/decreases it
By the way, I tried to avoid using Begin/end paint and it didn't work though in principle our hdc = GetDC(hWnd)
Avoiding BeginPaint is generally not a good idea. If you must force a wm-paint, use a timer and InvalidateRect. Sorry for bad spelling, I am on a mobile.
Hi Guys,
I did some tests by polling the Vertical Blank signal from the video monitor.
It seems to be working 100% correct on my machine.
Before implementing the Timer-Interrupt routine and the rest, I need some important feedback from you guys. :t
Does it also run on XP?
Does it also run on Win10?
Also if it doesn't work, I like to know.
Please, let me know by posting it with these 3 values:
- average VerticalBlankPeriod ---> this one is really important for me.
- average MonitorFrequency
- PixelFormat ?? (Type)
- and the operating system it runs on.
I would really appreciate it, many thanks in advance. :biggrin:
( don't mind the flickering, it will be gone if the timer interrupt is implemented )
Marinus
(https://www.dropbox.com/s/izb1e3ca0twqvb2/Vdraw.jpg?raw=1)
win 10
Let me know if you need anything else!
7-32
I have your same OS i think (windows 8.1) So i don't know if you want the same testing again...? :idea:
Hi, Marinus, don't you take a rest? :biggrin:
W7 64 bits
Quote from: felipe on April 23, 2018, 06:10:06 AM
I have your same OS i think (windows 8.1) So i don't know if you want the same testing again...? :idea:
Yes please, you have another monitor than me I suppose.
Quote from: caballero on April 23, 2018, 06:17:16 AM
Hi, Marinus, don't you take a rest? :biggrin:
W7 64 bits
No, this is therapy for me.
I need to keep my brain in shape. :biggrin:
Quote from: Siekmanski on April 23, 2018, 06:53:36 AM
Quote from: caballero on April 23, 2018, 06:17:16 AM
Hi, Marinus, don't you take a rest? :biggrin:
W7 64 bits
No, this is therapy for me.
I need to keep my brain in shape. :biggrin:
Please don't rest, there is a legion of noobs following every step!
average VerticalBlankPeriod: This has varied from execution to excution, incresing the numbers always (until now). First was something like 0.4xxxxxxxxx Miliseconds. Then was like 0.6xxxxxxx and now is 0.7xxxxxxxx. Wait! now was 0.5xxxxxxxxxxx.
average MonitorFrequency: This has also varied, now is 59.973xxxxxxxhz (was too something like 53.xxxxxxhz)
PixelFormat ?? (Type):22 Firts frame, vertical blank 0.4xxxxxx ms. Frame delta 16.6xxxx ms.
The lines of the average measures are overlapped between some of them.
This was tested in a netbook with a small resolution: 1366x768, using windows 8.1
In this second computer with a resolution of 1280x1024 (and windows 8.1):
The format is fine now (no lines overlapping).
average VerticalBlankPeriod: 0.670040437 miliseconds.
average MonitorFrequency:60.018938442hz.
PixelFormat ?? (Type):22 Firts frame, vertical blank 0.667589508 ms, Frame delta 16.656695063 ms.
Btw, i like to see those numbers moving so fast. :bgrin:
Marinus,
I've got an old laptop running XP. If no one tested, I could get it running and I'll test it for yoh
Quote from: LordAdef on April 23, 2018, 08:57:25 AM
Marinus,
I've got an old laptop running XP. If no one tested, I could get it running and I'll test it for yoh
I would really appreciate it, many thanks in advance. :t
XP is not tested yet.
I'll do it, no problems!
(https://i.imgur.com/1Ho7ml4.png)
Windows 10 :t
Hi Marinus,
Quote from: Siekmanski on April 23, 2018, 09:09:19 AM
Quote from: LordAdef on April 23, 2018, 08:57:25 AM
Marinus,
I've got an old laptop running XP. If no one tested, I could get it running and I'll test it for yoh
I would really appreciate it, many thanks in advance. :t
XP is not tested yet.
My XP laptop said; "GDIVERTI.EXE has encountered a problem
and needs to close. We are sorry for the inconvenience." And goes
on like that for quite a bit.
Do I need to download a DLL or some such?
HTH,
Steve N.
Hi Steve,
Not that I'm aware of.
The test program continuously polls the Vertical blank signal using all the CPU resources of the thread it is running on. (this will be reduced to 1 poll per screen refresh rate in the final routine)
15 years ago I made an attempt using this same technique, back then there where video cards that didn't support that function too.
I'll see if I can check the capabilities of the video cards and report if it supports polling the Vertical blank signal.
Thanks for the report, almost forgot about this issue.
Quote from: Siekmanski on April 24, 2018, 01:08:53 AM
Hi Steve,
Not that I'm aware of.
The test program continuously polls the Vertical blank signal using all the CPU resources of the thread it is running on. (this will be reduced to 1 poll per screen refresh rate in the final routine)
15 years ago I made an attempt using this same technique, back then there where video cards that didn't support that function too.
I'll see if I can check the capabilities of the video cards and report if it supports polling the Vertical blank signal.
Thanks for the report, almost forgot about this issue.
is it possible to use two cores/two threads and use LOCK prefix to synchronize
or some other way to backbuffer ->screen copy so that it doesnt flicker?
one thread is drawing,second thread is checking Vblank and scanline
maybe start/stop workerthread when vblank/notvblank?
That's the plan, 1 backbuffer that blits to the front buffer while the drawing starts immediatly at the second backbuffer, using 2 threads each on another core.
http://masm32.com/board/index.php?topic=7075.msg76192#msg76192
Hi,
Ran the program on another notebook with WinXP to see if
changing the video chipset makes a difference. It did not, same
error occurred. ATI Mobility Radeon in the first, Intel in the second.
Regards,
Steve N.
QuoteIf I'm right and we own the window (like in DX9), you can paint immediatly using the window hdc and skip BeginPaint and EndPaint. But, blitting to the window must be in sync with the monitors refresh rate, this is the thing to tackle, prevent tearing. ( preventing tearing, I think this is the task for BeginPaint and EndPaint )
Marinus, you don't need BeginPaint/EndPaint. I was cleaning my code logic and spent some time researching this. Game develpers do paint outside ==Paint. It's in fact how I am doing right now. I set my window as OWNED, so we can freely paint to it.
Quote from: LordAdef on April 25, 2018, 04:05:01 AM
QuoteIf I'm right and we own the window (like in DX9), you can paint immediatly using the window hdc and skip BeginPaint and EndPaint. But, blitting to the window must be in sync with the monitors refresh rate, this is the thing to tackle, prevent tearing. ( preventing tearing, I think this is the task for BeginPaint and EndPaint )
Marinus, you don't need BeginPaint/EndPaint. I was cleaning my code logic and spent some time researching this. Game develpers do paint outside ==Paint. It's in fact how I am doing right now. I set my window as OWNED, so we can freely paint to it.
How interesting, an example, please
Quote from: caballero on April 25, 2018, 04:35:04 AM
Quote from: LordAdef on April 25, 2018, 04:05:01 AM
QuoteIf I'm right and we own the window (like in DX9), you can paint immediatly using the window hdc and skip BeginPaint and EndPaint. But, blitting to the window must be in sync with the monitors refresh rate, this is the thing to tackle, prevent tearing. ( preventing tearing, I think this is the task for BeginPaint and EndPaint )
Marinus, you don't need BeginPaint/EndPaint. I was cleaning my code logic and spent some time researching this. Game develpers do paint outside ==Paint. It's in fact how I am doing right now. I set my window as OWNED, so we can freely paint to it.
How interesting, an example, please
Sure! but in the mean time, have a look at the link I provided of Casey Moratori's C game (the thread of references I posted here at the gave forum). He is one example, ==PAINT is only used to refresh the gui. the whole game is rendered outside the win message. It's called from the game loop.
I am doing this way and I find the blt to be more steady
Are you in win10? My code is currently broken for win 7. If so, I could post it for you
W7 here, but you could post it here any way and we may have a look to it.
Own the window, wc.style, CS_HREDRAW or CS_VREDRAW or CS_OWNDC
Call your routines from the timer and the hdc from the owned window
Don't use WM_PAINT, BeginPaint and EndPaint
Don't use InvalidateRect
I have tested this and it works ( although still without a backbuffer )
Quote from: Siekmanski on April 25, 2018, 05:10:33 AM
Own the window, wc.style, CS_HREDRAW or CS_VREDRAW or CS_OWNDC
Call your routines from the timer and the hdc from the owned window
Don't use WM_PAINT, BeginPaint and EndPaint
Don't use InvalidateRect
I have tested this and it works ( although still without a backbuffer )
According to my research, they don't use the ==TIMER also. The coder controls everything from the outside. ==TIMER has a fluctuation. I was doing my animation with ==TIMER and ==PAINT. It's a lot more steady without the two Marinus.
Quote from: caballero on April 25, 2018, 04:58:00 AM
W7 here, but you could post it here any way and we may have a look to it.
no problems. Tonight.
But I'll chase the win7 bug and send the exe too.
Quote from: Siekmanski on April 25, 2018, 05:10:33 AM
Own the window, wc.style, CS_HREDRAW or CS_VREDRAW or CS_OWNDC
Call your routines from the timer and the hdc from the owned window
Don't use WM_PAINT, BeginPaint and EndPaint
Don't use InvalidateRect
I have tested this and it works ( although still without a backbuffer )
Marinus,
According to msdn, using OWNED you also don't need to release the DC.
How nice is that.
But this is logical, we own the DC.
Already spend hours reading MSDN to learn all about GDI and taking notes if I think it is useful. ( and all the different types of BitMaps :icon_eek: )
from my notes I made,
invoke GetDC,hWnd
mov hFrontBufferDC,eax ; Note that the handle to the DC can only be used by a single thread at any one time.
; see GetDCEx function for clipping control.
MSDN: private DCs do not have to be released
pros and cons of CS_OWNDC (http://blogs.msdn.com/b/oldnewthing/archive/2006/06/01/612970.aspx)
Quote from: Siekmanski on April 25, 2018, 05:10:33 AM
Own the window, wc.style, CS_HREDRAW or CS_VREDRAW or CS_OWNDC
Call your routines from the timer and the hdc from the owned window
Don't use WM_PAINT, BeginPaint and EndPaint
Don't use InvalidateRect
I have tested this and it works ( although still without a backbuffer )
Didn't work to me
/* ----------------------------------------------------------------------------
- Plantilla Programación Gráfica - SWGPTG - Tiny C -
----- -----
- AUTOR : Alfonso Víctor Caballero Hurtado -
----- -----
- VERSION : 1.0 -
----- -----
- (c) 2018. http://www.abreojosensamblador.net -
- Small Windows Graphics Programming Tutorial with GDI -
---------------------------------------------------------------------------- */
#define cdXPos CW_USEDEFAULT
#define cdYPos CW_USEDEFAULT
#define cdYSize 400
#define cdXSize 640 //cdYSize*1.6
#define cdColFondo 0
#define MAIN_ICON 100 // IDI_APPLICATION
#define cdVCursor IDC_ARROW
#define cdVBarTipo 0
#define cdVBtnTipo WS_OVERLAPPEDWINDOW
#define cdIdTimer 1
#define DIB_RGB_COLORS 0
#include <windows.h>
// Prototipos de funciones
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
// Variables globales
int *pMainDIB = NULL;
int vdxClient, vdyClient, motion = 0;
BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER),cdXSize,-cdYSize,1,32,0,0,0,0,0,0};
void PintaObjeto (void) {
int x, y, k, a;
for (y = 0; y < cdYSize; y++)
for (x = 0; x < cdXSize; x++, k++) {
a = ((x-motion)^(y+motion))&255;
*(pMainDIB + k) = 0x400000 | (a<<8) | a;
}
motion++;
}
void Inicio (void) {
}
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HDC bufDIBDC;
static HBITMAP hMainDIB;
static HDC hMainDC ;
PAINTSTRUCT ps ;
static HGDIOBJ hOldDIB=0, hGDITmp;
int bResult;
switch (message)
{
case WM_CHAR :
if (wParam == VK_ESCAPE) {
goto wmDestruimos;
}
return 0 ;
case WM_CREATE:
hMainDC = GetDC(hWnd);
// Crea un búfer dib para PintaObjeto. pMainDIB es un puntero a él
bufDIBDC = CreateCompatibleDC (hMainDC);
hMainDIB = CreateDIBSection(hMainDC, (BITMAPINFO *) &bi, DIB_RGB_COLORS, (void **) &pMainDIB, NULL, 0);
hOldDIB = SelectObject (bufDIBDC, hMainDIB);
//ReleaseDC (hWnd, hMainDC); // Libera device context
Inicio ();
SetTimer (hWnd, cdIdTimer, 20, NULL) ;
return 0 ;
case WM_TIMER :
//InvalidateRect (hWnd, NULL, FALSE) ;
PintaObjeto ();
//bResult = StretchBlt (GetDC(hWnd), 0, 0, vdxClient, vdyClient, bufDIBDC, 0, 0, cdXSize, cdYSize, SRCCOPY);
bResult = StretchBlt (hMainDC, 0, 0, vdxClient, vdyClient, bufDIBDC, 0, 0, cdXSize, cdYSize, SRCCOPY);
return 0 ;
case WM_SIZE :
vdxClient = lParam & 0xFFFF;
vdyClient = lParam >> 0x10;
return 0 ;
/*case WM_PAINT :
hMainDC = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
return 0 ; */
case WM_DESTROY :
wmDestruimos:
KillTimer (hWnd, cdIdTimer) ;
hGDITmp = SelectObject (bufDIBDC, hOldDIB);
bResult = DeleteDC (bufDIBDC);
bResult = DeleteObject (hMainDIB);
bResult = DestroyWindow (hWnd);
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hWnd, message, wParam, lParam) ;
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
RECT WRect;
static TCHAR szAppName[] = TEXT ("SWGPTG") ;
HWND hWnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hbrBackground = cdColFondo ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hInstance = GetModuleHandle (NULL) ;
wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(MAIN_ICON)) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
TEXT ("Error"), MB_ICONERROR) ;
return 0 ;
}
SetRect (&WRect, 0, 0, cdXSize, cdYSize);
AdjustWindowRectEx (&WRect, cdVBtnTipo, 0, cdVBarTipo);
WRect.bottom += GetSystemMetrics (SM_CYCAPTION) + 1;
WRect.bottom += GetSystemMetrics (SM_CYFIXEDFRAME)*2 + 1;
WRect.right += (GetSystemMetrics(SM_CXFIXEDFRAME) + 1) * 2;
WRect.left = (GetSystemMetrics (SM_CXSCREEN) - WRect.right)/2;
WRect.top = (GetSystemMetrics (SM_CYSCREEN) - WRect.bottom) / 3;
hWnd = CreateWindow (szAppName, TEXT ("Plantilla SWGPTG - (c) abreojosensamblador.net"),
cdVBtnTipo,//WS_OVERLAPPEDWINDOW,
WRect.left,WRect.top,WRect.right,WRect.bottom,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hWnd, iCmdShow) ;
UpdateWindow (hWnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
It works for me, no WM_PAINT BeginPaint and EndPaint in my source.
Although only tested with DrawText directly to the Window.
Got the interrupt timer implemented and synchronized it with the VerticalBlank.
It stays nicely within the VerticalBlank period at 60 Hz. :eusa_dance:
Is FillRect the fastest way to clear a buffer?
Or are there different ways to clear buffers in SytemMem and VideoMem.
Next step is the double buffering and drawing some graphics.
Study the DIB and DDB first, there are so many possibilities in GDI. :dazzled:
Hope it works....
EDIT: When done drawing I validate the window with " invoke ValidateRect,hWnd,NULL "
MSDN: Handle to the window whose update region is to be modified. If this parameter is NULL, the system invalidates and redraws all windows.
Made some adjustments to the interrupt timer routine.
It now checks if the vertical blank signal is found.
If it is not supported by the video card it tries to sets the most accurate stable timer value possible.
Probably a bit faster than the monitor refresh rate.
Hope it works now for FORTRANS too on Windows XP.
Alex could you test it on XP too?
I'm very satisfied with the result and hope it runs stable on other machines too.
Feedback would be nice, thanks in advance. :t
Seems to be all ok here in my machine (the desktop one). :t
Quote from: Siekmanski on April 26, 2018, 10:48:23 PMFeedback would be nice, thanks in advance. :t
Win7-64: 59.838, 0.0166, pretty stable
On my XP VM, it chokes with "a problem" at offset 163b :(
Hi,
Tried it and got the same error pop-up offering to send an error
report to Microsoft. Should I try and copy some of the information
out of a window?
Regards,
Steve N.
I've got all error handling active.
I think maybe an old video card issue or XP doesn't support it?
QuoteShould I try and copy some of the information
out of a window?
That would be nice, with that info I can track down the error, I hope. :icon14:
BTW I've got the backbuffer running and blitting to the frontbuffer, no flickering anymore.
Up to some graphics drawing. :biggrin:
Hi,
Well, here are some screen shots of the pop-up. And a file
that was to be sent. They don't make it easy to copy stuff.
HTH,
Steve N.
Quote from: jj2007 on April 27, 2018, 12:38:00 AMOn my XP VM, it chokes with "a problem" at offset 163b :(
00401627 ³. C3 retn
00401628 ³> 0BDB or ebx, ebx
0040162A ³. 74 06 jz short 00401632
0040162C ³. 53 push ebx ; ÚhModule
0040162D ³. E8 ECF9FFFF call <jmp.&kernel32.FreeLibrary> ; ÀKERNEL32.FreeLibrary
00401632 ³> 0BFF or edi, edi
00401634 ³. 74 0D jz short 00401643
00401636 ³. 8BC7 mov eax, edi
00401638 ³. 50 push eax
00401639 ³. 8B00 mov eax, [eax]
0040163B ³. FF50 08 call near [eax+8] ; ####### This is offset 163b #######
0040163E ³. BF 00000000 mov edi, 0
Thanks Steve.
Jochen ,I see, it's the realease of an interface. I'll have a look tomorrow.
Thanks guys.
Seems to work ok here the "VerticalBlank Signal" bleeps often, but the second line only from time to time.
When exit I get an error.
Hi Alfonso,
That's because there's no backbuffer.
With the backbuffer it's without flickering. Have done this already.
What error do you have when you exit the application?
No message, just the next window
Jochen found the bug, I hope..
I had a quick look, spotted a coding error.
New attempt.
Quote from: Siekmanski on April 27, 2018, 04:17:55 AMJochen ,I see, it's the realease of an interface.
Yes, shortly after a FreeLibrary - that was easy. Note that on Win7-64 the old and new versions run fine but choke on exit, somewhere in the wild.
Jochen,
Same as Alfonso, think it is now fixed. ( see previous post )
EDIT: forgot the attachment.
Exactly the same error for version 2 and 3
Last attempt.
Else I have a better look tomorrow.
Sorry, the same. Have a breath :biggrin: you are almost capable of producing more than I can prove :biggrin:
:biggrin:
Engine4 runs fine but crashes on exit (Win7-64). When run with Olly, it exits OK with code 12h.
Rewrote some stuff in the interface handling.
No errors on my system.
Sometimes you think when it runs well on your own system it does also on other systems.
Turns out this isn't always the case. :bgrin:
Hope it runs now on XP and Win7 and closes without errors.
Are there Vista users on the forum who want to test this proggy?
It closes without problems :t
Thanks Jochen. :biggrin:
Simple scroll example ( 1 buffer )
It scrolls smooth on my sytem even with 1 buffer. :eusa_dance:
Little jumps about once per second but otherwise fine :t
Hi,
Tested engine5, and it works on Win XP. No retrace signal,
test value 480. (Yesterday, engine3 failed, by that time you had
put out engine4.)
Regards,
Steve N.
Congrats. Now it closes fine (v6). Nevertheless I'd say that I can observe some stumbles in the scrolling.
Thanks guys for testing and the reports. :t
Here a demo with Caballeros scrolling floor routine.
I could not apply the jitter correction factor on this routine because this routine takes integer steps for drawing the floor.
So, some stutters can be there.
One thing I noticed!
When running another GDI program that does blitting or drawing to the screen, my program starts to stutter else it is very smooth.
This stuttering doesn't take place when running at the same time with a DirectX program only with another GDI program.
I think because my program does not use BeginPaint and EndPaint, the screen BitBlt gets invoked by the GDI pipeline when other programs also using the GDI pipeline????
tested on a extreme monitor,where I could test up to 200 mhz,234.370 fps
it ran smooth and very fast,but I guess that maybe not good for a fast game become 3 times faster
Then I have to implement a presentation interval, will be done. :t
Quote from: Siekmanski on April 28, 2018, 04:19:11 AM
Then I have to implement a presentation interval, will be done. :t
I dont think its necessary as it can run on 60hz and many faster hz,I just remembered it was capable of upto 200hz, so I tested it
it shows your code is good enough to work even with so fast hardware :t
Cool. 8)
Presentation intervals can help for heavy games, to let it run at a steady 30 FPS for example.
I wonder if it would make sense to have a thread waiting for the vertical interrupt, and then just did an InvalidateRect.
That was my first thought also, but GDI does not draw at a certain interval and it uses a sort of an event queue. I like to do the drawing whenever I want and at an even interval so the workload is evenly divided.
InvalidateRect, no need to use it, we own the window.
Direct3d9 offers all of this, I was curious if it would be possible with GDI.
And with using a timer thread we have the possibility to execute our routines while the thread takes care of the buffer switch, clearing the background and other things simultaneous
I'm not going to abandon Direct3d9 it's much cooler and faster than GDI.
Hello.
- FloorWM01. Demo with GetMessage, so very little system resources needed.
- FloorWM02. Same demo with PeekMessage, FPS stabilizer and no WM_PAINT using. Much more system resources needed.
I wonder if PeekMessage worths the pity. Any one see any difference? Thank you
FloorWM01.exe GetMessage 0 %
FloorWM02.exe PeekMessage 7-8 %
My proggy with your Floor Routine uses 0.5 % with PeekMessage + vertical blank.
This is my Message Pump:
.while msg.message != WM_QUIT
invoke PeekMessage,addr msg,NULL,0,0, PM_REMOVE
.if (eax)
invoke TranslateMessage,addr msg
invoke DispatchMessage,addr msg
.endif
invoke RenderGDI ; do the rendering stuff
.endw
GetMessage 0, PeekMessage 20% (and both flicker a little bit)
Quote from: Siekmanski on April 29, 2018, 01:29:01 AM
This is my Message Pump:
.while msg.message != WM_QUIT
invoke PeekMessage,addr msg,NULL,0,0, PM_REMOVE
.if (eax)
invoke TranslateMessage,addr msg
invoke DispatchMessage,addr msg
.endif
invoke RenderGDI ; do the rendering stuff
.endw
I checked this out, but I've got an error on exit, so I have to use this one:
.WHILE TRUE
MessageLoop:
invoke PeekMessage, ADDR msg, 0, 0, 0, PM_NOREMOVE
.if eax != 0
invoke GetMessage, ADDR msg, 0, 0, 0
or eax, eax
jz L_Fin
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp MessageLoop
.endif
[... My tasks here... ]
.ENDW
Your program uses much less system resources but at least in my system also with flickering
QuoteYour program uses much less system resources but at least in my system also with flickering.
I couldn't run it with the jitter correction factor because how your motion value is imbedded in the routine itself.
When I run mine together with other GDI programs on the background it stutters.
But when I run it without other running GDI programs it is smooth.
Timing in Windows Sucks. :icon13:
> When I run mine together with other GDI programs on the background it stutters.
> But when I run it without other running GDI programs it is smooth.
ah, it's possible :t. Not everything was going to be simple...
This is a nice challenge, but if we will succeed?.... ::)
Well, the important thing about the road is not to cross it, but to enjoy the landscape. When we get tired we can always take another path, but we will surely have learned something :t
Excuse my ignorance: How do you synchronise with the VBI? I see you are not using the D3DKMTWaitForVerticalBlankEvent function (see johnsa's Vertical Retrace Sync with GDI/Win32 (http://masm32.com/board/index.php?topic=4410.msg47080#msg47080) post).
In what I have seen, "D3DKMT_WAITFORVERTICALBLANKEVENT" sounds to directx
Wouldn't it be better to stress test gdi with a scrolling background +lots of moving enemies ala # of enemies like space invaders,each having its bitblt?
Now I got curious how lord adef solves it,with how many bitblt /frame do he needs in his game?what fps do you achieve?
Quote from: jj2007 on April 29, 2018, 03:52:22 AM
Excuse my ignorance: How do you synchronise with the VBI? I see you are not using the D3DKMTWaitForVerticalBlankEvent function (see johnsa's Vertical Retrace Sync with GDI/Win32 (http://masm32.com/board/index.php?topic=4410.msg47080#msg47080) post).
D3DKMTWaitForVerticalBlankEvent has some side effect as you can read in johnsa's Vertical Retrace Sync with GDI/Win32 thread.
Alfonso,
D3DKMTWaitForVerticalBlankEvent you can find in the gdi32.dll ( it's not available in the masm32 gdi32.lib )
I'm setting up a fake video device ( tricky but it works ) to get to the interface that gives me access to the Video/Monitor rasterizer.
First I get the monitor refresh rate from GetDeviceCaps then create a timer thread with the SystemClock interface and set up a one-shot advise request for the reference time at slightly less then the monitor refresh rate.
Then I continuously poll the signal till it enters the Vertical blank, and start the one-shot advise timer again.
From now on I'm sure I don't poll more then necessary and we don't drift away out of the vertical blank period. ( it's only +/- 0.5 milliseconds long )
On my machine it has +/- 10 microseconds accuracy and not too much cpu workload.
The only thing ( I think, not 100% sure) is not to wake up the GDI event queue when we dont want it to take over the drawing management from us.
And another thing, not every video card behaves the same as other cards......
I miss the old Amiga days, perfect 50 Hz on all machines, no stutter at all. :eusa_boohoo:
Quote from: Siekmanski on April 29, 2018, 07:44:07 AMD3DKMTWaitForVerticalBlankEvent you can find in the gdi32.dll ( it's not available in the masm32 gdi32.lib )
If you can't find it there, check d3d10core.dll
Just an jotting on this subject, an interesting msdn article (https://msdn.microsoft.com/en-us/library/windows/desktop/ff729480) comparing GDI and D2D. I haven't read it in its entirity (... well, just a few... :biggrin:)
An interesting paragraph:
Quote
Direct2D and GDI are both 2D immediate-mode rendering APIs and are hardware accelerated
Quote
Rendering method
In order to maintain compatibility, GDI performs a large part of its rendering to aperture memory using the CPU. In contrast, Direct2D translates its APIs calls into Direct3D primitives and drawing operations. The result is then rendered on the GPU. Some of GDI's rendering is performed on the GPU when the aperture memory is copied to the video memory surface representing the GDI window.
Quote
Availability of Hardware Acceleration
GDI is hardware accelerated on Windows XP, and accelerated on Windows 7 when the Desktop Window Manager is running and a WDDM 1.1 driver is in use. Direct2D is hardware accelerated on almost any WDDM driver and whether or not DWM is in use. On Vista, GDI will always render on the CPU.
After reading this article, it makes clear GDI acceleration is different per operating system.
And what about different handling in the blit functions between Sytem and Video memory......
Aplha Blending and Transparency same story.
A bit of a bummer, because you can create many effects with it.
Maybe we can do the alpha stuff preparing in software, have to check this first. ( new challenge :biggrin:)
As long as the blit operations are accelerated we can still create nice games with it.
So prepare for testing code to check different operating systems.
As an experiment I'll write a jpg/png/bmp image loader for GDI which can handle and prepare alpha channels.
Just curious how it acts with the GDI blit operations without using the GDI Alpha Blending and Transparency functions.
Do you guys have experience with alpha blending in GDI?
Except anyone demonstrate me how to use alpha blending in GDI I think there is no such capability in GDI, except that you can do it by yourself, sure, that's the beauty of GDI :lol:. In fact, in GDI, alpha color has to be = 0, otherwise you will get error.
Attached a tinyc example.
1. First you have to rename it from "zip" to "7z", its real extension
2. unzip its contents to a folder, executable and bmp image
Quote from: Siekmanski on April 29, 2018, 08:27:43 PM
Do you guys have experience with alpha blending in GDI?
does GDI support .dds file format or maybe write one and make use of dx9 sdk texture tool, that can import different file formats and you can choose one image file as alpha channel, and export as ARGB 32bit .dds format
it worked with d3d9 texture,but havent tested with GDI
Hi Alfonso,
I see just with BitBlt, exactly what I hoped for, Direct3D9 handles the colors the same way.
Piece of a cake, we don't need the later GDI alpha functions. :t
Hi Magnus,
We are going to do that ourselfs with pixel manipulation.
Implemented 2 switching backbuffers in video memory. ( leaves us with more processing time for the routines )
Blitting to the window and clearing the backbuffers are done simultaneously in the background by the timer thread.
Implemented movement control in fragments of pixels.
In the attachment are 2 examples.
One of them closes all open windows at startup and opens them again when done.
See if the stutter control is improved or not.....
Think this is the closest we can get for stutter free GDI.
Please let me know if the stutters are reduced or gone. :t
Hi Marinus,
Both are still stuttering here for me. Have you tried without the stretch blt?
Hi Alex,
Yes, I used all blit methods, they all execute within the vertical blank.
If the operating system has no heavy tasks to run it scrolls very smooth without stutters.
But when it starts up doing something the stutters begin.
The timer thread runs in realtime priority and stays steady.
It must have something to do with how GDI renders/blits stuff in the background, priorities queueing, I don't know. :(
I'm out of ideas to get it better.
On my machine it runs 90% of the time smooth but now and then periods of those nasty stutters appear.
Sometimes it runs smooth without stutters for 30 minutes. ::)
I tried the 8 version and i like it :icon14: :greenclp:. I can't see anything bad on it. I actually don't know what do you mean by stutters. :idea:
Are stutters some rapid movements (but small movements)? That happen very little. Btw, are this figures fractals?
Thanks Felipe,
Quote from: felipe on May 04, 2018, 06:56:00 AM
Are stutters some rapid movements (but small movements)? That happen very little. Btw, are this figures fractals?
Yes, those are stutters, GDI waits sometimes for the next frame to do the blitting and then it produces stutters.
The nice fractal like stuff, is the routine from Caballeros Floor demo
It is a repeating color routine, perfect to spot stutters because it scrolls as a flat plane at equal speed.
Hi Siekmanski!
In my count last engines are 10 and 11!
From 7 (first with floor) very little difference in win7-32. Randon stutters that you note if are searching for.
I'd say that both runs smoothly nearly all the time, but from time to time I can perceive some flickering. I'd say that v8 goes better than v7 though. :t
Thanks guys,
It's not exactly the result I hoped for but it was a nice challenge.
If I only knew how to manipulate the GDI queueing management to get it to draw instantaneously, it could be really smooth....
Maybe some of you guys know about this.
GDI is not my preference for Games or Demo coding, Direct3D9 is!
Quote from: Siekmanski on May 04, 2018, 10:32:53 PMIf I only knew how to manipulate the GDI queueing management to get it to draw instantaneously
Would be interesting to see how much time it takes between an InvalidateRect (sent e.g. by a separate thread immediately after the VBI) and the arrival of the WM_PAINT message.
I've tried that, and it is also queued, not preventing the stutters.
Also send InvalidateRect at exactly 60Hz to let WM_PAINT handle things with and without the BeginPaint and EndPaint functions. No success.
There's a message named wm_erasebkgnd. It's used to erase the background, but i really don't know if this can help. :idea:
no need to use it because you previously has defined wndclass.hbrBackground = 0
It runs smooth on my XP and win8,but few months before I ran lots of compability tests on old ddraw, but also some other GDI code and very little worked on win8, so I dont see a future in GDI coding,when it comes with wrestle win10 and next OS's to get it work
the only future I see for 2d .is load vram full of images and let hardware accelerated dx with all the whistles and bells( read all antialias etc filters and pixelshaders you want to use or not)
Still many people use GDI for there Games or Demos.
They like it because you can create old school 2D stuff without using OpenGL or DirectX.
I can understand that, because it is fun to write your own pixel manipulation effects as in the old days.
The only thing, there is no GDI function to wait for the vertical blank that really works.
DirectDraw has the WaitForVerticalBlank function but doesn't work on Win10 out of the box.
With Vista, microsoft implemented the D3DKMTWaitForVerticalBlankEvent function.
I wanted a function that worked at least on Win XP, Win 10 and all the operating systems in between.
The only challenge left is, can we take over control of the GDI drawing qeueuing meganism?
IMHO, the best way to create really smooth, stutter free old school 2D stuff is, setting up Direct3D9 in 2D modus.
You can use an empty 2D Texture ( with a pointer to the pixel data ) to do your pixel manipulation just as in GDI.
As Magnus mentions in the previous post, you have access to all the functions of the video card to do all kind of amazing effects, you don't have in GDI.