mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 19:40:10 +01:00
mesa/glsl: build list of program resources during linking
Patch adds ProgramResourceList to gl_shader_program structure. List contains references to active program resources and is constructed during linking phase. This list will be used by follow-up patches to implement hooks for GL_ARB_program_interface_query. It can be also used to implement any of the older shader program query APIs. v2: code cleanups + note for SSBO and subroutines (Ilia Mirkin) v3: code cleanups + assert(MESA_SHADER_STAGES < 8) (Martin Peres) Signed-off-by: Tapani Pälli <tapani.palli@intel.com> Reviewed-by: Martin Peres <martin.peres@linux.intel.com>
This commit is contained in:
parent
b297fc27aa
commit
c796ce4108
3 changed files with 212 additions and 0 deletions
|
|
@ -2492,6 +2492,194 @@ check_explicit_uniform_locations(struct gl_context *ctx,
|
|||
delete uniform_map;
|
||||
}
|
||||
|
||||
static bool
|
||||
add_program_resource(struct gl_shader_program *prog, GLenum type,
|
||||
const void *data, uint8_t stages)
|
||||
{
|
||||
assert(data);
|
||||
|
||||
/* If resource already exists, do not add it again. */
|
||||
for (unsigned i = 0; i < prog->NumProgramResourceList; i++)
|
||||
if (prog->ProgramResourceList[i].Data == data)
|
||||
return true;
|
||||
|
||||
prog->ProgramResourceList =
|
||||
reralloc(prog,
|
||||
prog->ProgramResourceList,
|
||||
gl_program_resource,
|
||||
prog->NumProgramResourceList + 1);
|
||||
|
||||
if (!prog->ProgramResourceList) {
|
||||
linker_error(prog, "Out of memory during linking.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct gl_program_resource *res =
|
||||
&prog->ProgramResourceList[prog->NumProgramResourceList];
|
||||
|
||||
res->Type = type;
|
||||
res->Data = data;
|
||||
res->StageReferences = stages;
|
||||
|
||||
prog->NumProgramResourceList++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function builds a stage reference bitmask from variable name.
|
||||
*/
|
||||
static uint8_t
|
||||
build_stageref(struct gl_shader_program *shProg, const char *name)
|
||||
{
|
||||
uint8_t stages = 0;
|
||||
|
||||
/* Note, that we assume MAX 8 stages, if there will be more stages, type
|
||||
* used for reference mask in gl_program_resource will need to be changed.
|
||||
*/
|
||||
assert(MESA_SHADER_STAGES < 8);
|
||||
|
||||
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
struct gl_shader *sh = shProg->_LinkedShaders[i];
|
||||
if (!sh)
|
||||
continue;
|
||||
ir_variable *var = sh->symbols->get_variable(name);
|
||||
if (var)
|
||||
stages |= (1 << i);
|
||||
}
|
||||
return stages;
|
||||
}
|
||||
|
||||
static bool
|
||||
add_interface_variables(struct gl_shader_program *shProg,
|
||||
struct gl_shader *sh, GLenum interface)
|
||||
{
|
||||
foreach_in_list(ir_instruction, node, sh->ir) {
|
||||
ir_variable *var = node->as_variable();
|
||||
|
||||
if (!var)
|
||||
continue;
|
||||
|
||||
switch (var->data.mode) {
|
||||
/* From GL 4.3 core spec, section 11.1.1 (Vertex Attributes):
|
||||
* "For GetActiveAttrib, all active vertex shader input variables
|
||||
* are enumerated, including the special built-in inputs gl_VertexID
|
||||
* and gl_InstanceID."
|
||||
*/
|
||||
case ir_var_system_value:
|
||||
if (var->data.location != SYSTEM_VALUE_VERTEX_ID &&
|
||||
var->data.location != SYSTEM_VALUE_VERTEX_ID_ZERO_BASE &&
|
||||
var->data.location != SYSTEM_VALUE_INSTANCE_ID)
|
||||
continue;
|
||||
case ir_var_shader_in:
|
||||
if (interface != GL_PROGRAM_INPUT)
|
||||
continue;
|
||||
break;
|
||||
case ir_var_shader_out:
|
||||
if (interface != GL_PROGRAM_OUTPUT)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
};
|
||||
|
||||
if (!add_program_resource(shProg, interface, var,
|
||||
build_stageref(shProg, var->name)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds up a list of program resources that point to existing
|
||||
* resource data.
|
||||
*/
|
||||
static void
|
||||
build_program_resource_list(struct gl_context *ctx,
|
||||
struct gl_shader_program *shProg)
|
||||
{
|
||||
/* Rebuild resource list. */
|
||||
if (shProg->ProgramResourceList) {
|
||||
ralloc_free(shProg->ProgramResourceList);
|
||||
shProg->ProgramResourceList = NULL;
|
||||
shProg->NumProgramResourceList = 0;
|
||||
}
|
||||
|
||||
int input_stage = MESA_SHADER_STAGES, output_stage = 0;
|
||||
|
||||
/* Determine first input and final output stage. These are used to
|
||||
* detect which variables should be enumerated in the resource list
|
||||
* for GL_PROGRAM_INPUT and GL_PROGRAM_OUTPUT.
|
||||
*/
|
||||
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
if (!shProg->_LinkedShaders[i])
|
||||
continue;
|
||||
if (input_stage == MESA_SHADER_STAGES)
|
||||
input_stage = i;
|
||||
output_stage = i;
|
||||
}
|
||||
|
||||
/* Empty shader, no resources. */
|
||||
if (input_stage == MESA_SHADER_STAGES && output_stage == 0)
|
||||
return;
|
||||
|
||||
/* Add inputs and outputs to the resource list. */
|
||||
if (!add_interface_variables(shProg, shProg->_LinkedShaders[input_stage],
|
||||
GL_PROGRAM_INPUT))
|
||||
return;
|
||||
|
||||
if (!add_interface_variables(shProg, shProg->_LinkedShaders[output_stage],
|
||||
GL_PROGRAM_OUTPUT))
|
||||
return;
|
||||
|
||||
/* Add transform feedback varyings. */
|
||||
if (shProg->LinkedTransformFeedback.NumVarying > 0) {
|
||||
for (int i = 0; i < shProg->LinkedTransformFeedback.NumVarying; i++) {
|
||||
uint8_t stageref =
|
||||
build_stageref(shProg,
|
||||
shProg->LinkedTransformFeedback.Varyings[i].Name);
|
||||
if (!add_program_resource(shProg, GL_TRANSFORM_FEEDBACK_VARYING,
|
||||
&shProg->LinkedTransformFeedback.Varyings[i],
|
||||
stageref))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add uniforms from uniform storage. */
|
||||
for (unsigned i = 0; i < shProg->NumUserUniformStorage; i++) {
|
||||
/* Do not add uniforms internally used by Mesa. */
|
||||
if (shProg->UniformStorage[i].hidden)
|
||||
continue;
|
||||
|
||||
uint8_t stageref =
|
||||
build_stageref(shProg, shProg->UniformStorage[i].name);
|
||||
if (!add_program_resource(shProg, GL_UNIFORM,
|
||||
&shProg->UniformStorage[i], stageref))
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add program uniform blocks. */
|
||||
for (unsigned i = 0; i < shProg->NumUniformBlocks; i++) {
|
||||
if (!add_program_resource(shProg, GL_UNIFORM_BLOCK,
|
||||
&shProg->UniformBlocks[i], 0))
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add atomic counter buffers. */
|
||||
for (unsigned i = 0; i < shProg->NumAtomicBuffers; i++) {
|
||||
if (!add_program_resource(shProg, GL_ATOMIC_COUNTER_BUFFER,
|
||||
&shProg->AtomicBuffers[i], 0))
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO - following extensions will require more resource types:
|
||||
*
|
||||
* GL_ARB_shader_storage_buffer_object
|
||||
* GL_ARB_shader_subroutine
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
{
|
||||
|
|
@ -2899,6 +3087,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
|||
}
|
||||
}
|
||||
|
||||
build_program_resource_list(ctx, prog);
|
||||
if (!prog->LinkStatus)
|
||||
goto done;
|
||||
|
||||
/* FINISHME: Assign fragment shader output locations. */
|
||||
|
||||
done:
|
||||
|
|
|
|||
|
|
@ -2603,6 +2603,16 @@ struct gl_active_atomic_buffer
|
|||
GLboolean StageReferences[MESA_SHADER_STAGES];
|
||||
};
|
||||
|
||||
/**
|
||||
* Active resource in a gl_shader_program
|
||||
*/
|
||||
struct gl_program_resource
|
||||
{
|
||||
GLenum Type; /** Program interface type. */
|
||||
const void *Data; /** Pointer to resource associated data structure. */
|
||||
uint8_t StageReferences; /** Bitmask of shader stage references. */
|
||||
};
|
||||
|
||||
/**
|
||||
* A GLSL program object.
|
||||
* Basically a linked collection of vertex and fragment shaders.
|
||||
|
|
@ -2777,6 +2787,10 @@ struct gl_shader_program
|
|||
*/
|
||||
struct gl_shader *_LinkedShaders[MESA_SHADER_STAGES];
|
||||
|
||||
/** List of all active resources after linking. */
|
||||
struct gl_program_resource *ProgramResourceList;
|
||||
unsigned NumProgramResourceList;
|
||||
|
||||
/* True if any of the fragment shaders attached to this program use:
|
||||
* #extension ARB_fragment_coord_conventions: enable
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -315,6 +315,12 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg)
|
|||
ralloc_free(shProg->AtomicBuffers);
|
||||
shProg->AtomicBuffers = NULL;
|
||||
shProg->NumAtomicBuffers = 0;
|
||||
|
||||
if (shProg->ProgramResourceList) {
|
||||
ralloc_free(shProg->ProgramResourceList);
|
||||
shProg->ProgramResourceList = NULL;
|
||||
shProg->NumProgramResourceList = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue