DirectX 9 Driver (*Updated*)BlitzMax Forums/BlitzMax Programming/DirectX 9 Driver (*Updated*)
| New version Uploaded.|
This version address two things.
1. Centering of Window Mode displays like the Dx7/Open GL Drivers like 1.32 Max drivers
2. Render Buffering(Input Lag)
I have included a demo application provided by GFK(thanks and hope you don't mind my including for others to test) that demonstrated the problem. I have chosen a method that should minimize performance impacts. The method as a result of a massive Google hunt and came down to what was recommend by both ATI and NVidia to address the issue.
The mechanims uses a Direct3D Device Query and I think(*hope*) should work on all hardware. If not there is some additonal code in there that uses the DX7 driver method and if need be we can determine when to enable that code(big performance hit, but if its all the hardware can do...)
This will slow down max FPS(6/7%) as we are preventing render buffering,, which is really a GPU/CPU concurrency issue, not so much buffering which is why it is so difficult to track down.
I have implemented a driver option that allows disabling of the functionality all together.(See the readme or samples, if it really is big issue)
At this time there are 2 items I think outstanding that I would like to address before callng this a 1.0 although as of right now I think on modern hardware this is pretty much as good as it can get.
1. MIPMAPPING - currently i utilize hardware mipmap generation, I suspect there are still some crappy cards out there that dont support this. I am just lazy to write the code to generate MIPMAPs
2. VYSYNC - tearing here too I think there are issues with older hardware. I am also not to happy with the current implemention. The issue here really is change on part of direct X around Direct X 8 in that VSYNC is not option of present(BMAX Flip) but option on creation of the device.(BMAX Graphics) To make this BlitzMax like I emlulate VSYNC on the BMAX Flip command.
Frankly I dont think this works well. I think on final release, I am going to make it option on the driver and ignore the Flip Flag. What this means is you would set VSYNC on or off before calling the GRAPHICS command.
All feedback is appreciated.
did you fix the issue with using the dx9 driver causes your app to want to create a socket connection to some mystery address?
did you fix the issue with using the dx9 driver causes your app to want to create a socket connection to some mystery address?That is likely DX itself and has little to do with the driver. There are likely tips somewhere in a thread on how to disable DX phoning home on your system.
| @GW |
GaryV is correct this has nothing to due with my driver. Feel free to examine the source.
| GW, type dxdiag from the command prompt and untick the Check for WHQL digital signatures on first page. |
I have included a demo application provided by GFK(thanks and hope you don't mind my including for others to test) that demonstrated the problem.No probs.
Just tried the new version on my cruddy old test system - no lag whatsoever now. :)
| nice one |
| The issues I have with this D3D9 driver are following. Note that none of these problems exist with the default OpenGL or D3D7 driver:|
1) It doesn't seem to lock to VSYNC properly. On my 60hz LCD, carefully timed (60fps vsync'd) sequences using D3D7 and OGL work as expected, but run too fast under D3D9. For me to use D3D9, vsync needs to work like the default BMAX vsync.
2) I get a visible seam between two "seamless" textures used on a backdrop. Sorry, I can't post a screenshot.
3) On my custom GUI I use black lines, drawn with gradating ALPHA values, to give the appearance of drop shadows on menus and windows. These lines appear solid black under D3D9, not semi-transparent like they are under D3D7/OGL. It's like SetAlpha doesn't work with DrawLine or DrawRect.
I appreciate the feedback. A CAPs dump of you video card would be helpful.
1) As for the VYSNC, if you read my comments above i intend to change the functionality of it as the technique I use is not reliable across cards known issue on my part. I would be interested to know are you setting up a time rate on the Graphics Command or just using Flip True/False and cards refresh rate. I suspect I cant read the Raster Scan line. Probably unsupported on the card.
2)I have not seen this, but I am assuming you are tiling a Image? Is the image scaled? Might be my concern about mipmapping. If your card cant do hardware mipmapping this might be doing it.
3) Can you give me a snippet on how you gradating the lines. Are you drawing lines in a loop and dropping the alpha intensity. Not sure here, my testing of Alpha blending seem to work. Any other blend modes active.
In any case sorry you can produce sample code as when people produce samples I can address the issues faster.
If I can get your card caps that would be appreciated.
| @Tachyon alphablend bug confirmed. Thanks|
I cant duplicate the tile issue with a seamless texture using TileImage.
Are you tiling the image yourself with DrawImage?
Fix for Alpha problem.
Method SetAlpha( alpha:Float )
_Drawcolor=(Int(255*alpha) Shl 24)|(_Drawcolor&$ffffff)
Method SetAlpha( alpha:Float )
_Drawcolor=(Int(255*alpha) Shl 24)|(_Drawcolor&$ffffff)
' Set drawing verts colors
That was a booboo in 0.6 when I switched the way rendering worked.
Still trying to duplicate the seamless texture issue.
My card is a GeForce GTX 280 (top-of-the-line card just 6 months ago). I always use the latest certified driver from nVidia. I'm sure you can find CAPs info online.
Regarding the seam, after playing with the tile image, it does appear to have something to do with the alpha transparency of the .png file I use. I have made some adjustments to the image and the seam went away. However, it should still be noted that the visible seam was not there under D3D7/OGL.
But based upon the generation it I do know it supports the CAPS i use. What OS are you using and are you seeing the sync issue in Fullscreen or windows mode. If in windows mode do you have any themes ?
As for the image interesting.. So you had alpha channel and were tiling an alpha blended image or solid blend?
As for the seam I believe you. But you have to understand how difficult it is to find a rendering glitch if I cant duplicate the issue.
What are you using to make your PNG. There might be issue in the texture loading although it pretty much uses the same pixmap code that Dx7/OGL uses. Hmmm
| Thanks for the module!|
Can MaxGUI apps under XP or vista benefit from using this driver as well?
| @Grisu yest you can use the Driver wit MaxGUI. There is a simple dumb example in the samples that shows two canvases in use.|
I am working up the next update: which fixes the AlpahBlending bug, i posted fix for above as well as a reworked VSYNC mechanism that seems to be working pretty good.
The driver somehow "zoomes" the images displayed in a canavas.
See example image here.
Any idea why might cause this?
Apart from that the driver seems faster than the Dx7 one.. :o)
| @Grisu, That looks like a bug on my part just not sure exactly what.|
Is that dialog just a simple image in the picture? Or collection of images? Using simple DrawImage.
I see two canvas, are they both Graphics Canvas? I defiantly see the right size image messed up but it looks like the left side is butchered up pretty bad.
If you have any sample mock up that duplicates it, I should be able to quickly find and isolate the issue. I suspect I am not handling something correctly when the canvases are sized.
I will see if I can make a more complex demo MAXGUI and track it down. I will try to mock up what i see in your picture.
*EDIT* I think I can duplicate it. I have modified my example and definitely is not behaving the same way as DX7. I should be able to figure it out.
Thanks for feedback
Ok, I found it my test program pretty much sucked. Both my canvases where the same size so I could not see the problem. I missed the fact that each canvas had to reset the viewport and matrix with the SetGraphics calls so everything would skew all wonky depending on which view port was created first.
Will be fixed in next released. I need to move some code around in the Max2d driver and clean it up.
Thanks for the picture and report!
| You're welcome. |
Ouch, you were faster than me posting some example code... ;(
Will retest the module when you're done.
| Just found a bug, that's really a show stopper:|
Same image, same code, the top one on dx9, the low one on dx7/opengl.
If I rescale things up or down (with setscale), images that didn't show this borders sometimes show it down or to the right, or as in this picture, on both sides (never on top-left) - the sample above shows this error when on 640x480 resolution, but on 800x600 it appears normally. On 1024x768 the problem appear once again.
The image above is 200 x 44. Enlarging it to 256 x 64 makes no difference at all.
Very strange problem...
Edit: Just noticed, seems to be something related to image filtering. Loading images with flag 0 (Loadimage "name",0) seems to fix the border problem, but images don't rescale very well...
| Don't know if this is a "correct" fix, but solved the problem here:|
on TD3D9Max2DDriver, the DrawFrame method, just after:
Method DrawFrame( frame:TDX9ImageFrame,x0#,y0#,x1#,y1#,tx#,ty#)
Local deviceTexture : TDx9DeviceTexture=frame._Dx9DeviceTexture
Local p: Float Ptr= Varptr(deviceTexture._Vertices)
Local d: Int Ptr = Int Ptr (p)
And now I don't get black borders anymore!
I don't know why this fixes it, but it does... :)
| Hey Slotman,|
If I read it right you are scaling the image down or up?
Whats your video card again? Are you using MIPMAPPEDIMAGE flag when you load the image?
I think you are seeing the one part in the read me that I commented about not implementing yet, if the hardware does not support mipmapping, or there is minor difference in hardware mipmap generation vs software rendered.
Ill try to make an image up and see if I can duplicate and get off my lazy butt and fix mipmapping.
| Scaling both up and down. Let me clarify: I'm re-scaling my whole game according to user desktop resolution. It works fine on dx7-ogl, but on dx9 I was seeing those artifacts on some resolutions - mainly on 640x480 and 1024x768, which is both scaled down and above from "normal" (1:1) 800x600 resolution.|
And no, I´m not using the MIPMAPPEDIMAGE. But using it (or MASKEDIMAGE, FILTEREDIMAGE, etc) doesn't solve it at all.
The only thing I got to remove the lines was to disable the image filtering (D3DTEXF_LINEAR -> D3DTEXF_POINT) but then scaling images gets pretty bad; or the strange hack I posted above, which does work.
I'm on a ATI Radeon X1300.
If it helps, here's my CAPS:
(removed so it won't kludge the thread)
I think I might now whats going on since textures are loaded to power of 2. There is a step that is done in the Dx7 driver I dont do, regarding smearing the edges of the textures. Did not quite understand what that was doing.
The issues with your hack is fixing the issue as you are adjusting the coordinates by a partial pixel. This has do do with how pixels are mapped to textual and alogorim is used.
Any chance you could post simple example on how you are calculating this scaling factor? It would make it significantly easier for me to track down.
| Well nope, its not what I thought.|
I am stumped I cant seem to duplicate the problem. Well I can if I intentionally start butchering the texels/mapping.
Are your images PNG by chance? Can you post a link/email me the image you are using that demonstrates the problem?
I think I might have found it...
Replace these methods in the object TDx9DeviceTexture in
dxlog "Texture created"+Self.ToString()
Local hr:Int= _Driver._DXDriver.Direct3DDevice9().CreateTexture(_TextureWidth,_TextureHeight,level,usage,_TextureFormat,D3DPOOL_MANAGED,_Texture,Null)
' Local hr:Int= _Driver._DXDriver.Direct3DDevice9().CreateTexture(_TextureWidth,_TextureHeight,level,usage,_TextureFormat,D3DPOOL_DEFAULT,_Texture,Null)
If hr<>D3D_OK Then Throw "Failed to Create Texture:"+HR
' lock the surface
Local lockrect:D3DLOCKED_RECT=New D3DLOCKED_RECT
If _Texture.LockRect(0,lockrect,Null,0)<> D3D_OK
Throw "Failed to Lock Texture"
' Move the pixmap to offscreen surface
' unlock the surface
' Texture ready
' from DX7 driver clean up filtering artifacts on
' scaled textures
Local p:Byte Ptr
If _Flags & MIPMAPPEDIMAGE n=Width-_pixmap.Width
For y=0 Until _pixmap.Height
For x=0 Until n
If _Flags & MIPMAPPEDIMAGE n=Height-_pixmap.height
For y=1 To n
There was one method in the loading of textures in Dx7 driver I never quite understood what it did..... I think I know now. I could not exactly duplicate what you where seeing in down scaling but up scaling I saw a similar artifact. This change cleaned it up.
Your comment on messing with filtering gave me the clue.
Please let me know if this cleans it up as I want to upload a an update that fixes a few other issues. The stupid alpha bug mentioned above as well as MaxGUI Canvass problem.
I still have to update to latest release of Max...
Thanks for all the feedback and help you provided. Let see if this addresses the issue.
| I wonder if this would fix my seam problem (post #8 above)? |
| @Tachyon, |
It might. Lot of factors, scaling, filtering, pixmap size, and to make it more fun video drivers and cards.
I know I fixed the alpha issue, and I reworked the VYSYNC that should fix the other issue your reported.
This might be fix to seam problem. What is the size of your tiles? Any scaling?
| Yup, that was the problem!|
I was indeed using PNGs, and using this 'SmearEdges' fixed it :)
| Are all (or any) of these imports necessary in dx9graphics? why were they included?|
Edit: I guess i should rephrase my question. I try to recompile the module to remove these auto imports I get the error "cannot find interface to 'brl.maxlua'
How can i restrict what bmax tries to import when doing a 'makemod' on this module?
| Wow. That is totally unnecessary. |
| Heh. Cool.|
Are they actually part of an import list, or is that what you had to add to get it to compile?
Whenever you get that error "cannot find interface", it usually means your build is out-of-sync (assuming that everything else is correct).
If you are using someone else's pre-compiled module, you will generally need to have at least the brl+pub modules they have. Or you will see this.
If you don't, you will need to rebuild the module (you should be able to get away with only building the one).
From the BlitzMax/bin folder, you can run this command-line to do it :
bmk makemods -a modulename
where "modulename" is the name of the module that you would Import - for example, bah.libxml
(I tried to look it up on the google code page, but the source isn't in the repository.. and I wasn't going to download the zip just to check that).
| None of those modules are directly referenced by the module.|
I think Brucey is on to the problem as the module source zip is precompiled with 1.32 so you will need to rebuild the modules if you using a different version.
just type "bmk makemods -a dbs" and "bmk makemods -h dbs" if you want threaded versions.
| Sorry for the newbish question, I'm using 1.30. Everything after that seems to have major issues. |
Has there been changes to the bMax native DX9 stuff after 1.30 ?
What would cause this error.
C:\Dev\BlitzMax\bin>bmk makemods -a dbs
flat assembler version 1.66
3 passes, 24675 bytes.
Compile Error: Identifier 'D3DADAPTER_IDENTIFIER9' not found
| As of 1.32 the directx9 headers have been made part of the official distribution so the module now imports the direct x references from the pub\directx module that is part of 1.32|
The module is currently only compatible with 1.32 and above.
You could however back port the pub/directx module into the 1.30 modules and it should work correctly.
| Thanks for clear that up. |
| Possible bug:-|
Graphics 640, 480
mx = MouseX()
my = MouseY()
DrawCrosshair(mx, my) '<---Should be invisible
DrawText mx + ":" + my, 0, 0
Function DrawCrosshair(xp:Int, yp:Int)
The crosshair should become invisible due to the SetAlpha(0.0) command, but it stays as bright as a button?
Removing 'SetGraphicsDriver D3D9Max2DDriver()' and rolling back to the default driver fixes it, so obviously something is wrong.
| It is a bug fixed up not uploaded yet.|
| Oh, I see... I'll let it go then! :)|
| Using some example code I found, I am testing speed of writting to dual screens. When using the D3D9Max2DDriver I am getting unexplained errors, please give it a go:|
Local x:Double[2,2] , y:Double[2,2]
Global quit% = False
screen = CreateGraphics( 640, 480, 0, 60, 0 )
screen = CreateGraphics( 640, 480, 0, 60, 0 )
x[0 , 1] = 1
y[0 , 1] = 1.5
x[1 , 1] = 1
y[1 , 1] = 1.5
AddHook systemEventHook , _hook
While Not quit
For Local n = 0 To 1
SetGraphics( screen[n] )
x[n , 0] :+ x[n , 1]
y[n , 0] :+ y[n , 1]
If x[n , 0] > GraphicsWidth() Or x[n , 0] < 1 Then x[n , 1] = - x[n , 1]
If y[n , 0] > GraphicsHeight() Or y[n , 0] < 1 Then y[n , 1] = - y[n , 1]
DrawText("O" , x[n , 0] , y[n , 0] )
If KeyDown(KEY_SPACE) And n=1 Then DrawOval 0 , 0 , 640 , 480
Local Event:TEvent = TEvent(tData)
If Event.ID <> EVENT_MOUSEMOVE Then Print "[" + Event.ID + "] " + Event.ToString()
If event = Null Then Return tData
quit = True
I have to admit I did not even know you could do that that. I have to think about how to make something like that work.
That would work fine with two MAXGUI windows since the windows are created externally and you have some control over the windows.
Just curious why would you do something like this?
I will be on vacation til end of May so I wont be able to look at it til the end of the month.
Thanks for the reply. I am developing a game that uses two monitors and this application does a good job of showing the consequence of using a non accelerated 2nd screen, just drag one of the windows to a second screen and watch how slow things become. I was hoping that DX9 did a better job than DX7 but not been able to test as yet.
No problem on the reply. As for performance degradation with Dx7 probably OpenGL as well and why Dx9 does not currently work, has to do with the way resources are managed with the underlying drivers and how textures etc are shared, with a call to CreateGraphics .... there not.
Basically if you load an image and draw it on one Graphics Context then switch to another it disposes the one resource and reloads its. So nothing is ever cached and it just thrashes resources
With MAXGUI it uses the AttachGraphics call which sets up a shared context and that will not suffer that penalty. Under this the DX9 Driver works fine as I actually tested this conceptually with Dx9 and recently committed a fix as I was not correctly reseting the projection matrix on switch.
Dx9 will work significantly better than Dx7 as internally it setups separate swap chains for each window. Dx7 creates one huge hidden back buffer and blits internally manages rendering to a sub region the size of the window. I have not explored totaly how OpenGL works but most like creates a separate shared Opengl context for each DC (Device Context) of the window its attached.
I can probably make CreateGraphics work like Dx7/Dx9 but the internals of Texture management will suffer the same penalty. Unless you create the images and ensure they are only rendered in the correct window.
I recommend you try using MaxGUI to create the windows and attach Canvases and think you get what your looking for as well as performance to boot.
| I encounter the slow-down on my second monitor too. Not only with bmx, but also other games. Dx9 just performs the same.|
I think it might be not a problem of the gfx API. I googled about it and find some similar reports, but no solution yet.