View previous topic :: View next topic |
Author |
Message |
Baker

Joined: 14 Mar 2006 Posts: 1538
|
Posted: Fri Jul 16, 2010 4:56 am Post subject: MH's Direct3D 8.1 Wrapper |
|
|
Back in December 2009, MH released a Direct3D 8.1 that is easy to implement for most GLQuake engines (Example engines [6] site). Note: including an experimental EZQuake and my engine there are 8 working prototype engines using the wrapper.
[FitzQuake, Enhanced GLQuake, FuhQuake, ZQuake, Tomaz are the others.]
MH gave me and updated version of the wrapper lately from April and it is quite a bit faster.
I've been spending a bit of time lately sorting through things trying to isolate necessary and unnecessary changes in my own engine to optimize it and debug it.
Anyway, here is what is probably my final list of #ifdefs for the wrapper. I try to use detail that explains the exception ...
Code: | #ifdef DX8QUAKE
# define DX8QUAKE_NO_DIALOGS // No "starting Quake type "dialogs for DX8QUAKE
# define DX8QUAKE_NO_8BIT // D3D8 wrapper didn't keep the 8bit support
# define DX8QUAKE_GET_GL_MAX_SIZE // D3D8 wrapper obtains the maxsize from the video card
# define DX8QUAKE_CANNOT_DETECT_FULLSCREEN_BY_MODESTATE // Detecting modestate == MS_FULLDIB isn't useful
# define DX8QUAKE_NO_BINDTEXFUNC // SGIS/ancient GL pathway removal
# define DX8QUAKE_NO_GL_ZTRICK // DX8QUAKE hates gl_ztrick; clear the buffers every time
# define DX8QUAKE_GL_READPIXELS_NO_RGBA // Wrapper only supports GL_RGBA; not GL_RGBA like envmap command uses
#endif |
Most of the things like lack of "ztrick" support, the inability to do glReadPixels as GL_RGBA or compatibility with ancient obsoleted BindTexFunc or lack of 8 bit support or the "starting Quake" dialog wouldn't interest anyone anyway.
I have 2 or 3 bugs I'm battling not related to the Direct3D 8.1 wrapper but I am getting very high frames per second.
After ridding the 2 or 3 bugs that annoying me, the dx8 version of my engine is near enough in performance to GL as to be able to replace its usage and the reliability is top notch.
[Part of me is wondering what it'd be like to use the wrapper on a non-Quake engine that uses OpenGL 1.2 or thereabouts.] _________________ Tomorrow Never Dies. I feel this Tomorrow knocking on the door ... |
|
Back to top |
|
 |
Baker

Joined: 14 Mar 2006 Posts: 1538
|
Posted: Fri Jul 16, 2010 5:24 am Post subject: |
|
|
Btw ... how complicated is it to implement the wrapper in an OpenGL 1.2 type of engine (like not DarkPlaces).
Here are the changes in JoeQuake:
1. Put #ifdef/#endif as indicated around this code in sys_win.c to get rid of the "Starting Quake" type of dialog or in this case the popup JoeQuake logo ...
Code: | #ifdef USEFAKEGL
if (!(isDedicated = COM_CheckParm("-dedicated")))
{
hwnd_dialog = CreateDialog (hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, NULL);
if (hwnd_dialog)
{
if (GetWindowRect(hwnd_dialog, &rect))
{
if (rect.left > (rect.top * 2))
{
SetWindowPos (hwnd_dialog, 0,
(rect.left / 2) - ((rect.right - rect.left) / 2),
rect.top, 0, 0,
SWP_NOZORDER | SWP_NOSIZE);
}
}
ShowWindow (hwnd_dialog, SW_SHOWDEFAULT);
UpdateWindow (hwnd_dialog);
SetForegroundWindow (hwnd_dialog);
}
}#endif |
2. Very important ... in vid_wgl.c (gl_vidnt.c in some engines) ...
Do this ...
Code: | #ifdef USEFAKEGL
FakeSwapBuffers ();
#else
SwapBuffers (maindc);
#endif |
3. In quakedef.h near the very top like after #include <windows.h> add this ...
Code: | // we're using the fake gl wrapper
#define USEFAKEGL
// FAKEGL - switch include files
#ifndef USEFAKEGL
#include <gl/gl.h>
#include <GL/glu.h>
// switch your OpenGL libs to this so that you can more easily switch between configurations
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glu32.lib")
#else
#include "fakegl.h"
#endif |
Then add the wrapper (gl_fakegl.c) to the project. Then probably remove opengl32.lib and glu32.lib from references in the project as the immediately above code will add them if needed. _________________ Tomorrow Never Dies. I feel this Tomorrow knocking on the door ... |
|
Back to top |
|
 |
mh

Joined: 12 Jan 2008 Posts: 909
|
Posted: Fri Jul 16, 2010 9:25 am Post subject: |
|
|
Baker wrote: | Btw ... how complicated is it to implement the wrapper in an OpenGL 1.2 type of engine (like not DarkPlaces). | It depends on how the engine handles it's OpenGL initialization really. Something like Quake II won't work at all without heavy rewriting of the engine, as it does a LoadLibrary on opengl32.dll, then GetProcAddress on all entry points, including the 1.0 and 1.1 entry points.
In theory the wrapper could be compiled into an opengl32.dll which could then be dropped into your game directory. It should work in just about all cases then, although it would need to be viewed as being more like the old 3DFX mini GLs where only the needed subset of full OpenGL was implemented. _________________ DirectQ Engine - New release 1.8.666a, 9th August 2010
MHQuake Blog (General)
Direct3D 8 Quake Engines |
|
Back to top |
|
 |
Spike
Joined: 05 Nov 2004 Posts: 944 Location: UK
|
Posted: Fri Jul 16, 2010 9:48 am Post subject: |
|
|
SwapBuffers is not actually part of opengl32.dll
You'd need to replace more dlls than just the opengl-specific ones.
You can rewrite the program's import/export address tables at run time, of course... _________________ What's a signature? |
|
Back to top |
|
 |
mh

Joined: 12 Jan 2008 Posts: 909
|
Posted: Fri Jul 16, 2010 10:15 am Post subject: |
|
|
SwapBuffers actually calls into wglSwapBuffers if you're running an OpenGL context so it's cool. Likewise all of the other GDI functions end up calling wgl versions.
It's very interesting if you put a dummy DLL called opengl32.dll into your game directory, monitor GetProcAddress calls, and watch what happens behind the scenes. You can dump the exports table from MS's opengl32.dll, implement all of the required functions as stubs in your own DLL, then run it in a debugger with breakpoints set so that you can get a good idea of how everything links up together.
Incidentally, the only reason that the "Starting Quake..." dialog was removed was so that it would compile clean with VS 2008. It can still be used otherwise if you want.
This is a valid replacement winquake.rc that will also work with VS 2008:
Code: | #include "resource.h"
#include <windows.h>
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif
IDI_ICON2 ICON DISCARDABLE "quake.ico"
IDD_DIALOG1 DIALOGEX 0, 0, 62, 21
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP
EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
FONT 16, "Times New Roman", 0, 0, 0x1
BEGIN
CTEXT "Starting Quake...",IDC_STATIC,4,6,54,8
END |
_________________ DirectQ Engine - New release 1.8.666a, 9th August 2010
MHQuake Blog (General)
Direct3D 8 Quake Engines |
|
Back to top |
|
 |
mh

Joined: 12 Jan 2008 Posts: 909
|
Posted: Fri Jul 16, 2010 11:58 am Post subject: |
|
|
A note on performance and other characteristics of the wrapper
Direct3D is very sensitive to primitive batching. Previous versions of this wrapper (pre April 2010) didn't attempt to batch at all, and performance suffered as a result. In April 2010 I rewrote it to use batching everywhere, detecting state changes as they happen and beginning a new batch on every state change.
All batches use indexed primitives with 16-bit indexes and the triangle list primitive type, except for if the requested OpenGL primitive type is GL_TRIANGLES, in which case it will use an unindexed triangle list. Strips and fans don't exist in it at all.
In many cases this will get performance that comes close to (or occasionally exceeds) OpenGL (which seems to batch up polygons internally within the driver), but it's dependent on the data that it's fed. If it's given polygons that are not grouped by state (the worst offender is R_DrawSequentialPoly or anything similar to/derived from it) it won't be able to batch them, and we get performance drop off.
A further optimization would be to detect if hardware T&L is available and use a dynamic vertex buffer if so. This is the approach used by DirectQ, which batches very agressively, and is able to draw the entire first scene of start.bsp, including the status bar, in 24 draw calls. It may not be viable for use with the wrapper as feeding a dynamic vertex buffer with polygons that aren't grouped by state will slow things down further. Some reworking of the surface refresh (especially getting rid of R_DrawSequentialPoly - a thing of true evil - and grouping bmodel surfs by texture) would be definitely required before it would be worthwhile doing this. Alias models and everything else are probably OK to leave as they are, but GLQuake's default surface refresh (especially the multitexture path) is embarrassingly suboptimal, even for OpenGL.
The wrapper supports a subset of baseline OpenGL 1.1 (similar to the old 3DFX mini GL) with some extensions available. Multitexture is exported, but combine modes are not. This isn't because D3D can't do combine modes (it can, and it's API is considerably more sensible than OpenGL here) but rather because the OpenGL API introduced a heavy layer of complexity in implementing them which caused other things to break.
It doesn't attempt to do much in the way of parameter validation, assuming that your OpenGL code is at least reasonably correct to begin with. I'm not sure if this was a wise decision but it certainly helped to speed up the development process. It does mean that you should test and confirm correct operation using native OpenGL rather than relying on this, however. _________________ DirectQ Engine - New release 1.8.666a, 9th August 2010
MHQuake Blog (General)
Direct3D 8 Quake Engines |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2004 phpBB Group
|