Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[DirectX] Textures laden terwijl programma loopt

Pagina: 1
Acties:
  • 394 views sinds 30-01-2008
  • Reageer

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 12:58
Ik heb nog niet erg veel ervaring met DirectX, maar ben momenteel aan de hand van DirectX 9 in C++ een soort slideshow programmaatje aan het proberen schrijven.
De reden om het in DirectX te doen is zodat er van de hardware gebruik kan gemaakt worden voor transparantie-effecten, en misschien later experimenteren met pixel shaders of iets dergelijks.

Het is me op dit moment gelukt om een jpg in te laden als texture (tegenwoordig blijken grote textures en groottes die geen macht van 2 zijn geen probleem meer te zijn) en ze te tonen en transparantie toe te passen om tussen de foto's te faden.
Ook de kwaliteit heb ik door mipmap's te genereren en filters in te stellen goed gekregen.

Mijn probleem zit 'm op dit moment in het inladen van nieuwe foto's terwijl een animatie op de vorige foto eventueel nog bezig is.
Dit in dezelfde thread doen als het renderen zorgt voor een vrij grote pauze van enkele seconden.
Ik heb dus geprobeerd om het laden in een 2de thread the doen. Op het eerste zicht leek dit vrij goed te gaan, maar er zijn nog 2 probleempjes aan.
Ten eerste loopt die thread soms vast, ik denk in de functie D3DXCreateTextureFromFileEx. Ik heb niet kunnen vinden of deze functies al dan niet thread-safe zijn, dus mogelijk is de reden hiervan dat tegelijkertijd de andere thread bezig was met het renderen.

Het tweede probleem is dat ondanks dat deze functie gebeurd in een andere thread, er na het laden alsnog een korte pauze optreed.
Door met MessageBox'en een aantal breaks te plaatsen, ben ik er achter gekomen dat deze pauze optreed op het moment dat de pauze optreed op het moment dat de nieuwe texture voor de eerste keer geselecteerd word om te tekenen.
Door naar het geheugengebruik van mijn programma te kijken, vond ik ook dat er nadat de texture geladen was vrij veel geheugen gebruikt werd, maar het moment daarna, wanneer de texture getekend werd het geheugengebruik sterk daalde.
Ik vermoed dus dat D3DXCreateTextureFromFileEx het bestand laad, decompresseert en de mipmap's aanmaakt in het gewone geheugen, en dat pas op het moment van het eerste gebruik van de texture verplaatst word naar het videogeheugen.
Ik heb al geprobeerd om ook dat eerste tekenen eens te doen in de 2de thread, maar daar leek het geen effect te hebben, en de pauze bleef dus zichtbaar.

Heeft iemand misschien een idee hoe ik dit zou kunnen oplossen?

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • NaliXL
  • Registratie: Maart 2002
  • Laatst online: 26-11 19:52
Is het misschien een optie om de laad-thread de afbeeldingen vast naar de schermresolutie te laten converteren, zodat er zo min mogelijk tijd wordt besteed aan het laden (in het videogeheugen)/verplaatsen van de texture?

Genoeg is meer dan veel, en tart den overvloed


  • BCC
  • Registratie: Juli 2000
  • Laatst online: 14:12

BCC

Hey grappig, dit heb ik een paar jaar geleden ook gebouwd :). Pas je de texture toe op hetzelfde object, of werk je met twee objecten?

Na betaling van een licentievergoeding van €1.000 verkrijgen bedrijven het recht om deze post te gebruiken voor het trainen van artificiële intelligentiesystemen.


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 12:58
Bedankt, ik was inderdaad al aan het denken dat ik hoe dan ook de eerste mip-map levels vaak niet nodig zou hebben, maar het leek op het eerste zicht niet zo eenvoudig om dit aan te passen.
Ik heb nu echter gevonden dat de breedte en hoogte die aan de D3DXCreateTextureFromFileEx functie meegegeven worden de gewenste texture-grootte is, en niet de grootte van het bronbestand hoeft te zijn.
Als ik hier 1600x1200 meegeef (wat momenteel op niet al te snelle pc's toch wel het maximum is dat je tegenkomt denk ik) gaat het inderdaad behoorlijk goed, en kon ik niet direct meer een hapering zien. (Op een Radeon X1400 mobile op batterij-stand 210 Mhz)
Het 'Peak Memory Usage' is ook gedaald van 136MB naar 56MB, dus dat scheelt ook al wel een heel deel.

Het enige probleem dat ik hiermee zie is dat vooraf de verhoudingen gekend moeten zijn zodat de juiste resolutie voor de texture berekend kan worden. Ik weet niet of hier functies voor bestaan, of dat ik zelf de jpeg header zal moeten inlezen?

Het tweede probleem dat ik had blijft overigens helaas ook nog bestaan. Heel af en toe lijkt het laden van een texture in een tweede thread dus vast te lopen.

De texture van 1 plaatje wordt momenteel op 2 driehoeken geplaatst, en er zijn dus in totaal 4 driehoeken voor de 2 plaatjes waartussen gefade moet worden. Ik denk dat dit het eenvoudigste is om nog veel vrijheid over te houden bij het maken van transities.

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • SWfreak
  • Registratie: Juni 2001
  • Niet online
Adion schreef op vrijdag 17 augustus 2007 @ 20:13:
Het enige probleem dat ik hiermee zie is dat vooraf de verhoudingen gekend moeten zijn zodat de juiste resolutie voor de texture berekend kan worden. Ik weet niet of hier functies voor bestaan, of dat ik zelf de jpeg header zal moeten inlezen?
Van MSDN:
Width
[in] Width in pixels. If this value is zero or D3DX_DEFAULT, the dimensions are taken from the file and rounded up to a power of two. If the device supports non-power of 2 textures and D3DX_DEFAULT_NONPOW2 is specified, the size will not be rounded.
Hetzelfde verhaal geldt voor de height-parameter.
Het tweede probleem dat ik had blijft overigens helaas ook nog bestaan. Heel af en toe lijkt het laden van een texture in een tweede thread dus vast te lopen.
DirectX 9 is default niet thread-safe! (D.w.z. dat alle bewerkingen op een IDirect3DDevice9 object niet thread-safe zijn. Aangezien D3DCreateTextureFromFileEx eigenlijk niet meer is dan een fancy wrapper om IDirect3DDevice9::CreateTexture, is D3DCreateTextureFromFileEx dus ook niet thread-safe.)
Je kunt hier op verschillende manieren om heen werken:
  • Bij het maken van je device D3DCREATE_MULTITHREADED als flag op te geven. Daarmee wordt DirectX thread-safe. Dit wordt over het algemeen echter afgeraden, omdat dit vertragend werkt, en vooral als je veel calls naar DX maakt is dit goed merkbaar.
  • In een aparte thread de file in het geheugen te laden en vervolgens in de hoofd-thread gebruik van de functie D3DXCreateTextureFromFileInMemoryEx
  • Het gewoon zonder aparte threads doen.
Over de performance:
Zoals je zelf al opmerkte, wat waarschijnlijk het meeste tijd kost is de omzetting van JPEG naar iets waar de videokaart wat mee kan. Alle D3DXCreateTexture... functies hebben hier tijd voor nodig. De enige manier om hier om heen te werken is denk ik om zelf de jpeg-decoding te doen, maar lijkt me wat overkill...

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 12:58
SWfreak schreef op zaterdag 18 augustus 2007 @ 17:30:
Van MSDN:
Width
[in] Width in pixels. If this value is zero or D3DX_DEFAULT, the dimensions are taken from the file and rounded up to a power of two. If the device supports non-power of 2 textures and D3DX_DEFAULT_NONPOW2 is specified, the size will not be rounded.
Dit is dus het probleem, ofwel neem je D3DX_DEFAULT of D3DX_DEFAULT_NONPOW2, in welk geval de texture zijn oorspronkelijke grootte behoud (wat dus voor een 6MP foto veel geheugen kost, en het aanmaken van de mipmap levels ook enorm vertraagt), ofwel kies je zelf een grootte die bij benadering zo groot is als je hem wil gebruiken (dus de schermresolutie).
De bronfoto's zullen echter niet altijd dezelfde aspect ratio hebben als je scherm, dus is het wel wenselijk om de juiste breedte/hoogte te berekenen om optimaal het scherm te vullen.

Ondertussen heb ik dit opgelost door zelf een functie te schrijven die het jpeg bestand inleest en uit de header de originele resolutie leest.
DirectX 9 is default niet thread-safe! (D.w.z. dat alle bewerkingen op een IDirect3DDevice9 object niet thread-safe zijn. Aangezien D3DCreateTextureFromFileEx eigenlijk niet meer is dan een fancy wrapper om IDirect3DDevice9::CreateTexture, is D3DCreateTextureFromFileEx dus ook niet thread-safe.)
Je kunt hier op verschillende manieren om heen werken:
  • Bij het maken van je device D3DCREATE_MULTITHREADED als flag op te geven. Daarmee wordt DirectX thread-safe. Dit wordt over het algemeen echter afgeraden, omdat dit vertragend werkt, en vooral als je veel calls naar DX maakt is dit goed merkbaar.
  • In een aparte thread de file in het geheugen te laden en vervolgens in de hoofd-thread gebruik van de functie D3DXCreateTextureFromFileInMemoryEx
  • Het gewoon zonder aparte threads doen.
Ok, ik zal hier eens verder naar zoeken dan. Die multithreaded flag zou misschien wel een oplossing kunnen zijn. Ten opzichte van een gemiddeld spel maak ik ontzettend weinig calls naar DX denk ik (slechts een paar driehoeken die een 30 keer per second herberekend moeten worden.

VirtualDJ 2024 - Fast Image Resizer - Instagram

Pagina: 1