GLGETPROGRAMRESOURCE(3G)

πŸ’– NAME πŸ’–

Okay bestie, manual name is GLGETPROGRAMRESOURCE(3G) β€” and yes, the header has a lil [FIXME: manual] note chillin’ in it, we’re keeping that energy.

So what does glGetProgramResource do? It retrieves values for multiple properties of a single active resource within a program object. That’s the whole vibe. One resource, multiple properties, values retrieved. Slay.


✨ C SPECIFICATION ✨

Here’s the exact signature, character for character, no cap:

void glGetProgramResourceiv(GLuint program, GLenum programInterface,
                            GLuint index, GLsizei propCount,
                            const GLenum * props, GLsizei bufSize,
                            GLsizei * length, GLint * params);

πŸŽ€ PARAMETERS πŸŽ€

  • program β€” the name of a program object whose resources you’re querying. Like, which program are we snooping through? This one. πŸ’…
  • programInterface β€” a token identifying the interface within program containing the resource named name. So it tells you which interface inside the program has that resource. Iconic little token behavior. ✨

πŸ’… DESCRIPTION πŸ’…

ok so bestie, glGetProgramResourceiv is the girl who does the ✨most✨: she returns the values for multiple properties of one single active resource at a time. Like, one resource, many receipts. 🧾

Here's the vibe: there's this one resource, chilling at index index, inside the interface programInterface of the program object program. She goes in, and for that resource, she pulls out values for propCount properties β€” all of them listed out in the array props. πŸŽ€

🚨 Real talk: propCount may not be zero. Zero is not the vibe, and it will not be tolerated.

And she's picky in a very specific way β€” an error gets generated if:

  • any value in props is not one of the properties described immediately below, or
  • any value in props is not allowed for programInterface.

So which properties go with which interfaces? We got you, the whole chart is right here β€” every single one, no skips. 🌈

🌸 Property β†’ supported interfaces, the full guest list 🌸

  • GL_NAME_LENGTH β€” any interface except GL_ATOMIC_COUNTER_BUFFER and GL_TRANSFORM_FEEDBACK_BUFFER (they didn't get an invite, it's fine, it's fine 😭)
  • GL_TYPE β€” GL_UNIFORM, GL_PROGRAM_INPUT, GL_PROGRAM_OUTPUT, GL_TRANSFORM_FEEDBACK_VARYING, GL_BUFFER_VARIABLE
  • GL_ARRAY_SIZE β€” GL_UNIFORM, GL_BUFFER_VARIABLE, GL_PROGRAM_INPUT, GL_PROGRAM_OUTPUT, VERTEX_SUBROUTINE_UNIFORM, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_COMPUTE_SUBROUTINE_UNIFORM, GL_TRANSFORM_FEEDBACK_VARYING
  • GL_OFFSET β€” GL_UNIFORM, GL_BUFFER_VARIABLE, GL_TRANSFORM_FEEDBACK_VARYING
  • GL_BLOCK_INDEX β€” GL_UNIFORM, GL_BUFFER_VARIABLE
  • GL_ARRAY_STRIDE β€” GL_UNIFORM, GL_BUFFER_VARIABLE
  • GL_MATRIX_STRIDE β€” GL_UNIFORM, GL_BUFFER_VARIABLE
  • GL_IS_ROW_MAJOR β€” GL_UNIFORM, GL_BUFFER_VARIABLE
  • GL_ATOMIC_COUNTER_BUFFER_INDEX β€” GL_UNIFORM only, she's exclusive πŸ’…
  • GL_TEXTURE_BUFFER β€” none. Literally nobody. Empty guest list, party cancelled πŸ’€
  • GL_BUFFER_BINDING β€” GL_UNIFORM_BLOCK, GL_ATOMIC_COUNTER_BUFFER, GL_SHADER_STORAGE_BLOCK, GL_TRANSFORM_FEEDBACK_BUFFER
  • GL_BUFFER_DATA_SIZE β€” GL_UNIFORM_BLOCK, GL_ATOMIC_COUNTER_BUFFER, GL_SHADER_STORAGE_BLOCK
  • GL_NUM_ACTIVE_VARIABLES β€” GL_UNIFORM_BLOCK, GL_ATOMIC_COUNTER_BUFFER, GL_SHADER_STORAGE_BLOCK, GL_TRANSFORM_FEEDBACK_BUFFER
  • GL_ACTIVE_VARIABLES β€” GL_UNIFORM_BLOCK, GL_ATOMIC_COUNTER_BUFFER, GL_SHADER_STORAGE_BLOCK, GL_TRANSFORM_FEEDBACK_BUFFER

Like, memorize this table or keep it open in another tab, because if you roll up with a property that doesn't match your programInterface, it's giving error energy and you did that to yourself, ngl. πŸ™ˆ

  • GL_REFERENCED_BY_VERTEX_SHADER β€” works on GL_UNIFORM, GL_UNIFORM_BLOCK, GL_ATOMIC_COUNTER_SHADER, GL_BUFFER, GL_SHADER_STORAGE_BLOCK, GL_BUFFER_VARIABLE, GL_PROGRAM_INPUT, GL_PROGRAM_OUTPUT πŸ¦‹
  • GL_REFERENCED_BY_TESS_CONTROL_SHADER β€” same lil friend group: GL_UNIFORM, GL_UNIFORM_BLOCK, GL_ATOMIC_COUNTER_SHADER, GL_BUFFER, GL_SHADER_STORAGE_BLOCK, GL_BUFFER_VARIABLE, GL_PROGRAM_INPUT, GL_PROGRAM_OUTPUT ✨
  • GL_REFERENCED_BY_TESS_EVALUATION_SHADER β€” yep, identical list: GL_UNIFORM, GL_UNIFORM_BLOCK, GL_ATOMIC_COUNTER_SHADER, GL_BUFFER, GL_SHADER_STORAGE_BLOCK, GL_BUFFER_VARIABLE, GL_PROGRAM_INPUT, GL_PROGRAM_OUTPUT 🌸
  • GL_REFERENCED_BY_GEOMETRY_SHADER β€” bestie it's the same eight: GL_UNIFORM, GL_UNIFORM_BLOCK, GL_ATOMIC_COUNTER_SHADER, GL_BUFFER, GL_SHADER_STORAGE_BLOCK, GL_BUFFER_VARIABLE, GL_PROGRAM_INPUT, GL_PROGRAM_OUTPUT πŸ’œ
  • GL_REFERENCED_BY_FRAGMENT_SHADER β€” still the same crew: GL_UNIFORM, GL_UNIFORM_BLOCK, GL_ATOMIC_COUNTER_SHADER, GL_BUFFER, GL_SHADER_STORAGE_BLOCK, GL_BUFFER_VARIABLE, GL_PROGRAM_INPUT, GL_PROGRAM_OUTPUT πŸŽ€
  • GL_REFERENCED_BY_COMPUTE_SHADER β€” and the last of the six, same list again: GL_UNIFORM, GL_UNIFORM_BLOCK, GL_ATOMIC_COUNTER_SHADER, GL_BUFFER, GL_SHADER_STORAGE_BLOCK, GL_BUFFER_VARIABLE, GL_PROGRAM_INPUT, GL_PROGRAM_OUTPUT πŸ”₯
ok so quick vibe check on that whole block above πŸ‘† all six GL_REFERENCED_BY_* queries take the exact same set of interfaces. Lowkey iconic that they didn't change a single one, and no cap, it makes memorising them way easier.
  • GL_NUM_COMPATIBLE_SUBROUTINES β€” lives for the subroutine uniform types: GL_VERTEX_SUBROUTINE_UNIFORM, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_COMPUTE_SUBROUTINE_UNIFORM πŸ’…
  • GL_COMPATIBLE_SUBROUTINES β€” same set of subroutine uniforms, fr: GL_VERTEX_SUBROUTINE_UNIFORM, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_COMPUTE_SUBROUTINE_UNIFORM 🫢
  • GL_TOP_LEVEL_ARRAY_SIZE β€” this one is exclusive, only GL_BUFFER_VARIABLE gets it πŸ‘‘
  • GL_TOP_LEVEL_ARRAY_STRIDE β€” also GL_BUFFER_VARIABLE and nothing else ⭐
  • GL_LOCATION β€” big reach, valid on GL_UNIFORM, GL_PROGRAM_INPUT, GL_PROGRAM_OUTPUT, GL_VERTEX_SUBROUTINE_UNIFORM, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_COMPUTE_SUBROUTINE_UNIFORM 🌈
  • GL_LOCATION_INDEX β€” literally only GL_PROGRAM_OUTPUT, she's picky πŸ’€
  • GL_IS_PER_PATCH β€” applies to GL_PROGRAM_INPUT and GL_PROGRAM_OUTPUT 🧚
  • GL_LOCATION_COMPONENT β€” same two besties: GL_PROGRAM_INPUT and GL_PROGRAM_OUTPUT πŸ“

okay so picking up right where we left off with that table, bestie β€” here's the rest of it, exactly as it appears:

       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
       β”‚ GL_TRANSFORM_FEEDBACK_BUFFER_INDEX      β”‚ GL_TRANSFORM_FEEDBACK_VARYING                                                      β”‚
       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
       β”‚ GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE     β”‚ GL_TRANSFORM_FEEDBACK_BUFFER                                                       β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

now let's get into what each of these properties actually writes to params, because it's giving details and we love that for us:

  • GL_NAME_LENGTH β€” bestie, this writes a single integer to params that tells you the length of the name string for an active variable, interface block, or subroutine. And yes, that length includes the terminating null character, so don't forget it! πŸ’…
  • GL_TYPE β€” this one writes a single integer to params identifying the type of an active variable. The integer you get back is one of the values from table 2.16, no cap. ✨
  • GL_ARRAY_SIZE β€” writes a single integer to params telling you how many active array elements an active variable has. The array size is in units of the type from GL_TYPE. But if the active variable isn't an array of basic types, you get a big fat zero written to params. 🫢
  • GL_BLOCK_INDEX β€” writes a single integer to params with the index of the active interface block that contains the active variable. If the variable isn't a member of any interface block, you get -1 written to params. Simple as. πŸ’–
  • GL_OFFSET β€” writes a single integer to params identifying the offset of an active variable. Here's the tea:
    • For variables in the GL_UNIFORM and GL_BUFFER_VARIABLE interfaces that are backed by a buffer object, the value is the offset of that variable relative to the base of the buffer range holding its value.
    • For variables in the GL_TRANSFORM_FEEDBACK_VARYING interface, the value is the offset in the transform feedback buffer storage assigned to each vertex captured in transform feedback mode where the variable's value will be stored. These offsets are specified via the xfb_offset layout qualifier or assigned according to the variable's position in the list of strings passed to glTransformFeedbackVaryings(). Offsets are in basic machine units.
    • For all variables not recorded in transform feedback mode β€” including the special names "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2", "gl_SkipComponents3", and "gl_SkipComponents4" β€” -1 is written to params. 😭
  • GL_ARRAY_STRIDE β€” writes a single integer to params identifying the stride between array elements in an active variable. If the active variable is declared as an array of basic types, you get the difference, in basic machine units, between the offsets of consecutive elements in the array. If it's not declared as an array of basic types, zero goes to params. And if the active variable isn't backed by a buffer object, -1 goes to params no matter the variable type. Slay. πŸ’…
  • GL_MATRIX_STRIDE β€” writes a single integer to params identifying the stride between columns of a column-major matrix or rows of a row-major matrix. If the active variable is declared as a single matrix or an array of matrices, the value is the difference, in basic machine units, between the offsets of consecutive columns or rows in each matrix. If it's not a matrix or array of matrices, zero goes to params. And if it's not backed by a buffer object, -1 goes to params regardless of type. Iconic. ✨
  • GL_IS_ROW_MAJOR β€” writes a single integer to params that tells you if an active variable is a row-major matrix. If the variable is backed by a buffer object, declared as a single matrix or array of matrices, and stored in row-major order, you get a 1. For literally all other active variables, you get a 0. πŸŽ€
  • GL_ATOMIC_COUNTER_BUFFER_INDEX β€” writes a single integer to params with the index of the active atomic counter buffer containing the active variable. If the variable isn't an atomic counter uniform, you get -1 written to params. Bye. πŸ’€
  • GL_BUFFER_BINDING β€” writes the index of the buffer binding point associated with the active uniform block, shader storage block, atomic counter buffer, or transform feedback buffer to params. Got it? πŸ’–
  • GL_BUFFER_DATA_SIZE β€” writes the implementation-dependent minimum total buffer object size, in basic machine units, required to hold all active variables associated with an active uniform block, shader storage block, or atomic counter buffer to params. And if the final member of an active shader storage block is an array with no declared size, the minimum buffer size is computed assuming that array was declared with one element. No cap. πŸ¦‹
  • GL_NUM_ACTIVE_VARIABLES β€” writes the number of active variables associated with an active uniform block, shader storage block, atomic counter buffer, or transform feedback buffer to params. That's it, that's the tweet. 🐦
  • GL_ACTIVE_VARIABLES β€” writes an array of active variable indices associated with an active uniform block, shader storage block, atomic counter buffer, or transform feedback buffer to params. The number of values written to params for an active resource is exactly the value of GL_NUM_ACTIVE_VARIABLES for that resource. Periodt. πŸ‘‘
  • GL_REFERENCED_BY_VERTEX_SHADER, GL_REFERENCED_BY_TESS_CONTROL_SHADER, GL_REFERENCED_BY_TESS_EVALUATION_SHADER, GL_REFERENCED_BY_GEOMETRY_SHADER, GL_REFERENCED_BY_FRAGMENT_SHADER, and GL_REFERENCED_BY_COMPUTE_SHADER β€” for these, a single integer is written to params identifying whether the active resource is referenced by the vertex, tessellation control, tessellation evaluation, geometry, or fragment shaders, respectively, in the program object. A 1 is written if an active variable is referenced by the corresponding shader, or if an active uniform block, shader storage block, or atomic counter buffer contains at least one variable referenced by the corresponding shader. Otherwise, a 0 is written. (And yes, compute is in the list even though the sentence says fragment β€” the spec said what it said, bestie. πŸ’€)
  • GL_TOP_LEVEL_ARRAY_SIZE β€” writes a single integer to params identifying the number of active array elements of the top-level shader storage block member that contains the active variable. If the top-level block member isn't declared as an array, you get a 1. If it's an array with no declared size, you get a 0. Easy. 🌸
  • GL_TOP_LEVEL_ARRAY_STRIDE β€” writes a single integer to params identifying the stride between array elements of the top-level shader storage block member containing the active variable. If the top-level block member is declared as an array, the value is the difference, in basic machine units, between the offsets of the active variable for consecutive elements in the top-level array. If it's not declared as an array, zero goes to params. Slay. πŸ’…
  • GL_LOCATION β€” writes a single integer to params identifying the assigned location for an active uniform, input, output, or subroutine uniform variable. Here's the breakdown:
    • For input, output, or uniform variables with locations specified by a layout qualifier, the specified location is used.
    • For vertex shader input or fragment shader output variables without a layout qualifier, the location assigned when the program is linked is written to params.
    • For all other input and output variables, -1 is written.
    • For uniforms in uniform blocks, -1 is written. πŸ™ˆ
  • GL_LOCATION_INDEX β€” writes a single integer to params identifying the fragment color index of an active fragment shader output variable. If the active variable is an output for a non-fragment shader, you get -1 written to params. That's the tea. 🍡
  • GL_IS_PER_PATCH β€” writes a single integer to params telling you if the input or output is a per-patch attribute. If the active variable is a per-patch attribute (declared with the patch qualifier), you get a 1; otherwise, you get a 0. πŸ’–
  • GL_LOCATION_COMPONENT β€” writes a single integer to params indicating the first component of the location assigned to an active input or output variable. If the input or output variable has a component specified by a layout qualifier, that specified component is written. For all other input and output variables, zero is written. ✨
  • GL_TRANSFORM_FEEDBACK_BUFFER_INDEX β€” writes a single integer to params identifying the index of the active transform feedback buffer associated with an active variable. For variables corresponding to the special names "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2", "gl_SkipComponents3", and "gl_SkipComponents4", -1 is written to params. Bye bestie. πŸ’€
  • GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE β€” writes a single integer to params identifying the stride, in basic machine units, between consecutive vertices written to the transform feedback buffer. That's it. πŸŽ€

πŸ’€ ERRORS πŸ’€

okay so if you mess up, here's what the universe (and the spec) will throw at you:

  • GL_INVALID_VALUE is generated if program is not the name of an existing program object.
  • GL_INVALID_VALUE is generated if propCount is zero.
  • GL_INVALID_ENUM is generated if programInterface is not one of the accepted interface types.
  • GL_INVLALID_ENUM is generated if any value in props is not one of the accepted tokens for the interface programInterface. (Yes, that's a typo in the spec β€” GL_INVLALID_ENUM β€” we keep it real. πŸ’€)

✨ VERSION SUPPORT ✨

Okay bestie, here's the vibe check on when you can actually use this thing πŸ‘‘

  • glGetProgramResourceiv β€” not a thing in OpenGL 2.0, 2.1, 3.0, 3.1, 3.2, 3.3, 4.0, 4.1 or 4.2 (all of those are a big fat -, like, it simply did not exist yet πŸ’€)
  • glGetProgramResourceiv β€” fully slaying in OpenGL 4.3 βœ”
  • glGetProgramResourceiv β€” still iconic in OpenGL 4.4 βœ”
  • glGetProgramResourceiv β€” and living her best life in OpenGL 4.5 βœ”

So like, if you're on anything before 4.3, this function is not your main character, sorry babe 🫢


🌸 SEE ALSO 🌸

Go check out her besties, they're all part of the same friend group fr fr:

  • glGetProgramResourceName()
  • glGetProgramResourceIndex()
  • glGetProgramResourceLocation()
  • glGetProgramResourceLocationIndex()

Copyright Β© 2013-2014 Khronos Group. This material may be distributed subject to the terms and conditions set forth in the Open Publication License, v 1.0, 8 June 1999. http://opencontent.org/openpub/

Copyright Β© 2013-2014 Khronos Group

Yes bestie, the copyright section shows up twice in the original and I'm keeping both, because we do not skip details in this house πŸ’…

and that's a wrap, babes πŸŽ€ This little masterpiece is sourced from [FIXME: source] (yes, that's literally what it says, iconic placeholder energy 😭), it's dated 08/09/2021, and it lives at GLGETPROGRAMRESOURCE(3G) β€” go forth and query those program resources, queen πŸ‘‘βœ¨

πŸ“¦ where this page comes from