Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Di Mai 14, 2024 05:19

Foren-Übersicht » English » English Programming Forum
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Faster Loading of JPGs
BeitragVerfasst: Sa Okt 17, 2009 11:42 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
Hi all,

It's been a long time since I've asked a question. I've been adding more and more to my HMusicCentreXin project and one thing I've been noticing is a slight jerk to the UI when I'm loading more JPGs in the background, often via a TTimer's event. I'm putting this down to the amount of work the system is doing to load a JPG into a Texture and I'm wondering if there are more efficient ways of getting a JPG into my OpenGL application. These JPGs are all 426x104 pixels in dimensions, so nPoT.

At the moment, it does the following steps...

1) Create a JPG object.
2) Loads it from file.
3) Creates a 32-bit BMP object.
4) Draws the JPG onto the BMP.
5) Swaps the BMP image vertically.
6) Generates a Texture, sets GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER to GL_LINEAR.
7) Calls gluBuild2DMipmaps.

I was wondering if this could be done more efficiently, somehow. Ideas I was thinking about, and wouldn't mind advice on, are:

1) Can I avoid doing the vertical spin of the image (for these specific JPGs) and just change my glTexCoord2f calls?
2) Can I avoid calling gluBuild2DMipmaps altogether? Or can I reduce the amount of work that it has to do somehow?
3) Can I somehow thread this image loading, so that it doesn't interfere with the main UI of the application so obviously?
4) Should I just try to make calls to Application.ProcessMessages every now and again in the JPG loading code?

Any thoughts appreciated on this one... my application has a full screen poster of Album images that flip in and out as time progresses - when it does this flip, you can clearly see (although sometimes more than others) the application jerk for a fraction of a second. It would be nice to stop this happening, or so much.

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Okt 17, 2009 11:55 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
For question 3 I can recommend to put everything before the actual texture is generated into a separate thread. When this thread is finished, it should somehow notify the main thread (the one with the UI) about it (Synchronize, a queue, anything) so that it can load the image finally to a texture. You cannot put gl-calls in a thread.
The vertical spin should not be a problem anymore then, since this is done in the thread.
I would guess that with this image size, the most time is really spent on reading the image from hdd, decoding and drawing it onto the bitmap.

greetings

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Okt 17, 2009 11:57 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7804
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
You don't need to rotate the Texture manually.
You can rotate the texture coordinates easily.

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Okt 17, 2009 14:51 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
1) Yes. You can use other texcoords to avoid rotation. But simple flipping of an image only should takes 1-2ms. Max. You only have to copy whole lines from beginning of an memoryblock to the end. No big thing for cpu.

2) You never should use gluBuild2DMipmaps anymore. Really. gluBuild2DMipmaps is the slowest method to upload textures i ever seen. gluBuild2DMipmaps will resample you image if its not POT. This always takes cpu time and it decreses the quality of the texture. Your Texture should have 512x128 as resolution after uploading. If you can use NPOT Textures you should use them. To generate mipmaps you can set the parameter GL_GENERATE_MIPMAP. This parameter is contained in the OpenGL Core 1.4 and the extension GL_SGIS_generate_mipmap.
Code:
  1. glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE);

Uploading of the Textures so takes only few milliseconds.

3) like Lord Horazont said. Load the jpeg themself in the thread and create/upload the data in the main thread. With synchronize or something.

Some addition: If you are using the unit jpeg. You can set the property performance of the TJPEGImage class to fastest. There only support 2 possible values. One named fastest and the other named other. This also should bring some milliseconds while loading images. If you like it hardcore you also can use the libJpeg. In my glBitmap i also provide some loading code for this library. This library is also faster than the delphi implementation. But also heavy to write for.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Okt 17, 2009 15:59 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
Hmm... tinkering a bit led to me add Forms to my uses clause and go and insert some Application.ProcessMessages statements in around the JPG loading, flipping and suchlike. The UI jerk has decreased somewhat. I do not think this is a proper way to do it - the other ideas are proper - however, it has had a positive effect and doesn't seem (after some initial testing) to have had any adverse effects.

I guess, if my problem is not out-and-out performance, as such (maybe the title was misleading) - but is actually more to do with UI interference while loading JPGs, then this might be a simple partial solution.

Hmm, if I am not encouraged to use gluBuild2DMipmaps, because it is slow, should I be using glTexImage2D... with GL_TEXTURE_RECTANGLE_ARB? Can everyone use that though?

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Okt 17, 2009 18:57 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2621
Wohnort: Berlin
Programmiersprache: Go, C/C++
Is there any problem by using dds with dxt5 ?
1)would be solved
2)would be solved
3)nothing image format specif, you have to create a thread, this load the file to memory, do file format specif decoding, put it in internal software specific format, callback the renderthread or mark that the job is done and destroy thread
4)i dont understand the question

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Okt 18, 2009 04:51 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jul 21, 2004 22:39
Beiträge: 360
Wohnort: UK, Scotland
Id recommend using FreeImage, it can load lots of different formats and the delphi wrapper can give you the texture in the format opengl likes.

_________________
Free Map Editor - Game Requirements - Stucuk.Net
-Stu


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Okt 18, 2009 10:18 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Tak: I would say there is an problem to use dxt5. Because dpm_dpmartin programms an software for user. So i think the images would come from the user. And no user will create dxt5.

NPOT Textures. There are many ways to create npot textures.
1) If you have OpenGL Core 2.0 or the Extension GL_ARB_texture_non_power_of_two you can use npot texture as normally GL_TEXTURE_2D. Just upload Texturedata with glTexImage2D.
2) You can create an expanded POT texture. For 426x104 you can use 512x128. But for uploadung you use glTexSubImage2D. You have to change your texcoords to prevent for empty parts of the texture. You have some memory waste but your texture will be 1:1.
3) You can use Texture Rectangles. But MipMaps are not supported.

MipMaps (GL_GENERATE_MIPMAP) works with method 1 well. Excpect ATI Cards and the generation radeon 9x00 and radeon X800. Mipmaps with Method 2 will also work but you have to change something in the texture. The last row and line must be expanded to the end of the texture. So resampling of the texture wont make problems. If you dont need mipmaps you can use any of. But i prefer to use 1. Method 2 or 3 as fallback if method 1 isnt supported.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Okt 23, 2009 14:08 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
So, I did actually try doing the JPG load, BMP draw and conversion to byte array in a Thread, before synchronising with the main program and calling a procedure that uses gluBuild2DMipmaps. Compared to the normal routine for loading a texture, I now seem to have found out that the majority of time is spent in the gluBuild2DMipmaps routine, as might be expected, I suppose, as opposed to the time spent in loading of the JPG, drawing onto BMP and conversion to byte array.

With the normal routine, loading a 426x104 px JPG into a texture, seems to consistently take around 80 ticks, measured multiple times with GetTickCount. The whole JPG loading routine with the Thread, i.e. starting the Thread, loading the JPG, converting, synchronising etc., seems to consisently take about 110 ticks in total. If I move the GetTickCount call to measure before the call to gluBuild2DMipmaps then the loading of the JPG, drawing to BMP and converting to byte array seems to consistently take 20 ticks... seems gluBuild2DMipmaps is consistently taking around 90 ticks.

What this seems to mean, though, is that loading a JPG into a texture via a Thread doesn't really seem to benefit my jerky user interface, as there is still a big chunk of work being done in gluBuild2DMipmaps. At least, that's what I'm inferring from my rather basic testing.

Can I tell gluBuild2DMipmaps to not do so much work, somehow? I only really want my texture at one size.

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Okt 23, 2009 15:30 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2621
Wohnort: Berlin
Programmiersprache: Go, C/C++
The best performance you get with threading, background loading and precaching of the image files.
You can create a thread which open the file(only open) this will show the hdd which files are to fetch and if possible to copy in the cache of the HDD.
After you created all Threads and init them you start all threads and in the process methode they read the opened file and close the file(soon as possible best after the read command).
If this is done you have a memory copy of the file and can parse and decode it in the memory which higher the io throuput and the speed of the decoding process because there is no sync with the hdd anymore.
After you decoded the data to a new memory block you can remove the file image in the memory and send your texture loader a callback with the decoded image data and image information.
If the main process get his timewindow on the cpu it recognize the callback and will upload the imagedata into the opengl texture.
You can create the OpenGL texture in the loading call before the thread will be created and if you know the resolution you can create a empty texture without mipmaps and a default image(saved as hardcoded ressource in the binary) and if you don't have the size you create a dummy texture with 1x1 pixel and a fillcolor(white, gray, black are regular colors). In the second case you have to delete the id and create a new one after the decoded image data are arrived.
This way is a common way to load big and/or many texturedata without to stop the rendering process(picalens, Mirros Edge and other use thread based background loader but on the first point with the hdd cache optimation isn't, thats my idea to optimize it on pc).

edit:
It will be better if you write your own MipMap generator because this must be thread safe, you can handle npot and pot texture and the glu version don't use vector optimation like mmx or sse what reduce the performance.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Okt 24, 2009 16:06 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
It seems to me that what I need is gluBuild2DMipmapLevels. I have tried gluBuild2DMipmaps but found it slow. I have tried glTexImage2D but it doesn't work - not unexpectedly as I believe ARB_texture_non_power_of_two is not supported. What I think I want, ideally, is something that builds a single mipmap (if that makes sense).

What I thought I might be able to do is add:

Code:
  1. function gluBuild2DMipmapLevels (Target : GLEnum; Components, Width, Height : GLInt; Format, AType : GLEnum; Level, Base, Max : GLInt; Data : Pointer): GLInt; stdcall; external GLU32;

To my Textures unit, just like I have with:

Code:
  1. function gluBuild2DMipmaps (Target : GLEnum; Components, Width, Height : GLInt; Format, AType : GLEnum; Data : Pointer): GLInt; stdcall; external GLU32;

However, this does not seem to work either. I'm guessing that's because my version of OpenGL, GLU actually, doesn't support this. How do I know whether this is the case for sure?

Writing my own mipmap generator sounds... difficult? How would I start?

P.S. - checked my glu32.dll and it does not contain gluBuild2DMipmapLevels, so I think I've answered my first question.

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Okt 24, 2009 17:57 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 24, 2007 00:44
Beiträge: 144
I figured that gluBuild2DMipmaps, possibly, internally repeatedly calls gluScaleImage when doing its work, then calling glTexImage2D for each level. So I thought writing a one time conversion, by firstly scaling my 426x104 px image to 512x128 px, and then calling glTexImage2D once, might improve things for me.

Code:
  1.   gluScaleImage (GL_RGB,426,104,GL_UNSIGNED_BYTE,SourceData,512,128,GL_UNSIGNED_BYTE,ResultData);
  2.   glTexImage2D (GL_TEXTURE_2D,0,GL_RGB,512,128,0,GL_RGB,GL_UNSIGNED_BYTE,ResultData);

Although this works, in that a correct looking texture is produced and can be seen on screen looking just like I'd expect it to, after previously using gluBuild2DMipmaps, there doesn't actually seem to be much of an improvement in overall performance. I suppose I'd really expected it to be several times faster than gluBuild2DMipmaps, considering it is only doing a single gluScaleImage and glTexImage2D rather than the many I had presumed it was doing internal to gluBuild2DMipmaps.

In fact, it seems to be consistently slower than simply calling gluBuild2DMipmaps.

Or am I going slightly off-piste, with what gluBuild2DMipmaps is doing internally, here? Is it not calling gluScaleImage and glTexImage2D several times?

_________________
Cheers, DpM
http://www.hmusiccentre.org.uk


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Foren-Übersicht » English » English Programming Forum


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 6 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.081s | 17 Queries | GZIP : On ]