DDS/DXT support in DX8/DX9/OGL drivers
DDS/DXT support in DX8/DX9/OGL drivers
Hello
For my 2D casual game project I'm looking for native (that is hardware) support of DXT/DDS/S3TC compressed images. I'm even ready to put some effort into implementing this part myself (first DX8, and later OpenGL when building a MacOsX version).
Looked into egrath's DDS loader, that is just a decoder, I don't need decoded pixels, I need native hardware-accelerated DXT support. Also looked into patch to Irrlicht source, which kind of enables DDS support, and I got it working partially at cost of hard to catch bugs, and totally ruined unmaintainable Irrlicht source, which I had to restore from the distribution archive.
So what I want to get (or create myself) now is:
- ITexture descendant with native hardware support for DXT/S3TC;
- IImage descendant with limited capabilities (due to packed nature of DXT textures) which can load DDS surfaces;
- Minimal (or zero) intrusion into Irrlicht sources, wherever possible;
- Support for DirectX8 right now, and later for OpenGL.
Looking for suggestions where should I start, also will hang around #irrlicht on freenode tomorrow, if anyone could throw me some advices.
P.S. If it looks good, I don't mind sharing the result with the community or even to have it added to the main Irrlicht core. Whatever floats your boat.
For my 2D casual game project I'm looking for native (that is hardware) support of DXT/DDS/S3TC compressed images. I'm even ready to put some effort into implementing this part myself (first DX8, and later OpenGL when building a MacOsX version).
Looked into egrath's DDS loader, that is just a decoder, I don't need decoded pixels, I need native hardware-accelerated DXT support. Also looked into patch to Irrlicht source, which kind of enables DDS support, and I got it working partially at cost of hard to catch bugs, and totally ruined unmaintainable Irrlicht source, which I had to restore from the distribution archive.
So what I want to get (or create myself) now is:
- ITexture descendant with native hardware support for DXT/S3TC;
- IImage descendant with limited capabilities (due to packed nature of DXT textures) which can load DDS surfaces;
- Minimal (or zero) intrusion into Irrlicht sources, wherever possible;
- Support for DirectX8 right now, and later for OpenGL.
Looking for suggestions where should I start, also will hang around #irrlicht on freenode tomorrow, if anyone could throw me some advices.
P.S. If it looks good, I don't mind sharing the result with the community or even to have it added to the main Irrlicht core. Whatever floats your boat.
Last edited by kvakvs on Fri Aug 13, 2010 12:54 pm, edited 1 time in total.
/* my homesite */
Just had a look.
It is decompression code, it defeats the whole idea of storing compressed texture in video memory. That is something that I don't need, because in current state my game perfectly loads JPEG images + single channel JPEG alpha layers, and it works, but it eats horrible amount of video memory, that I'm addressing this issue.
It is decompression code, it defeats the whole idea of storing compressed texture in video memory. That is something that I don't need, because in current state my game perfectly loads JPEG images + single channel JPEG alpha layers, and it works, but it eats horrible amount of video memory, that I'm addressing this issue.
/* my homesite */
I'm still reviewing through the CImageLoaderDDS.cpp/h source, and only can see here ECF_A8R8G8B8 texture creation, which is decompressed upon loading. Keeping going like this, my JPEG+Alpha JPEG loading code works just fine, but eats too much video memory.anchor wrote:CuteAlien said: the DDS decompression will be optional is this new feature
Actually a set of new ECF_* constants should be added to SColor.h (which are not there yet), and then to use something like D3DXCreateTextureFromFileInMemoryEx (for DirectX8). That would be new color format, and new texture type (with limited pixel and area access).
/* my homesite */
Yeah - you can kick it out. But you don't get support for working with compressed textures that way. That's still a missing feature and yes - I would also like to have that one also.anchor wrote:CuteAlien said: the DDS decompression will be optional is this new feature ;)
There had actually been a patch for that a few years ago. It needed some changes to IImage, but worked at least for OpenGL (or was it DX? not sure anymore...). But I never found time to apply that and obviously the same for everyone else so far.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
You can find patch for OpenGL here:
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=33552
I think that this is the best solution at this moment.
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=33552
I think that this is the best solution at this moment.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Don't know. Why don't we get longer days than 24 hours? We could do so much more stuff ;-) (hm, probably we would just be forced to work even longer in our day-jobs)anchor wrote:Why You don't implement that?
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
So...
To keep stuff simple, what can I offer (also experimenting with it these days, trying to integrate into my prerelease quality 2D casual game)
1. Create CImageDDS, a subclass of IImage, always use format ECF_UNKNOWN (noone should ever need to access pixels and blocks in DDS surface) or add ECF_DXT* formats but that also means patching SColor.h which i'm trying to avoid. Deny copying incompatible textures/texture areas. Possibly deny locking, or make another function for it, as pixels aren't directly accessible.
2. Create CTextureDDS, a subclass of ITexture, created automatically from file in memory, or file reader. This will go under DX or OGL driver section, one per driver. As always, limited capabilities, deny anything which tries to access underlying texture blocks. Allow anything which is correctly supported by DX or OGL interface.
Not sure about mipmap levels, my game is not using it, so I won't really bother with them, also no chance to test them working.
Any other places to inspect and edit? I'm not much familiar with Irrlicht internals, thus I'm trying to avoid changing Irrlicht source as much as possible.
To keep stuff simple, what can I offer (also experimenting with it these days, trying to integrate into my prerelease quality 2D casual game)
1. Create CImageDDS, a subclass of IImage, always use format ECF_UNKNOWN (noone should ever need to access pixels and blocks in DDS surface) or add ECF_DXT* formats but that also means patching SColor.h which i'm trying to avoid. Deny copying incompatible textures/texture areas. Possibly deny locking, or make another function for it, as pixels aren't directly accessible.
2. Create CTextureDDS, a subclass of ITexture, created automatically from file in memory, or file reader. This will go under DX or OGL driver section, one per driver. As always, limited capabilities, deny anything which tries to access underlying texture blocks. Allow anything which is correctly supported by DX or OGL interface.
Not sure about mipmap levels, my game is not using it, so I won't really bother with them, also no chance to test them working.
Any other places to inspect and edit? I'm not much familiar with Irrlicht internals, thus I'm trying to avoid changing Irrlicht source as much as possible.
/* my homesite */
I've made:
* DDS Loader - another one, slightly based on that in SVN; Hidden inside nativedds namespace to avoid possible name clashes and to draw a clear line around my changes;
* DDS Image - minimum functions only holds the DDS file contents and responds to various queries;
* DDS Texture for DX8 - almost functional, but had various kinds of trouble trying to load via D3DXCreateTextureFromFileInMemory and *Ex, then decided to rewrite without D3DX according to Microsoft example in DXSDK9
Got into the following trouble now.
When using new DDS image and DDS texture classes I'm getting access violation in SMaterial & operator = access beyond allocated memory during DrawIndexedPrimitiveUP() call. The result and access violation address varies if I change _IRR_MATERIAL_MAX_TEXTURES_, so might be wrong allocated memory size - 0xABABABC3 (24 bytes beyond 0xAB) or AV accessing 0x00000002 (possibly some numeric member of SMaterial used as a pointer and caused the AV).
Obviously the new texture and new image classes now have different sizeof, than those Irrlicht's original. I did not modify SMaterial data members etc. Is there static memory allocation somewhere which could be conflicting with my new data sizes?
What possibly can cause this size difference? I have rebuilt Irrlicht and my project multiple times from scratch, can't be the LIB version mismatch.
* DDS Loader - another one, slightly based on that in SVN; Hidden inside nativedds namespace to avoid possible name clashes and to draw a clear line around my changes;
* DDS Image - minimum functions only holds the DDS file contents and responds to various queries;
* DDS Texture for DX8 - almost functional, but had various kinds of trouble trying to load via D3DXCreateTextureFromFileInMemory and *Ex, then decided to rewrite without D3DX according to Microsoft example in DXSDK9
Got into the following trouble now.
When using new DDS image and DDS texture classes I'm getting access violation in SMaterial & operator = access beyond allocated memory during DrawIndexedPrimitiveUP() call. The result and access violation address varies if I change _IRR_MATERIAL_MAX_TEXTURES_, so might be wrong allocated memory size - 0xABABABC3 (24 bytes beyond 0xAB) or AV accessing 0x00000002 (possibly some numeric member of SMaterial used as a pointer and caused the AV).
Obviously the new texture and new image classes now have different sizeof, than those Irrlicht's original. I did not modify SMaterial data members etc. Is there static memory allocation somewhere which could be conflicting with my new data sizes?
What possibly can cause this size difference? I have rebuilt Irrlicht and my project multiple times from scratch, can't be the LIB version mismatch.
/* my homesite */
Resolved now.kvakvs wrote:Got into the following trouble now.
D3D8Driver was using (CD3D8Texture *) C-style cast on everything. Fixed by making CD3D8Texture abstract common ancestor for (renamed) CD3D8TextureImpl and CNativeDDSTextureD3D8.
Now to fix the build tool (adding NV Texture Tools C# binding to my C# based level editor) and repack all my 6000 project resources and see what happens.
/* my homesite */
Okay.
For now, DDS support for DX8 is functional as much as I needed it to be.
* D3DX is not used. I used example from DX SDK 9, and rewrote it for DX8;
* Mip levels detected, loaded and supported;
* Per pixel disabled (for obvious reasons, can't access specific packed pixels)
* Locking of image returns packed image DDS data, might be not convenient for compatibility, should return NULL here probably, and make a new function to access DDS data.
* Locking of texture returns what DX8 would return. If you ever need that data.
Changes to rest of Irrlicht are kept to minimum (well at least i tried):
1. New define to IrrCompileConfig.h, and test to block both DDS loaders (Irrlicht original decoder DDS loader and my loader) from being enabled at the same time; Loader creates a subclass of ITexture (Native DDS Texture) which is a very limited brother of CTexture.
2. Added registration code for DDS file loader (don't remember which file, but code maintainers should know )
3. In SColor.h added new constant for native DDS texture format - all DDS textures return this constant regardless of internal format.
Changes apply to both CD3D8 AND CD3D9 code:
1. Change to D3D*Driver::CreateHardwareTexture to create my DDS texture class instead of original CD3D*Dexture.
2. Renamed CD3D*Texture to CD3D*TextureImpl everywhere in D3D*Driver and created CD3D*Texture as a base class with 3 abstract functions - this is to allow (CD3D*Texture *) C-style cast in D3D*Driver code, which would be throwing horrible access violations, if I would subclass my native DDS texture from ITexture and not CD3D*Texture.
3. In D3D8Texture and D3D9Texture Functions hasMipMaps, getDX*Texture, createRenderTarget, getRenderTargetSurface been made virtual. Constructors of D3D*TextureImpl now refer to C3D*Texture as base class instead of ITexture (since their base class changed).
4. DepthSurface and Texture members moved from CD3DTexture9Impl up to CD3DTexture, it remains NULL forever in CNativeDDSTextureD3D9, but used by normal CD3D9Texture's.
The code is now being thoroughly tested in a production environment (a 2D casual game with ~6000 texture resources most packed in DXT1 or DXT5). Our game is going to be released within 5-7 days so I expect, don't have time to do anything until then. Then I will find time to tidy up the code and upload to my website, and post here for review.
In couple of months I expect to be assigned to do MacOS port of the game, there will be created OpenGL DDS texture class and debugged in a production environment as well. So stay tuned.
For now, DDS support for DX8 is functional as much as I needed it to be.
* D3DX is not used. I used example from DX SDK 9, and rewrote it for DX8;
* Mip levels detected, loaded and supported;
* Per pixel disabled (for obvious reasons, can't access specific packed pixels)
* Locking of image returns packed image DDS data, might be not convenient for compatibility, should return NULL here probably, and make a new function to access DDS data.
* Locking of texture returns what DX8 would return. If you ever need that data.
Changes to rest of Irrlicht are kept to minimum (well at least i tried):
1. New define to IrrCompileConfig.h, and test to block both DDS loaders (Irrlicht original decoder DDS loader and my loader) from being enabled at the same time; Loader creates a subclass of ITexture (Native DDS Texture) which is a very limited brother of CTexture.
2. Added registration code for DDS file loader (don't remember which file, but code maintainers should know )
3. In SColor.h added new constant for native DDS texture format - all DDS textures return this constant regardless of internal format.
Changes apply to both CD3D8 AND CD3D9 code:
1. Change to D3D*Driver::CreateHardwareTexture to create my DDS texture class instead of original CD3D*Dexture.
2. Renamed CD3D*Texture to CD3D*TextureImpl everywhere in D3D*Driver and created CD3D*Texture as a base class with 3 abstract functions - this is to allow (CD3D*Texture *) C-style cast in D3D*Driver code, which would be throwing horrible access violations, if I would subclass my native DDS texture from ITexture and not CD3D*Texture.
3. In D3D8Texture and D3D9Texture Functions hasMipMaps, getDX*Texture, createRenderTarget, getRenderTargetSurface been made virtual. Constructors of D3D*TextureImpl now refer to C3D*Texture as base class instead of ITexture (since their base class changed).
4. DepthSurface and Texture members moved from CD3DTexture9Impl up to CD3DTexture, it remains NULL forever in CNativeDDSTextureD3D9, but used by normal CD3D9Texture's.
The code is now being thoroughly tested in a production environment (a 2D casual game with ~6000 texture resources most packed in DXT1 or DXT5). Our game is going to be released within 5-7 days so I expect, don't have time to do anything until then. Then I will find time to tidy up the code and upload to my website, and post here for review.
In couple of months I expect to be assigned to do MacOS port of the game, there will be created OpenGL DDS texture class and debugged in a production environment as well. So stay tuned.
Last edited by kvakvs on Fri Aug 13, 2010 1:41 pm, edited 5 times in total.
/* my homesite */