Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Further separation of sampler objects

  1. #1
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,182

    Further separation of sampler objects

    Right now in D3D I can do this:
    Code :
    // C++ code
    context->PSSetShaderResources (0, 1, &texture);
     
    // HLSL code
    SamplerState sampler0 : register(s0);
    SamplerState sampler1 : register(s1);
     
    Texture2D tex0 : register(t0);
     
    tex0.Sample (sampler0, ...);
    tex0.Sample (sampler1, ...);

    As in, bind the texture to the pipeline once and once only, taking up just a single texture unit, but sample it twice using different sampling parameters each time. This is useful for post-processing effects where you may have different "control" images in each colour channel of a single texture, and may wish one to be clamped but others to be wrapped, for example.

    In GL I can't; I need to bind the texture twice, to two separate texture units, owing to the way sampler objects use the same texture units as texture objects. This (1) is awkward, (2) burns an extra texture unit unnecessarily, and (3) not really reflective of the way hardware works.

    The solution is simple - define a separate set of "sampler units" using an API similar to glVertexAttribBinding - let's call it "glTextureSamplerBinding". Two GLuint params, one for the texture unit and one for the sampler unit to "bind" it to (not too happy about use of the word "bind" here - I'd prefer "attach", but precedent is set by glVertexAttribBinding so "bind" is at least consistent); a texture unit may be "bound" (attached) to more than one sampler unit, and the default is that each texture unit is "bound" (attached) to the same sampler unit as it's number (i.e. texture unit 0 "bound" (attached) to sampler unit 0 and so on).

  2. #2
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    not really reflective of the way hardware works.
    What evidence do you have that hardware works in this way?

  3. #3
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,182
    Quote Originally Posted by Alfonse Reinheart View Post
    What evidence do you have that hardware works in this way?
    http://www.x.org/docs/AMD/R6xx_R7xx_3D.pdf

    Page 14, section 3.6: "Texture Setup". Enough?

  4. #4
    Advanced Member Frequent Contributor
    Join Date
    Apr 2009
    Posts
    590
    I have learned my lesson from about UBO's.. if mhaigan says hardware works that way, at the very least AMD hardware does. What I don't follow is how the current GL API with bind a texture to a texture unit and set the uniform to what texture unit to sample from does not do exactly what is requested.. i.e:

    Code :
    glActiveTexture(Foo);
    glBindTexture(GL_TEXTURE_BAR, TexId);
    .
    .
    .
    glUniform(sampler0, Foo);
    glUniform(sampler1, Foo);

    Oh, wait me is dense.. you are wanting to decouple the sampler from the texture unit... smack head... so ideally a "texture unit" does not specify how to sample, just what to sample..... question is how to fit it into the current GL API... it is alreay inconsistent since it is called texture in C-code and sampler in GLSL... in a hacked way, there would be a new uniform call for samplers:

    Code :
    glSamplerUniform(GLuint location, GLuint textureUnit, GLuint samplerName);

    where it says the sampler at the named location uses the named textureUnit, but filtered through the named sampler.... or introduce new type to GLSL to get it right, but the naming will all be messed up.
    Last edited by kRogue; 09-18-2012 at 11:38 AM.

  5. #5
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    Quote Originally Posted by mhagain View Post
    http://www.x.org/docs/AMD/R6xx_R7xx_3D.pdf

    Page 14, section 3.6: "Texture Setup". Enough?
    OK, allow me to rephrase:

    "What evidence do you have that all hardware works in this way?"

    I'm not saying it doesn't. But you're not talking about an AMD extension here; you're talking about an OpenGL feature, which needs to run on a variety of hardware, AMD, NVIDIA, and Intel alike.

    Even if all relevant hardware (GL 3.x+) can support it, I'm just not seeing a burning need for exposing this ability of the hardware. So you save one or two texture units. You've got 16 per-stage to work with; it's not like you're going to run out. Is that really worth adding more ugliness and confusion to a part of the API that's already incredibly ugly and confused.

    Can you cite any performance advantages from this? Does each texture unit have a separate cache in some hardware, such that accessing the same texture through one unit won't necessarily get cache hits from accesses from the other unit? This isn't like ARB_vertex_attrib_binding, which likely offers real performance advantages. And that at least made the API prettier and less confusing (no more binding to `GL_ARRAY_BUFFER` followed by `glVertexAttribPointer`); I'm counting the days until I can rewrite the Vertex Specification page on the wiki to be in terms of vertex_attrib_binding (with an explanation after the fact of how `glVertexAttribPointer` works).

    Also, this feature as described seems to be missing half the point of the D3D equivalent. Namely, the ability to use different sampling parameters on textures from within the shader. That is, if we're going to have this feature, it ought to be done via shader logic, not external OpenGL calls. Just give shaders the ability to define samplers within them, then to use their pre-made samplers on textures arbitrarily.

  6. #6
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,182
    D3D doesn't have the ability to use different sampling parameters from within the shader; you're confusing HLSL with the Effects framework. The Effects framework is just a wrapper, the shader compiler will pull out those sampler states and just make standard API calls behind the scenes. D3D provides an Effect state filter object that you can hook up to an Effect and see it happening; you can see it happening in PIX; it happens. Besides, and even if emulated through the API, the capability isn't that great anyway. Look at GL_ARB_sampler_objects, issue 7:
    Separating samplers and texture images in the shader allows for a run-time combinatorial explosion of sampler- texture pairs that would be difficult to count.
    Anyone who's ever written D3D code using the Effects framework can vouch for the truth of this. Beyond simplistic techdemos and tutorials it's a nightmare to manage.

    On to the evidence. Here's the NVIDIA GTX280: http://www.bit-tech.net/hardware/gra...ture-review/11
    Each texture processing cluster inside the GT200 core has access to its own texture sampling unit, meaning there are ten texture samplers in a fully-functional GeForce GTX 280 graphics processing unit. These texture sampling units are able to address and also apply bilinear filtering to eight textures per clock; alternatively, each texture sampler can address and filter four 2:1 anisotropic filtered or four FP16 bilinear-filtered pixels per clock.
    And here's an NVIDIA patent discussing the difference between textures and samplers: http://www.freepatentsonline.com/7948495.html

    Again, it's clear that "textures" and "samplers" are different things. Which makes sense because a texture is just a big bunch of data, a sampler specifies how the texture is sampled.

    Does it add ugliness and confusion to the API? I argue no. It provides a cleaner and more sensible separation of data from state.
    Does it provide real performance advantages? Probably not, although it doesn't trash prior state on that second texture unit I mentioned so that's an (admittedly minor) advantage.
    Does it fix problems with the API? Hell, yes. By not recognizing the difference between textures and samplers, by not recognizing that there may be different numbers of each, it's possible to call glBindSampler (31, sampler) and possibly overflow a hardware limit.

  7. #7
    Advanced Member Frequent Contributor
    Join Date
    Dec 2007
    Location
    Hungary
    Posts
    985
    I would like to clarify a few misunderstanding:

    1. The number of hardware texture sampling units on a particular GPU has nothing to do with the number of texture units in OpenGL terminology. In this case, even though the GF 280 has only 10 texture sampling units it doesn't mean it has only 10 OpenGL texture units, it just defines the maximum texture sampling bandwidth of that GPU.
    2. D3D10 in fact supports 128 bound textures and 16 bound samplers and you can mix-and-match them, it's not an Effects framework specific thing. Both where hardware limitations of earlier GPU generations, I don't think that latest generation of GPUs have any such limitations.

    I think the fact that OpenGL doesn't have separate state for textures and samples, but all are tightly coupled into a so called "texture unit" has historical reasons. First, before D3D10 class hardware the texture and sampler state in fact was one common state. Why we don't have it now I think has to do with backwards compatibility as while in core OpenGL the texture unit is really only a pair of a texture object and a sampler object which could be trivial to separate, however in compatibility OpenGL the texture unit also has the so called texture environment state that affects both texture state and sampler state so it is almost impossible to separate texture and sampler state in OpenGL if one wants to maintain backwards compatibility.
    Disclaimer: This is my personal profile. Whatever I write here is my personal opinion and none of my statements or speculations are anyhow related to my employer and as such should not be treated as accurate or valid and in no case should those be considered to represent the opinions of my employer.
    Technical Blog: http://www.rastergrid.com/blog/

  8. #8
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    I don't see anything there that states that NVIDIA hardware has a division between hardware texture units and hardware sampler units. Indeed, it says quite the opposite: "Each texture processing cluster inside the GT200 core has access to its own texture sampling unit". Each texture unit has its own sampler.

    Just like OpenGL says.

    Also, note what Aqnuep said.

    Again, it's clear that "textures" and "samplers" are different things. Which makes sense because a texture is just a big bunch of data, a sampler specifies how the texture is sampled.

    Does it add ugliness and confusion to the API? I argue no. It provides a cleaner and more sensible separation of data from state.
    But we already have that separation of data from state now. We have texture objects and we have sampler objects. You combine them into a texture unit.

    What you're proposing is creating another layer of indirection, where a "texture unit" has a texture object and a reference to a sampler that is bound to an independent set of "sampler unit" bind points. That doesn't make the API less confusing.

    Does it fix problems with the API? Hell, yes. By not recognizing the difference between textures and samplers, by not recognizing that there may be different numbers of each, it's possible to call glBindSampler (31, sampler) and possibly overflow a hardware limit.
    It wouldn't help because you still need backwards compatibility with the way things are now. If you're using ARB_vertex_attrib_binding as a reference, note that it specifically states that there are (at least) 16 formats and 16 buffer binding points. Thus, it can redefine glVertexAttribPointer entirely in terms of the new API.

    Right now, texture units have textures and samplers. If you create this indirection, where the number of available sampler units can be less than the number of texture units, then you don't have the ability to redefine glBindSampler in terms of the new API.

  9. #9
    Advanced Member Frequent Contributor
    Join Date
    Apr 2009
    Posts
    590
    Right now, texture units have textures and samplers. If you create this indirection, where the number of available sampler units can be less than the number of texture units, then you don't have the ability to redefine glBindSampler in terms of the new API.
    Um.. not true at all... you can create a level of indirection as follows, tweaking the above I did:

    Code :
    /*
     Bind the samplerObject named samplerName to the samplerUnit, the value of
     samplerUnit must be in the range [0, numberSamplerUnits)
    */
    glBindSampler(uint samplerUnit, uint samplerName);
     
    /*
     Set the sampler uniform to use the texture at the named texture unit
     but to sample from the named sampler unit
    */
    glUniformSampler(uint uniformLocation, uint textureUnit, uint samplerUnit);

    There is a hitch in that since texture units implicitly consume a sampler unit the above is a little icky-ish in that sampler units is the number of hardware sampler units minus the number texture units reported by GL...

  10. #10
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    There is a hitch in that since texture units implicitly consume a sampler unit the above is a little icky-ish in that sampler units is the number of hardware sampler units minus the number texture units reported by GL...
    Yeah, that "hitch" is what makes it not backwards compatible.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •