参见Mesa3D的glsl的实现源码.
mesa\main\mtypes.h:
* Names of the various vertex/fragment program register files, etc.
*
* NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c)
* All values should fit in a 4-bit field.
*
* NOTE: PROGRAM_STATE_VAR, PROGRAM_CONSTANT, and PROGRAM_UNIFORM can all be
* considered to be "uniform" variables since they can only be set outside
* glBegin/End. They're also all stored in the same Parameters array.
*/
typedef enum
{
PROGRAM_TEMPORARY, /**< machine->Temporary[] */
PROGRAM_ARRAY, /**< Arrays & Matrixes */
PROGRAM_INPUT, /**< machine->Inputs[] */
PROGRAM_OUTPUT, /**< machine->Outputs[] */
PROGRAM_STATE_VAR, /**< gl_program->Parameters[] */
PROGRAM_CONSTANT, /**< gl_program->Parameters[] */
PROGRAM_UNIFORM, /**< gl_program->Parameters[] */
PROGRAM_WRITE_ONLY, /**< A dummy, write-only register */
PROGRAM_ADDRESS, /**< machine->AddressReg */
PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */
PROGRAM_SYSTEM_VALUE,/**< InstanceId, PrimitiveID, etc. */
PROGRAM_UNDEFINED, /**< Invalid/TBD value */
PROGRAM_IMMEDIATE, /**< Immediate value, used by TGSI */
PROGRAM_BUFFER, /**< for shader buffers, compile-time only */
PROGRAM_MEMORY, /**< for shared, global and local memory */
PROGRAM_IMAGE, /**< for shader images, compile-time only */
PROGRAM_FILE_MAX
} gl_register_file;
mesa\program\prog_execute.c:
/**
* Fetch the derivative with respect to X or Y for the given register.
* XXX this currently only works for fragment program input attribs.
*/
static void
fetch_vector4_deriv(struct gl_context * ctx,
const struct prog_src_register *source,
const struct gl_program_machine *machine,
char xOrY, GLfloat result[4])
{
if (source->File == PROGRAM_INPUT &&
source->Index < (GLint) machine->NumDeriv) {
const GLint col = machine->CurElement;
const GLfloat w = machine->Attribs[VARYING_SLOT_POS][col][3];
const GLfloat invQ = 1.0f / w;
GLfloat deriv[4];
if (xOrY == 'X') {
deriv[0] = machine->DerivX[source->Index][0] * invQ;
deriv[1] = machine->DerivX[source->Index][1] * invQ;
deriv[2] = machine->DerivX[source->Index][2] * invQ;
deriv[3] = machine->DerivX[source->Index][3] * invQ;
}
else {
deriv[0] = machine->DerivY[source->Index][0] * invQ;
deriv[1] = machine->DerivY[source->Index][1] * invQ;
deriv[2] = machine->DerivY[source->Index][2] * invQ;
deriv[3] = machine->DerivY[source->Index][3] * invQ;
}
result[0] = deriv[GET_SWZ(source->Swizzle, 0)];
result[1] = deriv[GET_SWZ(source->Swizzle, 1)];
result[2] = deriv[GET_SWZ(source->Swizzle, 2)];
result[3] = deriv[GET_SWZ(source->Swizzle, 3)];
if (source->Negate) {
assert(source->Negate == NEGATE_XYZW);
result[0] = -result[0];
result[1] = -result[1];
result[2] = -result[2];
result[3] = -result[3];
}
}
else {
ASSIGN_4V(result, 0.0, 0.0, 0.0, 0.0);
}
}
OK,一切自明! dFdx(p), dFdy(p) 传递的参数是寄存器标识。
精彩链接: http://www.aclockworkberry.com/shader-derivative-functions/