Separate sampler state from texture state

An oft requested feature since OpenGL 2.1. Right now, OpenGL treats sampler state as part of the texture object. This is not how the hardware works and makes specific algorithms inefficient (those that require different sampling states for the same texture).

Potential API:


// Preferred
glSamplerParameter(GL_SAMPLER0, GL_SAMPLER_MAG_FILTER, ...);
glSamplerTexture(GL_SAMPLER0, tex_id);
glGetSamplerParameter(GL_SAMPLER0, ...);

// following current bind-to-edit semantics (worse):
glBindSampler(GL_SAMPLER0);
glSamplerParameter(...);
glSamplerTexture(tex_id);
glGetSamplerParamater(GL_SAMPLER_MAG_FILTER, ...);
glBindSampler(0);

Alternatively, replace Sampler by TexUnit and SAMPLERi by the existing TEXTURE_UNITi tokens:


// Following current OpenGL naming conventions:
glTexUnitParameter(GL_TEXTURE_UNIT0, GL_TEXTURE_MAG_FILTER, ...);
glTexUnitTexture(GL_TEXTURE_UNIT0, tex_id);
glGetTexUnitParameter(GL_TEXTURE_UNIT0, ...);

glActiveTexture and glTexParameter tokens that set sampler state will be deprecated.

Backwards compatibility can be maintained:

  1. using a new version profile
  2. specifying that glTexParameter will be ignored when the relevant texture is bound to a sampler with glSamplerTexture. Old applications (using glActiveTexture) will continue to use glTexParameter and ignore glSamplerParameter.

Questions:

  1. “Sampler” or “TexUnit”? My personal preference is the latter, as it follows existing OpenGL naming conventions.

  2. Use bind-to-edit semantics? ActiveTexture is not bind-to-edit, so it would be best to define the new API to not use bind-to-edit.

  3. “TexUnitTexture” function - the name is ugly. We could reuse the ActiveTexture entry point but this is going to be nasty both for driver developers and users (backwards compatibility).

Other thoughts, questions, ideas? Any chance we will see something like this in OpenGL 3.3?

This sounds reasonable.
glSamplerParameter(GL_SAMPLER0, GL_SAMPLER_MAG_FILTER, …);

  1. The name should be very different. This is a good thing.
  2. no more bind to edit in the next API revision
  3. or TextureImageUnit but Sampler sounds simpler.
  4. What is the risk of this becoming obsolete? Will samplers become programmable one day? Will we have to do this instead one day?
    loc=glGetUniformLocation(program, “MagFilter”);
    glUseProgram(X);
    glUniform(loc, GL_LINEAR);

You should just need these 2 functions (plus some matching Get functions):

glUniformSamplerParameter{i,f,…}(GLint location, GLenum parameter, {GLint,GLfloat,…} value);

glUniformSamplerTexture(GLint location, GLint texture);

(where location is the result from glGetUniformLocation)

They’ve got ugly names, but they get the job done.

Regards
elFarto

Why not put these in the shader? Or at least optionally have these parameters be defined in the shader (external setting of params before link would override them)?

This has been suggested before and met furious resistance by both IHVs and users… so no, defining sampler state in the shader is probably not an option. :slight_smile:

If you are going to separate sampler state from textures, then there should be sampler objects that encapsulate that state. That way, you only need one function to set the sampler state on a uniform.

“This has been suggested before and met furious resistance by both IHVs and users…”

What? I have never seen any IHV make a comment about that, at all, and i have not seen any user complain about the idea. I myself have suggested it several times and no one ever complained.

If there is any in/official statement from the ARB or an IHV about it, i would like to see.

Jan.

Have to agree. The original LP designs called for an (immutable) object along these lines, no? If you’re going to change things - and we now have a deprecation mechanism in place to facilitate the emergence of new approaches - why not head in the general LP direction. Seems to me it’s not too late to climb that peak (or the twin peaks of Kilimanjaro :-))…

I don’t recall the name but I distinctly remember a member of the ARB saying that this feature was discussed and turned down. I’ll post a link if I find the relevant statements.

Edit: either my search-fu or the search function of this forum sucks. No matter what keywords I specify, it returns about every single post from the “suggestions” and “items of importance” forums…

Yeah, the search sucks, had the same problem several times. That is why i didn’t even bother to search about this myself :wink:

Jan.

i think the thread starters suggestion is very cumbersome. why should i attach the sampler state to a texture before the use in the shader? this way it makes no sense to me to separate these states. just create a sampler state objects (i would like it in the shader too) and bind it to a uniform. then in the shader decide what sampler state to use and do something like this:


vec4 c = texture(_sampler, _sampler_state, tex_coord);

whats the harm? flexibility!

i am thinking about something like volume rendering pre- and post classification based on the _sampler_state uniform etc…

A clean separation of objects would be nice - a separation that allows for a flexible mix & match configuration from within the shader rather than at the outermost API level.

Would also mirror the way things work in dx10 and I’d consider that a bonus going forward.

just create a sampler state objects (i would like it in the shader too) and bind it to a uniform. then in the shader decide what sampler state to use and do something like this:

Whatever we suggest must be GL 3.x hardware compatible. So having the shader decide how to combine sampler state and textures is not allowed. The shader can statically associate sampler state, as this can just internally be implemented as a default sampler state object. But the ability to arbitrarily combine textures and sampler state in GLSL itself may not be feasible on 3.x hardware.

All we really need is the ability to have sampler state objects and to bind them to sampler uniforms. There is no need to complicate this by having a separation of sampler states and texture bind points in the actual shader.

Well, DX10 supports it, so it would be reasonable to assume that there is hw support for it…

Well, DX10 supports it, so it would be reasonable to assume that there is hw support for it…

I am not familiar with DX10, can you please give an example of how this works?

For example, can you change the sampler state inside a branch?


vec4 texel;
if (condition)
    texel = tex2d(texture, coordinates, sampler_state_foo);
else
    texel = tex2d(texture, coordinates, sampler_state_bar);

(Frankly, I cannot see how this could work on the hardware level).

All we really need is the ability to have sampler state objects and to bind them to sampler uniforms. There is no need to complicate this by having a separation of sampler states and texture bind points in the actual shader.

Absolutely agreed!

Yes you can. The actual syntax for a sample operation is:

DXGI_FORMAT Object.Sample( sampler_state S, floatx Location [, int Offset]);

You can combine every sampler state object with every texture object that is defined as a shader variable.

On the hardware level this is pretty easy to do. As hardware supports more logical textures and sampler states as there are physical units the shader code needs to tell this units what logical entity should be used. If you want to separate textures and samplers you need to move two logical ids instead of one.

I’m sorry to say that but I think that you just propose some syntax sugar …

The purpose of separated image and sampler is more flexibility and probably removing the MAX_TEXTURE < 32 limitation. It would allows to use several samplers per image or several images per sampler.

I’m personally imagine a “sampler object”, binds like uniforms replacing glUniformi … No more TexUnit concept.

Wait, doesn’t the slew of texture-lookup GLSL functions already provide in-shader selectable filtering? texture() vs textureLod() vs texelFetch() . Or if you mean to provide a user-modifiable anisotropic-filtering value for a large range of textures, can’t you just keep a vector of those textures and set the param accordingly.

I agree 100%. The code in the OP was just meant as a starting point for the discussion.

Yes you can, but this workaround wastes texture memory and is far from ideal. Why copy texture data just to change sampling modes?

As an alternative, if sampler objects are just too different for OpenGL, you could have the ability to build a texture object from another texture object. They would share certain information (the texture data itself, internal format, etc), but they would have their own instance data (sampler state).

Wait, doesn’t the slew of texture-lookup GLSL functions already provide in-shader selectable filtering? texture() vs textureLod() vs texelFetch()

These do not change the filtering alone. These are different functions with different behaviors. For example, texelFetch expects the texture coordinates to be integer pixel values, not normalized floating-point.