blob: 6190dd53db64a5a52c82d257902622f8aa70ec99 [file] [log] [blame]
Name
ARB_shader_subroutine
Name Strings
GL_ARB_shader_subroutine
Contact
Jeff Bolz, NVIDIA Corporation (jbolz 'at' nvidia.com)
Contributors
Barthold Lichtenbelt, NVIDIA
Bill Licea-Kane, AMD
Bruce Merry, ARM
Eric Werness, NVIDIA
Graham Sellers, AMD
Greg Roth, NVIDIA
Nick Haemel, AMD
Pat Brown, NVIDIA
Pierre Boudier, AMD
Piers Daniell, NVIDIA
Notice
Copyright (c) 2010-2014 The Khronos Group Inc. Copyright terms at
http://www.khronos.org/registry/speccopyright.html
Specification Update Policy
Khronos-approved extension specifications are updated in response to
issues and bugs prioritized by the Khronos OpenGL Working Group. For
extensions which have been promoted to a core Specification, fixes will
first appear in the latest version of that core Specification, and will
eventually be backported to the extension document. This policy is
described in more detail at
https://www.khronos.org/registry/OpenGL/docs/update_policy.php
Status
Complete. Approved by the ARB at the 2010/01/22 F2F meeting.
Approved by the Khronos Board of Promoters on March 10, 2010.
Version
Last Modified Date: 02/28/2014
Revision: 19
Number
ARB Extension #90
Dependencies
This extension is written against the OpenGL 3.2 core specification and
version 1.50 of the GLSL specification.
ARB_gpu_shader5 is required.
This extension interacts with NV_gpu_program5.
This extension interacts trivially with EXT_separate_shader_objects.
Overview
This extension adds support to shaders for "indirect subroutine calls",
where a single shader can include many subroutines and dynamically select
through the API which subroutine is called from each call site.
Switching subroutines dynamically in this fashion can avoid the cost of
recompiling and managing multiple shaders, while still retaining most of
the performance of specialized shaders.
IP Status
No known IP claims.
New Procedures and Functions
int GetSubroutineUniformLocation(uint program, enum shadertype,
const char *name);
uint GetSubroutineIndex(uint program, enum shadertype,
const char *name);
void GetActiveSubroutineUniformiv(uint program, enum shadertype,
uint index, enum pname, int *values);
void GetActiveSubroutineUniformName(uint program, enum shadertype,
uint index, sizei bufsize,
sizei *length, char *name);
void GetActiveSubroutineName(uint program, enum shadertype, uint index,
sizei bufsize, sizei *length, char *name);
void UniformSubroutinesuiv(enum shadertype, sizei count,
const uint *indices);
void GetUniformSubroutineuiv(enum shadertype, int location,
uint *params);
void GetProgramStageiv(uint program, enum shadertype,
enum pname, int *values);
New Tokens
Accepted by the <pname> parameter of GetProgramStageiv:
ACTIVE_SUBROUTINES 0x8DE5
ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
GetFloatv, GetDoublev, and GetInteger64v:
MAX_SUBROUTINES 0x8DE7
MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
Accepted by the <pname> parameter of GetActiveSubroutineUniformiv:
NUM_COMPATIBLE_SUBROUTINES 0x8E4A
COMPATIBLE_SUBROUTINES 0x8E4B
UNIFORM_SIZE
UNIFORM_NAME_LENGTH
Additions to Chapter 2 of the OpenGL 3.2 Specification (OpenGL Operation)
Add a section "Subroutine Uniform Variables" after Section 2.11.4,
"Uniform Variables"
Subroutine uniform variables are similar to uniform variables, except they
are context state rather than program state. Having subroutine uniforms be
context state allows them to have different values if the program is used
in multiple contexts simultaneously. There is a set of subroutine
uniforms for each shader stage.
The command
int GetSubroutineUniformLocation(uint program, enum shadertype,
const char *name);
will return the location of the subroutine uniform variable <name> in the
shader stage of type <shadertype> attached to <program>, with behavior otherwise
identical to GetUniformLocation. The value -1 will be returned if <name>
is not the name of an active subroutine uniform. Active subroutine
locations are assigned using consecutive integers in the range from zero
to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS minus one for the shader
stage. There is an implementation-dependent limit on the number of active
subroutine uniform locations in each shader stage; a program will fail to
link if the number of subroutine uniform locations required is greater
than the value of MAX_SUBROUTINE_UNIFORM_LOCATIONS. If <program> has not
been successfully linked, the error INVALID_OPERATION will be generated.
For active subroutine uniforms declared as arrays, the declared array
elements are assigned consecutive locations.
Each function in a shader associated with a subroutine type is considered
an active subroutine, unless the compiler conclusively determines that the
function could never be assigned to an active subroutine uniform. Each
active subroutine will be assigned an unsigned integer subroutine index
that is unique to the shader stage. This index can be queried with the
command
uint GetSubroutineIndex(uint program, enum shadertype,
const char *name);
where <name> is the null-terminated name of a function in the shader stage
of type <shadertype> attached to <program>. Subroutine indices are assigned using
consecutive integers in the range from zero to the value of
ACTIVE_SUBROUTINES minus one for the shader stage. The value INVALID_INDEX will
be returned if <name> is not the name of an active subroutine in the
shader stage. After the program has been linked, the subroutine index
will not change unless the program is re-linked.
There is an implementation-dependent limit on the number of active
subroutines in each shader stage; a program will fail to link if the
number of subroutines is greater than the maximum subroutine count
(the value of MAX_SUBROUTINES).
Information about active subroutine uniforms can be obtained by calling
void GetActiveSubroutineUniformiv(uint program, enum shadertype,
uint index, enum pname, int *values);
void GetActiveSubroutineUniformName(uint program, enum shadertype,
uint index, sizei bufsize,
sizei *length, char *name);
<program> and <shadertype> specify the program and shader stage. <index>
must be an active subroutine uniform index in the range from zero to the
value of ACTIVE_SUBROUTINE_UNIFORMS minus one for the shader stage. If <index>
is greater than or equal to the value of ACTIVE_SUBROUTINE_UNIFORMS, the
error INVALID_VALUE is generated.
For GetActiveSubroutineUniformiv, <pname> identifies a property of the
active subroutine uniform being queried. If <pname> is
NUM_COMPATIBLE_SUBROUTINES, a single integer indicating the number of
subroutines that can be assigned to the uniform is returned in <values>.
If <pname> is COMPATIBLE_SUBROUTINES, an array of integers is returned in
<values>, with each integer specifying the index of an active subroutine
that can be assigned to the selected subroutine uniform. The number of
integers returned is the same as the value returned for
NUM_COMPATIBLE_SUBROUTINES. If <pname> is UNIFORM_SIZE, a single integer
is returned in <values>. If the selected subroutine uniform is an array,
the declared size of the array is returned; otherwise, one is returned.
If <pname> is UNIFORM_NAME_LENGTH, a single integer specifying the length
of the subroutine uniform name (including the terminating null character)
is returned in <values>.
For GetActiveSubroutineUniformName, the uniform name is returned as a
null-terminated string in <name>. The actual number of characters written
into <name>, excluding the null terminator is returned in <length>. If
<length> is NULL, no length is returned. The maximum number of characters
that may be written into <name>, including the null terminator, is
specified by <bufsize>. The length of the longest subroutine uniform name
in <program> and <shadertype> is given by the value of
ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH, which can be queried with
GetProgramStageiv.
The name of an active subroutine can be queried given its subroutine
index with the command:
void GetActiveSubroutineName(uint program, enum shadertype,
uint index, sizei bufsize,
sizei *length, char *name);
<program> and <shadertype> specify the program and shader stage. <index>
must be an active subroutine index in the range from zero to the value of
ACTIVE_SUBROUTINES minus one for the shader stage. If <index> is greater than
or equal to the value of ACTIVE_SUBROUTINES, the error INVALID_VALUE is
generated. The name of the selected subroutine is returned as a
null-terminated string in <name>. The actual number of characters written
into <name>, excluding the null terminator, is returned in <length>. If
<length> is NULL, no length is returned. The maximum number of characters
that may be written into <name>, including the null terminator, is
specified by <bufsize>. The length of the longest subroutine name in
<program> and <shadertype> is given by the value of
ACTIVE_SUBROUTINE_MAX_LENGTH, which can be queried with GetProgramStageiv.
The command
void UniformSubroutinesuiv(enum shadertype, sizei count,
const uint *indices);
will load all active subroutine uniforms for shader stage <shadertype>
with subroutine indices from <indices>, storing <indices>[i] into the
uniform at location i. If <count> is not equal to the value of
ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the program currently in use at
shader stage <shadertype>, or if any value in <indices> is greater than or
equal to the value of ACTIVE_SUBROUTINES for the shader stage, the error
INVALID_VALUE is generated. If, for any subroutine index being loaded to
a particular uniform location, the function corresponding to the
subroutine index was not associated (as defined in Section 6.1.2 of the
GLSL spec) with the type of the subroutine variable at that location, then
the error INVALID_OPERATION is generated. If no program is active for
the shader stage identified by <shadertype>, the error INVALID_OPERATION
is generated.
Each subroutine uniform must have at least one subroutine to assign to the
uniform. A program will fail to link if any stage has one or more
subroutine uniforms that has no subroutine associated with the subroutine
type of the uniform.
When UseProgram is called, the subroutine uniforms for all shader stages
are reset to arbitrarily chosen default functions with compatible
subroutine types. When UseShaderProgramEXT is called, the subroutine
uniforms for the shader stage specified by <type> are reset to arbitrarily
chosen default functions with compatible subroutine types.
Additions to Chapter 3 of the OpenGL 3.2 Specification (Rasterization)
None.
Additions to Chapter 4 of the OpenGL 3.2 Specification (Per-Fragment
Operations and the Frame Buffer)
None.
Additions to Chapter 5 of the OpenGL 3.2 Specification (Special Functions)
None.
Additions to Chapter 6 of the OpenGL 3.2 Specification (State and
State Requests)
Add to Section 6.1.15 (Shader and Program Queries)
The command
void GetUniformSubroutineuiv(enum shadertype, int location,
uint *params);
returns the value of the subroutine uniform at location <location> for
shader stage <shadertype> of the current program. If <location> is
greater than or equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS
for the shader currently in use at shader stage <shadertype>, the error
INVALID_VALUE is generated. If no program is active, the error
INVALID_OPERATION is generated.
The command
void GetProgramStageiv(uint program, enum shadertype,
enum pname, int *values);
returns properties of the program object <program> specific to the
programmable stage corresponding to <shadertype> in <values>. The
parameter value to return is specified by <pname>. If <pname> is
ACTIVE_SUBROUTINE_UNIFORMS, the number of active subroutine variables in
the stage is returned. If <pname> is ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
the number of active subroutine variable locations in the stage is
returned. If <pname> is ACTIVE_SUBROUTINES, the number of active
subroutines in the stage is returned. If <pname> is
ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH or ACTIVE_SUBROUTINE_MAX_LENGTH, the
length of the longest subroutine uniform or subroutine name, respectively,
for the stage is returned. The returned name length includes space for a
null terminator. If there is no shader of type <shadertype> in <program>,
the values returned will be consistent with a shader with no subroutines
or subroutine uniforms.
Modifications to The OpenGL Shading Language Specification, Version 1.50
Including the following line in a shader can be used to control the
language features described in this extension:
#extension GL_ARB_shader_subroutine : <behavior>
where <behavior> is as specified in section 3.3.
In section 3.6, p.14 (Keywords)
Add subroutine to the list of reserved keywords.
Modify Section 6.1.1 (Function Calling Conventions)
(modify the last paragraph of the section, p. 66, to forbid potential
recursion via subroutines) Recursion is not allowed, not even statically.
Static recursion is present if the static function-call graph of a program
contains cycles. This includes all potential function calls through
variables declared as subroutine uniform (described below). It is an
error if a single compilation unit (shader) contains either static
recursion or the potential for recursion through subroutine variables.
Add a new Section 6.1.2 (Subroutines)
Subroutines provide a mechanism allowing shaders to be compiled in a
manner where the target of one or more function calls can be changed at
run-time without requiring any shader recompilation. For example, a
single shader may be compiled with support for multiple illumination
algorithms to handle different kinds of lights or surface materials. An
application using such a shader may switch illumination algorithms by
changing the value of its subroutine uniforms. To use subroutines, a
subroutine type is declared, one or more functions are associated with
that subroutine type, and a subroutine variable of that type is declared.
The function currently assigned to the variable function is then called by
using function calling syntax replacing a function name with the name of
the subroutine variable. Subroutine variables are assigned to specific
functions only through commands (UniformSubroutinesuiv) in the OpenGL API.
Subroutine types can be declared using a statement similar to a function
declaration, as follows:
subroutine returnType subroutineTypeName(type0 arg0, type1 arg1,
..., typen argn);
Functions may be associated to subroutine types that have a matching
prototype by prepending the subroutine types to the function definition:
subroutine(subroutineTypeName0, ..., subroutineTypeNameN)
returnType functionName (type0 arg0, type1 arg1, ..., typen argn)
... // function body
Subroutine declarations cannot be prototyped. It is an error to prepend
subroutine(...) to a function declaration. It is an error to declare
two distinct functions with the same function name within the same shader
(i.e. overloaded function names) that are both associated to subroutine
types.
Subroutine types share a namespace with standard function names.
Overloading (section 6.1) is not supported for functions that may be
associated with subroutine types. A program will fail to link if any
shader includes two or more functions with the same name, at least one of
which is associated with a subroutine type.
Subroutine variables are required to be "subroutine uniforms", and
are declared with a specific subroutine type in a subroutine uniform
variable declaration:
subroutine uniform subroutineTypeName subroutineVarName;
and are called the same way simple functions are called. Subroutine
variables may be declared as explicitly-sized arrays, which can be
dynamically indexed at use.
Subroutine variables are associated to functions declared with the
same subroutine type with the UniformSubroutinesuiv command in the OpenGL
API. When a subroutine variable (or an element of a subroutine variable
array) is associated to a particular function, all function calls through
that variable will call that particular function.
Additions to the AGL/GLX/WGL Specifications
None.
GLX Protocol
None.
Errors
The error INVALID_OPERATION is generated by GetSubroutineUniformLocation
if the program object identified by <program> has not been successfully
linked.
The error INVALID_VALUE is generated by GetActiveSubroutineUniformiv or
GetActiveSubroutineUniformName if <index> is greater than or equal to the
value of ACTIVE_SUBROUTINE_UNIFORMS for the shader stage.
The error INVALID_VALUE is generated by GetActiveSubroutineName if <index>
is greater than or equal to the value of ACTIVE_SUBROUTINES for the shader
stage.
The error INVALID_VALUE is generated by UniformSubroutinesuiv if <count>
is not equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the
shader stage <shadertype>.
The error INVALID_VALUE is generated by UniformSubroutinesuiv if any value
in <indices> is greater than or equal to the value of ACTIVE_SUBROUTINES
for the shader stage.
The error INVALID_OPERATION is generated by UniformSubroutinesuiv if any
subroutine index in <indices> identifies a subroutine not associated with
the type of the subroutine uniform variable assigned to the corresponding
location.
The error INVALID_OPERATION is generated by UniformSubroutinesuiv if no
program is active.
The error INVALID_VALUE is generated by GetUniformSubroutineuiv if
<location> is greater than or equal to the value of
ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the shader stage.
The error INVALID_OPERATION is generated by GetUniformSubroutineuiv if no
program is active for the shader stage identified by <shadertype>.
New State
(add to table 6.28, Program Object State, p. 293)
Initial
Get Value Type Get Command Value Description Sec.
--------------------------- ---------- ----------- ------- --------------------------- ------
ACTIVE_SUBROUTINE_UNIFORM_ 5xZ+ GetProgram- 0 Number of subroutine unif. 2.11.4
LOCATIONS Stageiv locations in the shader
ACTIVE_SUBROUTINE_UNIFORMS 5xZ+ GetProgram- 0 Number of subroutine unif. 2.11.4
Stageiv variables in the shader
ACTIVE_SUBROUTINES 5xZ+ GetProgram- 0 Number of subroutine 2.11.4
Stageiv functions in the shader
ACTIVE_SUBROUTINE_UNIFORM_ 5xZ+ GetProgram- 0 Maximum subroutine uniform 2.11.4
MAX_LENGTH Stageiv name length
ACTIVE_SUBROUTINE_MAX_LENGTH 5xZ+ GetProgram- 0 Maximum subroutine name 2.11.4
Stageiv length
NUM_COMPATIBLE_SUBROUTINES 5x0*xZ+ GetActiveSub- - Number of subroutines comp- 2.11.4
routineUniformiv atible with a sub. uniform
COMPATIBLE_SUBROUTINES 5x0*x0*xZ+ GetActiveSub- - List of subroutines comp- 2.11.4
routineUniformiv atible with a sub. uniform
UNIFORM_SIZE 5x0*xZ+ GetActiveSub- - Number of elements in sub. 2.11.4
routineUniformiv uniform array
UNIFORM_NAME_LENGTH 5x0*xZ+ GetActiveSub- - Length of sub. uniform name 2.11.4
routineUniformiv
- 5x0*xS GetActiveSub- - Sub. uniform name string 2.11.4
routineUniformName
- 5x0*xS GetActiveSub- - Length of subroutine name 2.11.4
routineName
- 5x0*xS GetActiveSub- - Subroutine name string 2.11.4
routineName
(For the above, the "5" is indicates separate state for each of the five
shader stages in the program.)
New Implementation Dependent State
Minimum
Get Value Type Get Command Value Description Sec. Attrib
----------------------------- ---- --------------- ------- --------------------- ------ ------
MAX_SUBROUTINES Z+ GetIntegerv 256 Maximum number of 2.14.1 -
subroutines per
shader stage
MAX_SUBROUTINE_UNIFORM_ Z+ GetIntegerv 1024 Maximum number of 2.X.5 -
LOCATIONS subroutine uniform
locations per stage
Dependencies on NV_gpu_program5:
If NV_gpu_program5 is supported, the following edits are made to extend
the assembly programming model documented in the NV_gpu_program4 extension
and extended by NV_gpu_program5. No "OPTION" line is required; the
following capability is implied by NV_gpu_program5 program headers such as
"!!NVfp5.0".
New Procedures and Functions
void ProgramSubroutineParametersuivNV(enum target, sizei count,
const uint *params);
void GetProgramSubroutineParameteruivNV(enum target, uint index,
uint *param);
New Tokens
Accepted by the <pname> parameter of GetProgramivARB:
MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV 0x8F44
MAX_PROGRAM_SUBROUTINE_NUM_NV 0x8F45
(Modify "Section 2.14.1" of the ARB_vertex_program specification,
describing program parameters.)
Each program target has an associated array of program subroutine
parameters. Unlike program local parameters, program subroutine parameters
are context state rather than program state. Program subroutine parameters
are scalar unsigned integer values that correspond to "SUBROUTINENUM"
declarations in a program. The number of scalars is given by the
implementation-dependent value MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV.
The command
void ProgramSubroutineParametersuivNV(enum target, sizei count,
const uint *params);
updates the values of all program subroutine parameters used by the
currently bound program for the given program target <target>. <params>
points to an array of <count> values, where the first value is used to
update the program subroutine parameter numbered zero and the last value
is used to update the program subroutine parameter numbered <count> - 1.
The error INVALID_VALUE is generated if <count> is not equal to one plus
the maximum program subroutine parameter index used in the currently bound
program.
Program subroutine parameters for a given target are reset to arbitrary
defaults when the program string is respecified, and when BindProgram is
called to bind a program to that target, even if the specified program is
already bound.
The error INVALID_OPERATION is generated by
ProgramSubroutineParametersuivNV if, for any number <i> in [0, <count>),
program.subroutine[<i>] is a live parameter of a certain SUBROUTINETYPE,
and <params>[<i>] is not a SUBROUTINENUM that was associated to that
SUBROUTINETYPE as described in Section 2.X.5.
Modify Section 2.X.2 of NV_gpu_program4, Program Grammar
If a program begins with a header string defined by GL_NV_gpu_program5,
the following modifications apply to the program grammar:
<FlowInstruction> ::= <BRAop_instruction>
| <FLOWCCop_instruction>
| <IFop_instruction>
| <REPop_instruction>
| <ENDFLOWop_instruction>
| <CALI_instruction>
<namingStatement> ::= <varMods> <ATTRIB_statement>
| <varMods> <PARAM_statement>
| <varMods> <TEMP_statement>
| <varMods> <OUTPUT_statement>
| <varMods> <BUFFER_statement>
| <ALIAS_statement>
| <SUBROUTINETYPE_statement>
| <SUBROUTINE_statement>
<labelList> ::= <identifier>
| <identifier> "," <labelList>
<labelInitList> ::= /* empty */
| <labelList>
<SUBROUTINETYPE_statement> ::= "SUBROUTINETYPE" <establishName> "{"
<labelInitList> "}"
<progSubroutineParam> ::= "program" "." "subroutine" <arrayMemAbs>
<progSubroutineParams> ::= <progSubroutineParam>
| "program" "." "subroutine" <arrayRange>
<progSubroutineInitList>::= <progSubroutineParams>
| <progSubroutineParams> ","
<progSubroutineInitList>
<SUBROUTINE_statement> ::= "SUBROUTINE" <establishedName> <establishName>
"=" <progSubroutineParam>
| "SUBROUTINE" <establishedName> <establishName>
<optArraySize> "=" "{" <progSubroutineInitList>
"}"
<CALIop> ::= "CALI"
<CALI_instruction> ::= <CALIop> <opModifiers> <subroutineVarName>
<optArrayMem> <optBranchCond>
<instLabel> ::= <identifier>
| <identifier> "SUBROUTINENUM" "(" <int> ")"
Modify Section 2.X.4, Program Execution Environment
(Update the instruction set table to add CALI)
Instr- Modifiers
uction V F I C S H D Out Inputs Description
------- -- - - - - - - --- -------- --------------------------------
CALI 50 - - - - - - - c indirect subroutine call
Modify Section 2.X.5 (Program Flow Control) of the NV_gpu_program4
specification
(Add after the description of subroutines)
Subroutines may be called indirectly using the CALI instruction. An
"indirect" call will transfer control to one of a set of labels, where
the specific label that is used in a particular program invocation is
set through a "subroutine" parameter (see Section 2.14.1).
Functions that will be used for indirect subroutine calls must all be
assigned a unique unsigned integer SUBROUTINENUM using the modified
<instLabel> grammar rule.
A <SUBROUTINETYPE_statement> associates one or more subroutine labels with
a "type". For example:
SUBROUTINETYPE Hero { batman, robin };
creates a SUBROUTINETYPE named "Hero" (if it does not already exist) and
adds the subroutines whose labels are "batman" and "robin" to the
SUBROUTINETYPE.
A "subroutine" parameter is a special type of program parameter whose value
refers to one of a set of subroutines, selected by the API. A subroutine is
given a SUBROUTINETYPE when it is declared, and it may refer to any label
of that type. Continuing this example:
SUBROUTINETYPE Hero { superman, wolverine };
SUBROUTINETYPE Hero { batman, robin };
SUBROUTINETYPE GothamHero { batman, robin };
# anyHero may "point to" any Hero
SUBROUTINE Hero anyHero = program.subroutine[0];
# gothamHero may "point to" any GothamHero
SUBROUTINE GothamHero gothamHero = program.subroutine[1];
batman SUBROUTINENUM(0):
...
robin SUBROUTINENUM(1):
...
superman SUBROUTINENUM(2):
...
wolverine SUBROUTINENUM(3):
...
main:
# could call any of the four heros
CALI anyHero;
# could call either batman or robin
CALI gothamHero;
Program subroutine parameters are assigned to labels by setting the
corresponding SUBROUTINENUMs via ProgramSubroutineParametersuivNV. For
example,
uint params[2] = {2, 0};
ProgramSubroutineParametersuivNV(target, 2, params);
would assign program.subroutine[0] (and therefore "anyHero") to "superman",
and program.subroutine[1] (and therefore "gothamHero") to "batman".
All SUBROUTINENUMs must be greater than or equal to zero, and less than the
value of MAX_PROGRAM_SUBROUTINE_NUM_NV. A label may be assigned to multiple
SUBROUTINETYPEs. A program subroutine parameter may only be assigned to
subroutine variables of a single SUBROUTINETYPE.
Programs that may potentially cause infinite recursion through indirect
calls will fail to compile.
Section 2.X.8.Z, CALI: Indirect Subroutine Call
The CALI instruction conditionally transfers control to the instruction
following some label, as described in CAL. The determination of which
label is used is described in Section 2.X.5 (Program Flow Control).
Add to Chapter 6 (State and State Requests)
The command
void GetProgramSubroutineParameteruivNV(enum target, uint index,
uint *params);
obtains the current value for the program subroutine parameter numbered
<index> for the given program target <target>, and places the single
unsigned integer value in the array <params>. The error INVALID_ENUM is
generated if <target> specifies a nonexistent program target or a program
target that does not support program environment parameters. The error
INVALID_VALUE is generated if <index> is greater than or equal to the
implementation-dependent number of supported program subroutine parameters
for the program target.
Add various new conditions by which a program string would fail to load.
The error INVALID_ENUM is generated by GetProgramSubroutineParameteruivNV
and ProgramSubroutineParametersuivNV if <target> specifies a nonexistent
program target.
The error INVALID_VALUE is generated by GetProgramSubroutineParameteruivNV
if <index> is greater than or equal to the max number of program subroutine
parameters, and by ProgramSubroutineParametersuivNV if <count> is <count>
is not equal to one plus the maximum program subroutine parameter index used
in the currently bound program.
The error INVALID_OPERATION is generated by
ProgramSubroutineParametersuivNV if, for any number <i> in [0, <count>),
program.subroutine[<i>] is a live parameter of a certain SUBROUTINETYPE,
and <params>[<i>] is not a SUBROUTINENUM that was associated to that
SUBROUTINETYPE as described in Section 2.X.5.
Add new implementation dependent state
Minimum
Get Value Type Get Command Value Description Sec. Attrib
-------------------------------- ---- --------------- ------- --------------------- ------ ------
MAX_PROGRAM_SUBROUTINE_ Z+ GetProgramivARB 1024 Maximum number of 2.14.1 -
PARAMETERS_NV program subroutine
parameters
MAX_PROGRAM_SUBROUTINENUM_NV Z+ GetProgramivARB 256 Maximum SUBROUTINENUM 2.X.5 -
value
Dependencies on EXT_separate_shader_objects
If EXT_separate_shader_objects is not supported, remove references to
UseShaderProgramEXT.
Issues
(1) What terms should we use to describe the various data types and
concepts in this specification?
RESOLVED: This extension uses mechanisms similar to function pointers in
C. We aren't directly exposing function pointers, but are instead using a
function pointer-like data type. We are using the term "subroutine" to
qualify various concepts in this extension. The function pointer type is
referred to as a "subroutine type". Integer indices used to identify
functions that can be assigned to a function pointer type are referred to
as "subroutine indices". Uniforms that can hold function pointer values
are referred to as "subroutine uniforms".
We considered using the term "interfaces", but were concerns about
confusion with object-oriented programming models -- the model we are
using is not object-oriented. Referring instead to these limited function
pointers as "subroutines" avoids this confusion and matches its use in
similar circumstances. The term is not currently used in any GLSL nor
OpenGL specification.
(2) What happens if you try to link a program that has active subroutines
that have no subroutines that can be assigned ot them?
RESOLVED: Attempting to link a program that calls a function pointer
with no potential associations produces a link error.
(3) What happens if the app specifies a bad subroutine index?
RESOLVED: There are two different forms of invalid subroutine indices --
ones that correspond to no subroutine, and ones that correspond to a
subroutine of the wrong type. If the app specifies a number that
corresponds to no subroutine, an INVALID_VALUE error is generated. If the
number corresponds to a subroutine of the wrong type, an INVALID_OPERATION
error is generated.
(4) What happens if the shaders change without reassigning subroutine
associations?
RESOLVED: The subroutine uniforms will revert to a default function of
of those associated with it in the shader. The default function chosen
may be implementation dependent.
(5) How should subroutine parameters be updated?
RESOLVED: UniformSubroutinesuivARB requires sending all subroutine
parameters at once so they can be validated in a single burst. This is
similar to D3D which goes as far as to require setting all of them in the
same operation that binds the shader.
(6) Why is the new "subroutine" state owned by the context rather than
by the assembly program or GLSL program/shader?
RESOLVED: We expect that a common usage of this extension
would be to create a so-called "uber-shader" -- a program that can
support many different state configurations. If an application uses
such a program in multiple contexts, it likely it would not want changes
to linkage for one context to affect the other context.
(7) Does that mean other types of uniforms also need to be context state?
RESOLVED: Apps can choose to share or not share numeric uniform types at
their discretion using UBO, however for more "opaque" uniform types like
samplers it may be desirable to have context state. Such a change is
beyond the scope of this extension. No effort was made to make subroutine
uniforms generic enough to support other potential usages. Should such
emerge, they will define their own unique uniform types.
(8) GLSL allows function name overloading, how can you query a
subroutine location in that case?
RESOLVED: Disallow overloading of function names used for subroutine
functions.
(9) What sort of implementation-dependent limits apply to subroutines?
RESOLVED: There is an limit on the number of subroutines per shader stage
(MAX_SUBROUTINES) and also a limit on the number of subroutine uniform
locations (MAX_SUBROUTINE_UNIFORM_LOCATIONS).
(10) How many subroutine variables be used? Should they be allowed as
function parameters, structure members, and arrays?
RESOLVED: Arrays of subroutine uniforms are allowed. The spec does not
currently permit them as function parameters or structure members, as it
requires subroutine variables be declared as uniforms. Subroutine
function parameters can be emulated by declaring a uniform array holding
all possible subroutines that a shader might want to pass as a parameter
and then passing an integer index to select a subroutine to call.
(11) Is the "subroutine" keyword necessary when declaring a subroutine
uniform?
RESOLVED: Yes, "subroutine uniform" in the declaration is required.
(12) Why don't the new tokens and entry points in this extension have
"ARB" suffixes like other ARB extensions?
RESOLVED: Unlike most ARB extensions, this is a strict subset of
functionality already approved for the OpenGL core. This extension
exists only to support that functionality on older hardware that cannot
implement all the functionality in that OpenGL version. Since there are
no possible behavior changes between the ARB extension and core features,
source code compatibility is improved by not using suffixes on the
extension.
(13) Are compilers permitted to eliminate unreferenced elements at the end
of an array for subroutine uniforms like they can for regular uniforms?
RESOLVED: No, because of differences in the uniform loading APIs.
Consider the following example:
uniform float array[10];
// shader only references array[0..5]
The GL implementation is permitted to treat "array" as having a size of
6, but may also use the declared size of 10. An application may have
built-in knowledge that "array" has a declared length of 10, and might
call Uniform1f() with a <count> of 10. The specified behavior for
Uniform*() APIs is that any values specified that extend beyond the last
active element of the array are ignored. As a result, passing "extra"
elements to Uniform*() causes no problems; applications don't need to
query the active size of a uniform array to get correct behavior.
The subroutine uniform loading API is different, as it accepts a single
array containing the values for every active uniform. This allows
applications to specify the values for all subroutine uniforms in a
single call, instead of multiple calls for regular uniforms. However,
this approach doesn't provide a mechanism for discarding unused array
elements. If "array" above was a subroutine uniform and the application
wrote 10 values into the array it would pass to UniformSubroutinesuiv,
it might overwrite the values of other subroutines or write off the end
of the array if the compiler only assigned 6 locations for "array". If
unused elements could be eliminated, implementations would have to query
the active size for each subroutine uniform array, even if they knew the
declared size up-front. To avoid the need to always query lengths, we
instead specify that all elements of an active subroutine array are
active.
Revision History
Rev. Date Author Changes
---- ---------- -------- ----------------------------------------------
19 02/28/2014 Jon Leech Restrict error for UniformSubroutinesuiv to
the case where no program stage is active for
the shader stage identified by <shadertype>
(Bug 11306).
18 02/10/2011 pbrown Add a clarification to the GLSL spec language
prohibiting potential recursion via subroutine
uniforms; a program will fail to link if there
is any possible combination of subroutine
uniform values that would result in recursion
(bug 7327).
17 03/29/2010 pbrown Update issues (1) and (10).
16 03/21/2010 pbrown Minor clarification in the NV_gpu_program5
interaction that no OPTION is required to
use subroutines in assembly programs.
15 02/08/2010 Jon Leech Minor wording changes for consistency with
4.0 specification.
14 01/30/2010 pbrown Specify that implementations are not permitted
to chop unreferenced elements off the end of
a subroutine uniform array like they are with
regular uniforms (bug 5978). Minor
clarification on the meaning of "active
subroutines".
13 01/26/2010 pbrown Assigned enum values for enums added by most
recent edits.
12 01/20/2010 pbrown Update state tables to classify per-subroutine
and per-subroutine uniform state as "5x" to
indicate a separate set of values for each
shader stage.
11 01/18/2010 pbrown Rename GetActiveSubroutineUniformiv. Add
enums to query the longest subroutine uniform
and subroutine names in a stage. Rename enum
NUM_COMPATIBLE_SUBROUTINES. Change error
behavior to allow most queries on unlinked
programs and ones without the specified stage
(except GetSubroutineUniformLocation). Added
errors in UniformSubroutines and
GetUniformSubroutineuiv if no program is
active. Minor spec language cleanups. All
based on review comments in bug 5861.
10 01/15/2010 pbrown Significant changes to allow for full
discoverability of subroutine uniforms,
subroutines, and their locations (bug 5861).
Rename the term "subroutine number" to "active
subroutine index". Rename GetSubroutineIndex
(was GetSubroutineNumber) and the <indices>
parameter of UniformSubroutinesuiv. Fix
prototype of GetSubroutineIndex and other APIs
to consistently use "uint". Add APIs to query
properties of active subroutine uniforms
(name, associated subroutines). Separate the
notion of subroutine uniform indices and
locations just like regular uniforms. Arrays
may have one index but multiple locations.
Specify that locations are packed in
consecutive locations. Rename
GetSubroutineName to GetActiveSubroutineName
to match other enumeration APIs. Add a query
for the number of active subroutine uniform
locations, and change the implementation limit
to be on active locations instead of indices.
Clarify that subroutines in a shader need not
be active if there is no active uniform that
can call them (bug 5859). Update state tables
and some issues.
9 01/14/2010 pbrown Add some more text to the introduction to
subroutines in the GLSL spec section.
8 12/10/2009 groth ARBify.
7 12/10/2009 groth Correct prototypes and clarify/correct errors.
Fix a few state retrieval typos.
6 10/29/2009 groth Clarify a number of areas in response to
feedback from bmerry.
5 09/24/2009 groth Fix typo in GLSL example. Assign enums.
4 09/17/2009 pbrown Add implementation-dependent limits on
subroutines. Document some of these limits
and restrictions on function overloading and
subroutine uniforms with no matching function.
3 09/16/2009 groth Resolve issues. A few clarifications.
rename interface to subroutine.
2 09/14/2009 groth EXTify. move asm changes to dependencies.
1 jbolz Internal revisions.