Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are array textures related to sampler arrays?

OpenGL has array textures, denoted in shaders by specific sampler types:

sampler2DArray array_texture;

But GLSL also allows samplers to be aggregated into arrays:

sampler2D array_of_textures[10];

Are these two features related to each other? How are they different?

like image 462
Nicol Bolas Avatar asked Feb 04 '23 01:02

Nicol Bolas


1 Answers

Let's understand the distinction by analogy. Samplers in GLSL are like pointers in C++; they reference some other object of a given type. So consider the following C++ code:

int*                 pi;
std::array<int, 5>*  pai;
std::array<int*, 5>  api;

pi is a pointer to a single object of type int (let's ignore the fact that technically it could be a pointer to an array of ints).

pai is also a pointer. But it doesn't point to an int; it points to an array of ints. That "array of ints" is a single object, with a single contiguous allocation of storage.

api is not a pointer; it is an array. Specifically, it is an array of pointers to ints. Each individual pointer can point to individual int objects. Each individual pointer is independent from the rest, and the objects they point to are completely unrelated, save for the fact that they all must be ints.

What does this have to do with OpenGL and textures?

  • pi is like sampler2D.
  • pai is like sampler2DArray: a single pointer/sampler which references multiple int/2D textures that all reside in a single object.
  • api is like a sampler2D[]: a single name which represents multiple pointers/samplers, each of which is independently bound, referencing objects that are unrelated save for the fact that they all must be int/sampler2Ds.

An array texture is a distinct construct from a non-array texture. Array textures have a special texture target. Accessing array textures in GLSL requires explicitly using a distinct sampler type that matches the target. Texture accessing functions that take array textures take an extra texture coordinate component, providing the array layer to be accessed. When you assign a texture to an array texture sampler, you are assigning a single texture object, with whatever number of array layers it was created with.

By contrast, a sampler array is simply a compile-time sized collection of multiple independent samplers grouped under one name. Textures are assigned to locations in the array independently, with any texture of the appropriate type being able to be used. Each element of the array takes up a additional binding point.

The biggest difference besides resource consumption is this: you can pick a sampler from the array using a runtime index (in OpenGL 4.x; in pre-4.x, you had to use a compile-time constant. So sampler arrays were basically useless).

But not an arbitrary runtime index. You can only use an index which is a dynamically uniform expression. That is, for all invocations in the drawing command, each invocation that executes that instruction must result in the same index.

Array textures have no such indexing limitations; the array index you provide them in texture fetching commands can be any runtime value (within the array, of course).

But array textures do have other limitations. Every "texture" in an array texture has the same size; so if you create a 512x512x20 2D array texture, each sub-texture is 512x512. For sampler arrays, the size of each texture in the array can vary. Of course, the fact that each sampler array index takes up a binding point is also important; you only have 16 of those per-stage (though possibly more; 16 is the minimum requirement).

like image 145
Nicol Bolas Avatar answered Mar 06 '23 04:03

Nicol Bolas