Optimisation des textures¶
Ce document décrit les pratiques d'optimisation pour le stockage et l'upload des textures OpenGL.
Stockage immuable avec glTexStorage2D¶
L'utilisation de glTexStorage2D (OpenGL 4.2+) alloue la texture avec une taille et un format fixes, offrant plusieurs avantages over glTexImage2D :
// ✅ Stockage immuable — alloue tous les niveaux en une fois
glTexStorage2D(GL_TEXTURE_2D,
num_mip_levels, // 1 + floor(log2(max(width, height)))
GL_RGBA16F, // Format interne
width, height);
// ❌ Stockage mutable — alloue niveau par niveau, potentiellement re-alloué
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0,
GL_RGBA, GL_FLOAT, NULL);
Avantages du stockage immuable¶
- Performance pilote : L'allocation complète dès le début évite les réallocations internes
- Validation : Le pilote peut valider les formats et dimensions une seule fois
- Cohérence : Impossible de modifier accidentellement le format après allocation
- NVIDIA : Réduit les warnings de validation sur certains pilotes
Correction de l'alignement d'unpack¶
Par défaut, OpenGL suppose un alignement de 4 octets pour les lignes de texture. Pour les textures dont la largeur n'est pas un multiple de 4, cela cause des décalages :
// Vérifier si l'alignement par défaut (4) est correct
uint32_t row_bytes = width * channels; // ex: 3 canaux × largeur impair
if (row_bytes % 4 != 0) {
// Forcer l'alignement à 1 octet
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
upload_texture(...);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // Restaurer
}
Cas courants nécessitant l'alignement à 1 : - Textures RGB (3 canaux) de largeur impaire - Textures de glyphes de fontes (1 canal, largeur quelconque) - Données compressées non-alignées
Diagramme de layout mémoire¶
Texture 5×2 pixels, RGB (3 octets/pixel), alignement 4 :
Ligne 0 : [R G B] [R G B] [R G B] [R G B] [R G B] [PAD]
pixel0 pixel1 pixel2 pixel3 pixel4 (1 octet de padding)
Ligne 1 : [R G B] [R G B] [R G B] [R G B] [R G B] [PAD]
pixel5 pixel6 pixel7 pixel8 pixel9
14 octets + 1 padding = 15 → arrondi à 16 (multiple de 4)
Avec GL_UNPACK_ALIGNMENT = 1 :
Ligne 0 : [R G B] [R G B] ... [R G B] ← 15 octets, pas de padding
Ligne 1 : [R G B] [R G B] ... [R G B] ← 15 octets
Upload via PBO vs transfert direct¶
| Méthode | Latence | Cas d'usage |
|---|---|---|
Direct (glTexSubImage2D) |
Bloquant | Init unique, petites textures |
| PBO simple | Non bloquant | Uploads fréquents |
| PBO double tampon persistant | Non bloquant optimal | Textures HDR large, streaming |
Pour les textures HDR 4K, toujours utiliser le PBO double tampon persistant (voir async_pbo.md).
Formats recommandés¶
| Contenu | Format interne | Type source | Notes |
|---|---|---|---|
| HDR environment | GL_RGBA16F |
GL_HALF_FLOAT |
Après conversion SIMD |
| Albédo sRGB | GL_SRGB8_ALPHA8 |
GL_UNSIGNED_BYTE |
Conversion gamma auto |
| Normal map | GL_RGB8_SNORM |
GL_BYTE |
Signé pour les normales |
| Roughness/Metal | GL_RG8 |
GL_UNSIGNED_BYTE |
2 canaux suffisent |
| Depth buffer | GL_DEPTH_COMPONENT32F |
— | 32 bits pour la précision |
Voir aussi¶
- async_pbo.md — PBOs persistants double tampon
- simd_optimization.md — Conversion F32→F16 optimisée
- opengl_cleanup.md — Avertissements de format
0x20084