From ffdb44d3a0a2199487f17ff566c51280c9708c60 Mon Sep 17 00:00:00 2001 From: Antia Puentes Date: Wed, 8 Aug 2018 14:29:38 +0200 Subject: [PATCH] nir/linker: Add inputs/outputs to the program resource list v2: added TODO comment hinting possible future refactoring of nir_build_program_resource_list and build_program_resource_list, to avoid code duplication (Alejandro, to explicitly reflect a valid concern from Timothy during the review). Reviewed-by: Timothy Arceri --- src/compiler/glsl/gl_nir_linker.c | 108 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/src/compiler/glsl/gl_nir_linker.c b/src/compiler/glsl/gl_nir_linker.c index 49ba950..13d4e83 100644 --- a/src/compiler/glsl/gl_nir_linker.c +++ b/src/compiler/glsl/gl_nir_linker.c @@ -33,6 +33,85 @@ * Also note that this is tailored for ARB_gl_spirv needs and particularities */ +static bool +add_interface_variables(const struct gl_context *cts, + struct gl_shader_program *prog, + struct set *resource_set, + unsigned stage, GLenum programInterface) +{ + const struct exec_list *var_list = NULL; + + struct gl_linked_shader *sh = prog->_LinkedShaders[stage]; + if (!sh) + return true; + + nir_shader *nir = sh->Program->nir; + assert(nir); + + switch (programInterface) { + case GL_PROGRAM_INPUT: + var_list = &nir->inputs; + break; + case GL_PROGRAM_OUTPUT: + var_list = &nir->outputs; + break; + default: + assert("!Should not get here"); + break; + } + + nir_foreach_variable(var, var_list) { + if (var->data.how_declared == nir_var_hidden) + continue; + + int loc_bias = 0; + switch(var->data.mode) { + case nir_var_system_value: + case nir_var_shader_in: + if (programInterface != GL_PROGRAM_INPUT) + continue; + loc_bias = (stage == MESA_SHADER_VERTEX) ? VERT_ATTRIB_GENERIC0 + : VARYING_SLOT_VAR0; + break; + case nir_var_shader_out: + if (programInterface != GL_PROGRAM_OUTPUT) + continue; + loc_bias = (stage == MESA_SHADER_FRAGMENT) ? FRAG_RESULT_DATA0 + : VARYING_SLOT_VAR0; + break; + default: + continue; + } + + if (var->data.patch) + loc_bias = VARYING_SLOT_PATCH0; + + struct gl_shader_variable *sh_var = + rzalloc(prog, struct gl_shader_variable); + + /* In the ARB_gl_spirv spec, names are considered optional debug info, so + * the linker needs to work without them. Returning them is optional. + * For simplicity, we ignore names. + */ + sh_var->name = NULL; + sh_var->type = var->type; + sh_var->location = var->data.location - loc_bias; + sh_var->index = var->data.index; + + if (!link_util_add_program_resource(prog, resource_set, + programInterface, + sh_var, 1 << stage)) { + return false; + } + } + + return true; +} + +/* TODO: as we keep adding features, this method is becoming more and more + * similar to its GLSL counterpart at linker.cpp. Eventually it would be good + * to check if they could be refactored, and reduce code duplication somehow + */ void nir_build_program_resource_list(struct gl_context *ctx, struct gl_shader_program *prog) @@ -44,8 +123,37 @@ nir_build_program_resource_list(struct gl_context *ctx, prog->data->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 (!prog->_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; + struct set *resource_set = _mesa_pointer_set_create(NULL); + /* Add inputs and outputs to the resource list. */ + if (!add_interface_variables(ctx, prog, resource_set, input_stage, + GL_PROGRAM_INPUT)) { + return; + } + + if (!add_interface_variables(ctx, prog, resource_set, output_stage, + GL_PROGRAM_OUTPUT)) { + return; + } + /* Add uniforms * * Here, it is expected that nir_link_uniforms() has already been -- 2.7.4