*size = max;
}
-extern "C" {
-
-/* First half of converting glsl_to_nir.. this leaves things in a pre-
+/* First third of converting glsl_to_nir.. this leaves things in a pre-
* nir_lower_io state, so that shader variants can more easily insert/
* replace variables, etc.
*/
-nir_shader *
+static nir_shader *
st_glsl_to_nir(struct st_context *st, struct gl_program *prog,
struct gl_shader_program *shader_program,
gl_shader_stage stage)
struct pipe_screen *pscreen = st->pipe->screen;
enum pipe_shader_type ptarget = pipe_shader_type_from_mesa(stage);
const nir_shader_compiler_options *options;
- nir_shader *nir;
assert(pscreen->get_compiler_options); /* drivers using NIR must implement this */
if (prog->nir)
return prog->nir;
- nir = glsl_to_nir(shader_program, stage, options);
+ return glsl_to_nir(shader_program, stage, options);
+}
+
+/* Second third of converting glsl_to_nir. This creates uniforms, gathers
+ * info on varyings, etc after NIR link time opts have been applied.
+ */
+static void
+st_glsl_to_nir_post_opts(struct st_context *st, struct gl_program *prog,
+ struct gl_shader_program *shader_program)
+{
+ nir_shader *nir = prog->nir;
/* Make a pass over the IR to add state references for any built-in
* uniforms that are used. This has to be done now (during linking).
NIR_PASS_V(nir, nir_lower_var_copies);
/* fragment shaders may need : */
- if (stage == MESA_SHADER_FRAGMENT) {
+ if (prog->info.stage == MESA_SHADER_FRAGMENT) {
static const gl_state_index wposTransformState[STATE_LENGTH] = {
STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM
};
if (st->ctx->_Shader->Flags & GLSL_DUMP) {
_mesa_log("\n");
_mesa_log("NIR IR for linked %s program %d:\n",
- _mesa_shader_stage_to_string(stage),
+ _mesa_shader_stage_to_string(prog->info.stage),
shader_program->Name);
nir_print_shader(nir, _mesa_get_log_file());
_mesa_log("\n\n");
}
-
- prog->nir = nir;
-
- return nir;
}
/* TODO any better helper somewhere to sort a list? */
exec_list_move_nodes_to(&new_list, var_list);
}
-/* Second half of preparing nir from glsl, which happens after shader
+static void
+set_st_program(struct gl_program *prog,
+ struct gl_shader_program *shader_program,
+ nir_shader *nir)
+{
+ struct st_vertex_program *stvp;
+ struct st_common_program *stp;
+ struct st_fragment_program *stfp;
+ struct st_compute_program *stcp;
+
+ switch (prog->info.stage) {
+ case MESA_SHADER_VERTEX:
+ stvp = (struct st_vertex_program *)prog;
+ stvp->shader_program = shader_program;
+ stvp->tgsi.type = PIPE_SHADER_IR_NIR;
+ stvp->tgsi.ir.nir = nir;
+ break;
+ case MESA_SHADER_GEOMETRY:
+ case MESA_SHADER_TESS_CTRL:
+ case MESA_SHADER_TESS_EVAL:
+ stp = (struct st_common_program *)prog;
+ stp->shader_program = shader_program;
+ stp->tgsi.type = PIPE_SHADER_IR_NIR;
+ stp->tgsi.ir.nir = nir;
+ break;
+ case MESA_SHADER_FRAGMENT:
+ stfp = (struct st_fragment_program *)prog;
+ stfp->shader_program = shader_program;
+ stfp->tgsi.type = PIPE_SHADER_IR_NIR;
+ stfp->tgsi.ir.nir = nir;
+ break;
+ case MESA_SHADER_COMPUTE:
+ stcp = (struct st_compute_program *)prog;
+ stcp->shader_program = shader_program;
+ stcp->tgsi.ir_type = PIPE_SHADER_IR_NIR;
+ stcp->tgsi.prog = nir_shader_clone(NULL, nir);
+ break;
+ default:
+ unreachable("unknown shader stage");
+ }
+}
+
+static void
+st_nir_get_mesa_program(struct gl_context *ctx,
+ struct gl_shader_program *shader_program,
+ struct gl_linked_shader *shader)
+{
+ struct st_context *st = st_context(ctx);
+ struct gl_program *prog;
+
+ validate_ir_tree(shader->ir);
+
+ prog = shader->Program;
+
+ prog->Parameters = _mesa_new_parameter_list();
+
+ _mesa_copy_linked_program_data(shader_program, shader);
+ _mesa_generate_parameters_list_for_uniforms(ctx, shader_program, shader,
+ prog->Parameters);
+
+ if (ctx->_Shader->Flags & GLSL_DUMP) {
+ _mesa_log("\n");
+ _mesa_log("GLSL IR for linked %s program %d:\n",
+ _mesa_shader_stage_to_string(shader->Stage),
+ shader_program->Name);
+ _mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL);
+ _mesa_log("\n\n");
+ }
+
+ prog->ExternalSamplersUsed = gl_external_samplers(prog);
+ _mesa_update_shader_textures_used(shader_program, prog);
+
+ nir_shader *nir = st_glsl_to_nir(st, prog, shader_program, shader->Stage);
+
+ set_st_program(prog, shader_program, nir);
+ prog->nir = nir;
+}
+
+extern "C" {
+
+bool
+st_link_nir(struct gl_context *ctx,
+ struct gl_shader_program *shader_program)
+{
+ struct st_context *st = st_context(ctx);
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *shader = shader_program->_LinkedShaders[i];
+ if (shader == NULL)
+ continue;
+
+ st_nir_get_mesa_program(ctx, shader_program, shader);
+ }
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *shader = shader_program->_LinkedShaders[i];
+ if (shader == NULL)
+ continue;
+
+ st_glsl_to_nir_post_opts(st, shader->Program, shader_program);
+
+ assert(shader->Program);
+ if (!ctx->Driver.ProgramStringNotify(ctx,
+ _mesa_shader_stage_to_program(i),
+ shader->Program)) {
+ _mesa_reference_program(ctx, &shader->Program, NULL);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Last third of preparing nir from glsl, which happens after shader
* variant lowering.
*/
void
NIR_PASS_V(nir, nir_lower_samplers, shader_program);
}
-struct gl_program *
-st_nir_get_mesa_program(struct gl_context *ctx,
- struct gl_shader_program *shader_program,
- struct gl_linked_shader *shader)
-{
- struct st_context *st = st_context(ctx);
- struct gl_program *prog;
-
- validate_ir_tree(shader->ir);
-
- prog = shader->Program;
-
- prog->Parameters = _mesa_new_parameter_list();
-
- _mesa_copy_linked_program_data(shader_program, shader);
- _mesa_generate_parameters_list_for_uniforms(ctx, shader_program, shader,
- prog->Parameters);
-
- if (ctx->_Shader->Flags & GLSL_DUMP) {
- _mesa_log("\n");
- _mesa_log("GLSL IR for linked %s program %d:\n",
- _mesa_shader_stage_to_string(shader->Stage),
- shader_program->Name);
- _mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL);
- _mesa_log("\n\n");
- }
-
- prog->ExternalSamplersUsed = gl_external_samplers(prog);
- _mesa_update_shader_textures_used(shader_program, prog);
-
- struct st_vertex_program *stvp;
- struct st_common_program *stp;
- struct st_fragment_program *stfp;
- struct st_compute_program *stcp;
-
- nir_shader *nir = st_glsl_to_nir(st, prog, shader_program, shader->Stage);
-
- switch (shader->Stage) {
- case MESA_SHADER_VERTEX:
- stvp = (struct st_vertex_program *)prog;
- stvp->shader_program = shader_program;
- stvp->tgsi.type = PIPE_SHADER_IR_NIR;
- stvp->tgsi.ir.nir = nir;
- break;
- case MESA_SHADER_GEOMETRY:
- case MESA_SHADER_TESS_CTRL:
- case MESA_SHADER_TESS_EVAL:
- stp = (struct st_common_program *)prog;
- stp->shader_program = shader_program;
- stp->tgsi.type = PIPE_SHADER_IR_NIR;
- stp->tgsi.ir.nir = nir;
- break;
- case MESA_SHADER_FRAGMENT:
- stfp = (struct st_fragment_program *)prog;
- stfp->shader_program = shader_program;
- stfp->tgsi.type = PIPE_SHADER_IR_NIR;
- stfp->tgsi.ir.nir = nir;
- break;
- case MESA_SHADER_COMPUTE:
- stcp = (struct st_compute_program *)prog;
- stcp->shader_program = shader_program;
- stcp->tgsi.ir_type = PIPE_SHADER_IR_NIR;
- stcp->tgsi.prog = nir_shader_clone(NULL, nir);
- break;
- default:
- assert(!"should not be reached");
- return NULL;
- }
-
-
- return prog;
-}
-
} /* extern "C" */