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);
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) ;
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? )
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
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.