
Prise en charge des Texture Views dans l’API bas niveau
Dans cette release d’Evergine, nous avons introduit les Texture Views comme concept à part entière de l’API graphique bas niveau. Les Texture Views vous permettent de référencer des sous-plages d’une texture, de réinterpréter les formats de pixels et de changer le type de vue, le tout sans créer de copies ni allouer de mémoire GPU supplémentaire. Cette fonctionnalité aligne Evergine sur les API graphiques modernes et supprime les copies de textures inutiles qui pénalisaient auparavant les performances.
Qu’est-ce qu’une Texture View ?
Sur le GPU, une texture peut prendre de nombreuses formes : 1D, 2D, 3D, cube maps, tableaux et combinaisons de ceux-ci. Les API graphiques modernes comme DirectX 12, Vulkan, Metal et WebGPU ne permettent pas de lier directement une texture au pipeline de rendu. Elles exigent à la place une Texture View, un objet qui décrit comment le GPU doit interpréter les données de la texture.
Une Texture View ne contient aucune donnée propre. Elle référence une texture existante et fournit le prisme à travers lequel le GPU lit ou écrit ces données. Vous pouvez la voir comme une fenêtre sur une texture : elle peut montrer la texture entière ou seulement une partie, et même présenter les données dans un format ou une structure différents de l’original.

Principales capacités
Les Texture Views d’Evergine offrent quatre capacités principales :
Sélection de sous-plages
Vous pouvez sélectionner un sous-ensemble de niveaux de mip et de couches d’une texture. Ce choix est contrôlé par quatre paramètres : baseMip, mipCount, baseLayer et layerCount.
Imaginez par exemple que vous disposiez d’une Texture2DArray de 18 couches représentant les shadow maps de 3 point lights (6 faces de cube chacune). Vous pouvez créer des Texture Views individuelles qui référencent les couches 0–5, 6–11 et 12–17, ce qui donne à chaque lumière sa propre vue cube map sans dupliquer aucune donnée.
Réinterprétation de format
Les Texture Views peuvent présenter les mêmes données avec un format de pixel différent, à condition que les formats soient compatibles. Par exemple, une texture stockée en R8G8B8A8_UNorm peut être vue en R8G8B8A8_UNorm_SRgb pour appliquer une correction gamma. De même, un depth buffer stocké en D32_Float peut être vu en R32_Float afin qu’un compute shader puisse le lire comme une valeur float classique.
Changement de type de vue
Une Texture View peut modifier la manière dont le GPU interprète la structure de la texture. Une Texture2DArray de exactement 6 couches peut être vue comme une TextureCube, ce qui permet aux shaders de l’échantillonner avec des coordonnées de cube map. C’est particulièrement utile pour les techniques de rendu basées sur des cubes, comme les shadow maps de point lights ou les environment probes.
Double binding
Avec les Texture Views, vous pouvez créer à la fois une Shader Resource View (pour la lecture) et une Unordered Access View (pour l’écriture) à partir de la même texture. Un compute shader peut ainsi écrire dans une texture et un pixel shader la lire sans créer de copie intermédiaire.
Le problème avant les Texture Views
Avant l’introduction des Texture Views, Evergine créait chaque texture avec un type de vue fixe. Dans DirectX 11, par exemple, une texture était liée soit en tant que Shader Resource View, soit en tant qu’Unordered Access View lors de sa création, et ce choix ne pouvait plus être modifié par la suite.
Cette limitation empêchait d’utiliser une même texture à la fois en entrée et en sortie. Si un compute shader devait écrire dans une texture et qu’un pixel shader devait ensuite la lire, le moteur devait maintenir deux textures distinctes et effectuer une copie GPU entre elles. Cela doublait la consommation mémoire et consommait de la bande passante GPU à chaque opération de copie.
Le pipeline de post-traitement était particulièrement touché : chaque effet de la chaîne nécessitait ses propres textures intermédiaires et opérations de copie, ce qui représentait une surcharge importante dans les scènes complexes.

Utilisation des Texture Views dans Evergine
Avec cette release, nous avons déjà appliqué les Texture Views en interne dans trois domaines clés du moteur :
Pipeline de post-traitement
Chaque effet de post-traitement crée désormais une Texture View au format approprié sur sa texture d’entrée. Grâce à la réinterprétation de format (via ToColorFormat()), le pipeline élimine les copies intermédiaires qui étaient auparavant nécessaires entre les nœuds de traitement.
Tone mapping
La passe de tone mapping nécessitait auparavant une copie complète de la texture avant de pouvoir lire l’entrée HDR. Avec les Texture Views, la même texture est désormais référencée directement avec un format compatible, ce qui supprime entièrement la copie.
Compute Depth Bounds
Ce compute shader calcule les valeurs de profondeur minimale et maximale d’une frame afin d’ajuster dynamiquement les plans near et far de la caméra, ce qui préserve la précision de profondeur. Il doit lire le depth buffer, mais les formats de profondeur ne peuvent pas être échantillonnés directement comme des données de couleur. Une Texture View réinterprète le format afin que le compute shader puisse le lire.
Utiliser les Texture Views dans l’API bas niveau
Créer une Texture View dans Evergine est simple. La méthode Factory.CreateTextureView accepte la texture source ainsi que des paramètres optionnels pour personnaliser la vue :
TextureView CreateTextureView(
Texture texture,
PixelFormat pixelFormat = PixelFormat.Unknown,
uint baseMip = 0,
uint mipCount = uint.MaxValue,
uint baseLayer = 0,
uint layerCount = uint.MaxValue,
TextureType? viewType = null);Voici trois exemples pratiques :
Créer une vue CubeMap à partir d’un tableau 2D de 6 couches
// facesTexture is a Texture2DArray with ArraySize = 6
var cubeView = gfxFactory.CreateTextureView(facesTexture, viewType: TextureType.TextureCube);Créer une vue de stockage sans gamma pour l’écriture par un compute shader
Les UAV ne prennent pas en charge les formats sRGB :
var facesTextureDesc = new TextureDescription
{
Type = TextureType.Texture2DArray,
Format = PixelFormat.R8G8B8A8_UNorm_SRgb,
Width = 1024,
Height = 1024,
ArraySize = 6,
Flags = TextureFlags.ShaderResource | TextureFlags.UnorderedAccess,
};
var facesTexture = graphicsContext.Factory.CreateTexture(ref facesTextureDesc, "Faces");
// Remove gamma for UAV compatibility
var storeView = graphicsContext.Factory.CreateTextureView(
facesTexture, pixelFormat: facesTextureDesc.Format.WithoutGamma());Réinterpréter un depth buffer pour la lecture par un compute shader
var depthView = graphicsContext.Factory.CreateTextureView(
depthTexture, pixelFormat: PixelFormat.R32_Float);Les Texture Views sont implémentées sur tous les backends de rendu : DirectX 11, DirectX 12, Vulkan, Metal, WebGPU et OpenGL.
Et ensuite ?
Cette release pose les bases des Texture Views dans Evergine. Dans les prochaines releases, nous prévoyons d’étendre leur utilisation à d’autres parties du moteur.
D’autres étapes du pipeline de rendu adopteront les Texture Views pour supprimer les copies intermédiaires partout où c’est possible.
Nous prévoyons également d’exposer plus largement les Texture Views dans l’API de haut niveau, afin que les développeurs puissent plus facilement tirer parti de cette fonctionnalité dans leurs propres projets sans travailler directement avec la couche bas niveau.
Conclusion
Les Texture Views sont un concept fondamental des API graphiques modernes, et Evergine les prend désormais entièrement en charge. Elles éliminent les copies de textures inutiles, réduisent la consommation de mémoire GPU et permettent une réinterprétation flexible des données sans allouer de ressources supplémentaires. Le pipeline de post-traitement, le tone mapping et le calcul des depth bounds bénéficient déjà de cette fonctionnalité, et d’autres systèmes du moteur suivront dans les prochaines releases.
Daniel Cáceres Maña – Senior Researcher
