Mipmaping in the absense of fixed functionality

I am working on OpenGL 3.2 core implementation.
Mipmap level computation requires texture coordinate gradients. How to compute these gradients if we only have programmable pipeline (no fixed functionality) ?

Mipmap level computation requires texture coordinate gradients. How to compute these gradients if we only have programmable pipeline (no fixed functionality) ?

What do you mean by “no fixed functionality?” Texture filtering is very much still part of core OpenGL.

You don’t need to compute the specific mipmap levels yourself ever. The most you might need to do, due to having conditional branching before a texture access, is to compute the gradients to be used in the “textureGrad” functions. That requires use of the “dfdx” and “dfdy” GLSL functions.

Actually, we have started with OpenGL ES 2.0 implementation source code which needs to be upgraded to OpenGL 3.2 core.

He means how are the texture co-ordianate derivatives computed since a fragment shader decides the texture co-ordinate… in old GL fixed function pipeline with no dependent texture lookups, the derivatives could, in theory, be computed in the vertex stage.

The answer is this though, the fragment shader is executed on multiple fragments at the same time and the derivatives are computed by just difference with neighbor… this is also how dFdx() and dFdy() work too.

Mmm, this sounds a little complicated…

  1. execute fragment shader on 2 ([x,y] & [x+1, y+1]) or 4 ([x,y] & [x,y+1] & [x+1,y] & [x+1,y+1]) fragments in parallel.
  2. Synchronize at every texel lookup or dFdx() or dFdy() call - GLSL compiler needs to insert appropriate code for this?
  3. Compute gradients (GLSL compiler to generate code for this too?)
  4. Continue with execution of remainder of fragment shader

Is this how a typical implementation would work?

Is this how a typical implementation would work?

Yes and no.

On a CPU, you have a thread of execution. That thread has a set of registers associated with it and has a position within a sequence of instructions. The instructions operate on registers and can read from/write to main memory. CPUs can allow multiple concurrent threads of execution.

GPUs work that way, but slightly wierder.

The way the user thinks of, for example, a fragment shader is that each fragment generated by the rasterizer is processed separately. So if a triangle generates 12 fragments, you would expect 12 executions of the fragment shader, with each execution seemingly independent of each other.

Except that this would be a huge waste of resources.

Instead, what is commonly done is that groups of fragments are taken together. Each series of instructions operates, not on a single fragment at a time, but several. Conceptually, you can think of it as having really, really big registers. Instead of a vec4 register, what you have is a vec16 register, where each group of 4 floats within that register represents data from one fragment. The vec16 register stores the data for an entire 2x2 block.

That way, each 2x2 block of fragments uses the same instruction processor, instruction dispatchers, etc. They have different computational units, so nobody is waiting on anyone else. But each of the fragments executes the same instructions at the same time.

That is, neighboring fragments are always synchronized. Parallel execution of neighboring fragments executes in lock-step, so there’s no need to synchronize anything.

Though again, I want to know what you mean by “no fixed-function.” Mipmapping is still part of hardware; unless you are doing something special prevents you from using “texture” or other automatic mipmapping texture functions, you don’t need to compute gradients manually.

Well more specifically: since there is no glTexCoordPointer in OpenGL ES 2.0, how does the implementation know which gradients (gradients of the vertex attributes are available as a byproduct of rasterization) to use to compute the mipmap level that is used during texel lookup. Also, the fragment shader may decide to use some arbitrary values for the texture coordinates and not one of the varyings…

Texture mipmaping for fixed function pipeline is easier to implement as the texture coordinates that would be used for texel lookup are clearly known during rasterization (vertex stage).

For programmable pipeline, differencing with neighbors seems to be the only way for computing the gradients as kRogue pointed out.

Actually currently we are working to build a software implementation running on x86, hardware mapping to be done at a later stage.

since there is no glTexCoordPointer in OpenGL ES 2.0, how does the implementation know which gradients (gradients of the vertex attributes are available as a byproduct of rasterization) to use to compute the mipmap level that is used during texel lookup.

glTexCoordPointer had nothing to do with that to begin with. It never did.

Vertex attributes are not made available to the rasterizer; only vertex processing outputs are made available. Texture coordinates have always been subject to modification pre-rasterization, whether by texture matrices and/or automatic generation as in fixed-function OpenGL or by arbitrary vertex programs as in modern OpenGL.

As to exactly how an OpenGL implementation should calculate the mipmap levels to use in filtering, the OpenGL specification is quite clear on this process. If you’re writing an OpenGL implementation, I’d suggest you get very familiar with all parts of the spec, since it defines what you’re supposed to be doing.