Textures compression tool (BINARY RELEASED)

Announce new projects or updates of Irrlicht Engine related tools, games, and applications.
Also check the Wiki
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Re: Optimized/Compressed Textures - KTX Loader (v.0.0.1 READ

Post by REDDemon »

Agree partially with you Nadro. As you sad new flags are required but Proxy textures are still needed. (just see examples below.. anyway keeping a copy of a IImage is a proxy pattern anyway). I will not add new flags to loading methods, but to the "lock" method.

How irrlicht is used? If a user need to load a texture he's probably doing that with one of the following methods (IVideoDriver):

Code: Select all

 
ITexture* getTexture(const io::path& filename);
ITexture* getTexture(io::IReadFile* file);
 
Those methods internally are using the image loaders. They create a IImage, they convert it to a texture and then they drop the IImage.. But creating and destroying a IImage is a bit expensive.

With the KTX loader those methods are no longer forced to create the IImage . The KTX texture is directly created with the KTX loader (wich is finished). This gives a huge speed up at loading time. A ITexture is returned but in much less time. (probably you can already give me the permission to slitghtly modify those methods Hybrid).

The thing wich is expensive is creating a IImage from a compressed texture. That would require to send compressed data to GPU for decompression (decompression is really fast. But sending and receving texture data from GPU can be slow). Now you'll agree that giving the chance to the user to create a Image from compressed textures need a second thought. Doing that will be expensive operation

But if we decide to do so, it must be in the following way:

Now suppose the user want to create a Image from that texture (he don't know that the texture is compressed). He'll need that method.

Code: Select all

 
IImage* createImage(ITexture* texture,
                                const core::position2d<s32>& pos,
                                const core::dimension2d<u32>& size) ;
 
We don't want to give user compressed data:
1) He don't know how to use compressed data
2) even if he know how to do that, the license don't allow him for doing nothing without permission (unless he's using DX or GL API.. but at this point why he used Irrlicht if he don't want to take advantage from high level API? :D)

The user don't have to use the "lock" methods since it's called by Irrlicht doing most of the work for him. In that case the proxy will be useless and is not needed (as suggested by you Nadro).

But with more advanced usage, the Proxy is strictly needed let's see these examples.

user read the texture without the proxy

Code: Select all

 
myTexture->lock(READ_LOCK); // Allocation. + Gpu read access
 
myTexture->unlock(); // data deallocation. 
myTexture->lock(READ_LOCK) // new allocation. another gpu read access
 
myTexture->unlock(); //data deallocation
 
 
user read the texture with a proxy

Code: Select all

 
myTexture->lock(READ_LOCK_KEEP); // proxy is created.  GPu access (only once)
 
myTexture->unlock(); // proxy is notdestroyed
myTexture->lock(READ_LOCK_KEEP) // proxy is already PRESENT => NO GPU READ ACCESS (great time gain)
 
myTexture->unlock(); // proxy not destroyed
myTexture->lock(FREE_RAM);// proxy destroyed
myTexture->unlock(); //do nothing user can skip it. Just good exercise to call unlock anyway.
 
 
user read/write without a proxy

Code: Select all

 
myTexture->lock(READ_LOCK); // memory allocated. GPU read access
 
myTexture->unlock(); // memory deallocated
 
 
myTexture->lock(WRITE_LOCK); //memory allocated.
 
myTexture->unlock() ; //memory deallocated. data sent to GPU ==> IMAGE QUALITY LOSS
 
myTexture->lock(READ_LOCK); //memory allocated. GPU read access
 
myTexture->unlock(); //memory deallocated.
 
 
user read/write with a proxy

Code: Select all

 
myTexture->lock(READ_LOCK_KEEP); // proxy is created.  GPU access for reading (only once)
 
myTexture->unlock(); // proxy is not  destroyed
 
myTexture->lock(WRITE_LOCK_KEEP); //proxy is already present. 
 
myTexture->unlock() ; //proxy is not destroyed. Data sent to GPU => LOSS OF QUALITY (only once, and only on the GPU. the original image with original quality is still
in ram and can be accessed)
 
myTexture->lock(READ_LOCK_KEEP); //proxy is already present. NO GPU READ access( we have already that data in the proxy) NO LOSS OF QUALITY. (we access data wich is holded in RAM memory and has original quality).
 
myTexture->unlock(); //proxy is not destroyed.
 
/// when user no longer need the data. he release the proxy
myTexture->lock(FREE_RAM); // no need to call unlock
 
You'll agree that every time we send data back to GPU it'll be compressed reducing image quality. So using a proxy help to preserve image quality. Using a proxy help to save performance. Read access to GPU is slow. we read from GPU only once and then the proxy keep that data cached for us (with the original quality).
 
 
So if we want to give users ability to access compressed textures data,  we must do that adding 4 new lock flags

Code: Select all

 
READ_LOCK_KEEP  //proxy created if not present and not not destroyed on unlock. If proxy is created we Read from GPU.
WRITE_LOCK_KEEP //proxy created if not present and not not destroyed on unlock. data sent to GPU on unlock
READ_WRITE_LOCK_KEEP //proxy created if not present and not not destroyed on unlock. data sent to GPU on unlock
FREE_RAM //drop proxy
 
existing enum:
 
READ_LOCK //no proxy creation (if can be avoided as sad by Nadro). if proxy is present will be destroyed on unlock (and data will readed from that proxy anyway to save time)
WRITE_LOCK // no proxy creation (if can be avoided). if proxy is present will be destroyed on unlock (data will be readed from that proxy anyway to save time) Data is sent to GPU on unlock.
READ_WRITE_LOCK// no proxy creation (if can be avoided). if proxy is present will be destroyed on unlock (data will be readed from the proxy and sent back to GPU before destroying the proxy.).
 

the behaviour of those new locks can be extended to pre-existing texture Implementation (will be very usefull in future if someone want to implement texture streaming. I know how to do that but just I want to focus un one problem for now).

But probably in a first place will be more usefull that pre-existing implementation ignore new enums (locking with new enums just return a null pointer for old textures implementation. that's a safe way for don't messing up Irrlicht's working code). After that those enums are working for compressed textures we can discuss about extending that implementation also to pre-existing textures or not.
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: Optimized/Compressed Textures - KTX Loader (v.0.0.1 READ

Post by Nadro »

Loading process with Image and TextureProxy approach will be the same, allocation and dealocation also. Your concept with a TextureProxy is really nice, but I think that if we can use already existed structures we should use it.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Re: Optimized/Compressed Textures - KTX Loader (v.0.0.1 READ

Post by REDDemon »

Nadro wrote:Loading process with Image and TextureProxy approach will be the same, allocation and dealocation also. Your concept with a TextureProxy is really nice, but I think that if we can use already existed structures we should use it.
Agree. what matters is the pattern not the structure holding it. By the way, if is possible using directly the Image class would be great. I need to check if IImage supports data with unpack alignement of 4 else It can't be used for direct exange with the GPU. (with such alignment all GPU operations are faster).
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Optimized/Compressed Textures - KTX Loader (v.0.0.1 READ

Post by Granyte »

woah this is some awsome stuff

i have a couple question i looked through the thread but it's way to information heavy and i lost some

is there or will there be a way to create compressed texture internaly?
just as aditional context in my project i generate 6 texture maps of 1024*1024 using the gpu so that implies rendering to an rtt, compying the rtt to IImage, creating a new texture from IImage and in the end the texture take up like 512mb of video memory so compressed texture would be quite usefull here.

argh i lost the rest while writing this so ill ask some more if they come to my mind
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Optimized/Compressed Textures - KTX Loader (v.0.0.1 READ

Post by hendu »

6*1024*1024*4 = 24mb, not 512?
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Optimized/Compressed Textures - KTX Loader (v.0.0.1 READ

Post by Granyte »

24mb * 9 planets *2 for IImage that can't be dropped = 432mb

let's not get into what happens when i use 2048*2048 size maps
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Optimized/Compressed Textures - KTX Loader (v.0.0.1 READ

Post by hendu »

Then you clearly need a LOD system, not compressed textures (which would drop quality too) ;)
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Optimized/Compressed Textures - KTX Loader (v.0.0.1 READ

Post by mongoose7 »

I don't understand the bit about copying a texture to an IImage and then creating a texture from it.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: Optimized/Compressed Textures - KTX Loader (v.0.0.1 READ

Post by Nadro »

mongoose7 wrote:I don't understand the bit about copying a texture to an IImage and then creating a texture from it.
We copy a "texture data" from a file to IImage and next we create a texture from a IImage data, so we don't copy a texture to an IImage.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Optimized/Compressed Textures - KTX Loader (v.0.0.1 READ

Post by Granyte »

hendu wrote:Then you clearly need a LOD system, not compressed textures (which would drop quality too) ;)
well the texture version is used only for texture splating inside a shader so quality drop is not that much of a loss since i use a the IImage to generate the mesh
i would have used a generator to generate texture per patch when the ground lod change but being forced to generate a IImage from a RTT to then generate a normal texture from it is all but enjoyable
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Re: Optimized/Compressed Textures - KTX Loader (v.0.0.1 READ

Post by REDDemon »

THX :D !

quality loss for compressed textures is not very noticeable. Especially for photographies and real textures. Quality loss is very noticeable in hand drawn and cartoon like textures. Texture compression however is fast but not so fast for realtime purposes. (compress a 1024x1024 texture takes few seconds on my machine)
Granyte wrote: is there or will there be a way to create compressed texture internaly?
actually there's no way for take a IImage or other texture and compress it with Irrlicht. I'm still waiting for opinion about how to integrate it in the irrlicht API. (I proposed few little changes too and I'm preparing some code but nothing serious for a patch for now). But there's a working loader and now also the KTX exporter:

In the while I finished the first release of it! Now you have the loader for Irrlicht and the compression tool.
Enjoy (also updated the first post):

https://sourceforge.net/projects/fixeengine/files/

that's for Windows only. If there is any good Samaritan that has time to compile it for Linux and/or Mac that would be great. Source code is available and zlib licensed

please if you find any bug just report here. I did my best for test in these days but It's impossible that is bug free.
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: Textures compression tool (v0.0.1 READY!!)

Post by hybrid »

Basically, we don't need any new functions at all. Simply put the compressed data into the IImage data and pass it on to the ITexture creation process. Just note that hundreds of places in Irrlicht will choke on this new IImage class, and hence will make users wonder why many things working with .bmp files don't work with .dds files anymore. That's something we don't want. So we first need a cleanup of the IImage API and can then add some new IImage implementations supporting several compression techniques etc.
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Re: Textures compression tool (v0.0.1 READY!!)

Post by REDDemon »

hybrid wrote:Basically, we don't need any new functions at all. Simply put the compressed data into the IImage data and pass it on to the ITexture creation process. Just note that hundreds of places in Irrlicht will choke on this new IImage class, and hence will make users wonder why many things working with .bmp files don't work with .dds files anymore. That's something we don't want. So we first need a cleanup of the IImage API and can then add some new IImage implementations supporting several compression techniques etc.
what's wrong with my proposal (1st post of the page)?

1) no changes to IImage class. ==> compressed files loaded from dds/KTX textures continue to working as normal RGB /RGBA images.
2) when a operation like "compressedTexture==>IImage" or "IImage==>compressedtexture" is required by the user (he's not forced to know that the texture is compressed ) the compression/decompression is handled by the ITexture implementation (this is driver specific and I find 100 times better add driver specific code to driver implementation then to IImage, wich is already huge).

summary == no API changes at all. very fast loading. ease of use for users, wich will not notice any difference except the fact that there are 2 new loadable file formats.


better never put compressed data into IImage(and for that there is no reason for API changes just for compressed textures). The Irrlicht API actually don't explicitly need that compressed texture data must putted in a IImage first. If the user explicity require a IImage from a compressed texture then the data (wich was on the IItexture first) is decompressed on the fly and sended to the IImage (and since is already decompressed the user will not have any trouble. so what was working with bmp will also work for KTX and DDS.. pretty good isn't it?).

Optional:
few additional changes to the API (not required for compressed textures. But may be required by irrlicht in future):

new enums for ITexture->lock(). They are not needed for now. But in future if you want texture streaming for Irrlicht you need those new locks methods. (makes everything faster).

summary == faster texture streaming. (and better control on texture streaming for advanced users). basically old lock enums are already present, so older code using older locking enums will still works (so the change is back->compatible). But newer code writed with the new locks works faster.
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: Textures compression tool (BINARY RELEASED!!!)

Post by Nadro »

We can leave in an IImage class methods compatible with both compressed and uncompressed data eg dimension, size etc. and other methods like a scaling, fill etc. put in an IImageManipulator, which will be compatible only with uncompressed images. As REDDemon said we can use methods like a glGetTexImage for get uncompressed data (so just ITexture::lock), what is very good idea, but it require that texture have to be created before image with uncompressed data, so what with a functions like a createImageFromFile? We must add a two states to an IImage: compressed and uncompressed (compressed state will lock some of IImageManipulator methods or internal CImage methods if we will not re-organise this class). If user will want a manipulate over a compressed image he will have to use ITexture::lock() method firstly to decompress image data, I think that method like a:

Code: Select all

IImage::decompress(ITexture* texture);
or

Code: Select all

IImageManipulator::decompressImage(IImage* image, ITexture* texture);
will be ok.

In future we will be allowed to add alternative methods for decompression:

Code: Select all

IImage::decompress();
or

Code: Select all

IImageManipulator::decompressImage(IImage* image);
for decompress a data without GPU support, but these methods bodies will be covered by
ifdef _PATENT_ALLOWED_OR_OTHER_NAME_
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Re: Textures compression tool (BINARY RELEASED!!!)

Post by REDDemon »

Nadro wrote: so what with a functions like a createImageFromFile?

Code: Select all

 
//returns 0 if trying to load a DDS or KTX file from BURNINGS VIDEO or SOFTWARE DEVICE
IImage * createImageFromFile(io::path & filename)
{
    ///If file type is KTX (or DDS )
    ITexture * text = Driver->getTexture(filename);
    IImage * image = Driver->createImage(text, ... );
    Driver->removeTexture(text);
    return image;
}
 
wich solves all other troubles and don't require changes to IImage ;-)
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
Post Reply