xref: /aosp_15_r20/external/mesa3d/src/mesa/main/pipelineobj.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright © 2013 Gregory Hainaut <[email protected]>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23  * IN THE SOFTWARE.
24  */
25 
26 /**
27  * \file pipelineobj.c
28  * \author Hainaut Gregory <[email protected]>
29  *
30  * Implementation of pipeline object related API functions. Based on
31  * GL_ARB_separate_shader_objects extension.
32  */
33 
34 #include <stdbool.h>
35 #include "util/glheader.h"
36 #include "main/context.h"
37 #include "main/draw_validate.h"
38 #include "main/enums.h"
39 #include "main/hash.h"
40 #include "main/mtypes.h"
41 #include "main/pipelineobj.h"
42 #include "main/shaderapi.h"
43 #include "main/shaderobj.h"
44 #include "main/state.h"
45 #include "main/transformfeedback.h"
46 #include "main/uniforms.h"
47 #include "compiler/glsl/glsl_parser_extras.h"
48 #include "compiler/glsl/ir_uniform.h"
49 #include "program/program.h"
50 #include "program/prog_parameter.h"
51 #include "util/ralloc.h"
52 #include "util/bitscan.h"
53 #include "api_exec_decl.h"
54 
55 /**
56  * Delete a pipeline object.
57  */
58 void
_mesa_delete_pipeline_object(struct gl_context * ctx,struct gl_pipeline_object * obj)59 _mesa_delete_pipeline_object(struct gl_context *ctx,
60                              struct gl_pipeline_object *obj)
61 {
62    unsigned i;
63 
64    for (i = 0; i < MESA_SHADER_STAGES; i++) {
65       _mesa_reference_program(ctx, &obj->CurrentProgram[i], NULL);
66       _mesa_reference_shader_program(ctx, &obj->ReferencedPrograms[i], NULL);
67    }
68 
69    _mesa_reference_shader_program(ctx, &obj->ActiveProgram, NULL);
70    free(obj->Label);
71    ralloc_free(obj);
72 }
73 
74 /**
75  * Allocate and initialize a new pipeline object.
76  */
77 static struct gl_pipeline_object *
_mesa_new_pipeline_object(struct gl_context * ctx,GLuint name)78 _mesa_new_pipeline_object(struct gl_context *ctx, GLuint name)
79 {
80    struct gl_pipeline_object *obj = rzalloc(NULL, struct gl_pipeline_object);
81    if (obj) {
82       obj->Name = name;
83       obj->RefCount = 1;
84       obj->Flags = _mesa_get_shader_flags();
85       obj->InfoLog = NULL;
86    }
87 
88    return obj;
89 }
90 
91 /**
92  * Initialize pipeline object state for given context.
93  */
94 void
_mesa_init_pipeline(struct gl_context * ctx)95 _mesa_init_pipeline(struct gl_context *ctx)
96 {
97    _mesa_InitHashTable(&ctx->Pipeline.Objects);
98 
99    ctx->Pipeline.Current = NULL;
100 
101    /* Install a default Pipeline */
102    ctx->Pipeline.Default = _mesa_new_pipeline_object(ctx, 0);
103    _mesa_reference_pipeline_object(ctx, &ctx->_Shader, ctx->Pipeline.Default);
104 }
105 
106 
107 /**
108  * Callback for deleting a pipeline object.  Called by _mesa_DeleteHashTable().
109  */
110 static void
delete_pipelineobj_cb(void * data,void * userData)111 delete_pipelineobj_cb(void *data, void *userData)
112 {
113    struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data;
114    struct gl_context *ctx = (struct gl_context *) userData;
115    _mesa_delete_pipeline_object(ctx, obj);
116 }
117 
118 
119 /**
120  * Free pipeline state for given context.
121  */
122 void
_mesa_free_pipeline_data(struct gl_context * ctx)123 _mesa_free_pipeline_data(struct gl_context *ctx)
124 {
125    _mesa_reference_pipeline_object(ctx, &ctx->_Shader, NULL);
126    _mesa_DeinitHashTable(&ctx->Pipeline.Objects, delete_pipelineobj_cb, ctx);
127    _mesa_delete_pipeline_object(ctx, ctx->Pipeline.Default);
128 }
129 
130 /**
131  * Look up the pipeline object for the given ID.
132  *
133  * \returns
134  * Either a pointer to the pipeline object with the specified ID or \c NULL for
135  * a non-existent ID.  The spec defines ID 0 as being technically
136  * non-existent.
137  */
138 struct gl_pipeline_object *
_mesa_lookup_pipeline_object(struct gl_context * ctx,GLuint id)139 _mesa_lookup_pipeline_object(struct gl_context *ctx, GLuint id)
140 {
141    if (id == 0)
142       return NULL;
143    else
144       return (struct gl_pipeline_object *)
145          _mesa_HashLookupLocked(&ctx->Pipeline.Objects, id);
146 }
147 
148 /**
149  * Add the given pipeline object to the pipeline object pool.
150  */
151 static void
save_pipeline_object(struct gl_context * ctx,struct gl_pipeline_object * obj)152 save_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
153 {
154    if (obj->Name > 0) {
155       _mesa_HashInsertLocked(&ctx->Pipeline.Objects, obj->Name, obj);
156    }
157 }
158 
159 /**
160  * Remove the given pipeline object from the pipeline object pool.
161  * Do not deallocate the pipeline object though.
162  */
163 static void
remove_pipeline_object(struct gl_context * ctx,struct gl_pipeline_object * obj)164 remove_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
165 {
166    if (obj->Name > 0) {
167       _mesa_HashRemoveLocked(&ctx->Pipeline.Objects, obj->Name);
168    }
169 }
170 
171 /**
172  * Set ptr to obj w/ reference counting.
173  * Note: this should only be called from the _mesa_reference_pipeline_object()
174  * inline function.
175  */
176 void
_mesa_reference_pipeline_object_(struct gl_context * ctx,struct gl_pipeline_object ** ptr,struct gl_pipeline_object * obj)177 _mesa_reference_pipeline_object_(struct gl_context *ctx,
178                                  struct gl_pipeline_object **ptr,
179                                  struct gl_pipeline_object *obj)
180 {
181    assert(*ptr != obj);
182 
183    if (*ptr) {
184       /* Unreference the old pipeline object */
185       struct gl_pipeline_object *oldObj = *ptr;
186 
187       assert(oldObj->RefCount > 0);
188       oldObj->RefCount--;
189 
190       if (oldObj->RefCount == 0) {
191          _mesa_delete_pipeline_object(ctx, oldObj);
192       }
193 
194       *ptr = NULL;
195    }
196    assert(!*ptr);
197 
198    if (obj) {
199       /* reference new pipeline object */
200       assert(obj->RefCount > 0);
201 
202       obj->RefCount++;
203       *ptr = obj;
204    }
205 }
206 
207 static void
use_program_stage(struct gl_context * ctx,GLenum type,struct gl_shader_program * shProg,struct gl_pipeline_object * pipe)208 use_program_stage(struct gl_context *ctx, GLenum type,
209                   struct gl_shader_program *shProg,
210                   struct gl_pipeline_object *pipe) {
211    gl_shader_stage stage = _mesa_shader_enum_to_shader_stage(type);
212    struct gl_program *prog = NULL;
213    if (shProg && shProg->_LinkedShaders[stage])
214       prog = shProg->_LinkedShaders[stage]->Program;
215 
216    _mesa_use_program(ctx, stage, shProg, prog, pipe);
217 }
218 
219 static void
use_program_stages(struct gl_context * ctx,struct gl_shader_program * shProg,GLbitfield stages,struct gl_pipeline_object * pipe)220 use_program_stages(struct gl_context *ctx, struct gl_shader_program *shProg,
221                    GLbitfield stages, struct gl_pipeline_object *pipe) {
222 
223    /* Enable individual stages from the program as requested by the
224     * application.  If there is no shader for a requested stage in the
225     * program, _mesa_use_shader_program will enable fixed-function processing
226     * as dictated by the spec.
227     *
228     * Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec
229     * says:
230     *
231     *     "If UseProgramStages is called with program set to zero or with a
232     *     program object that contains no executable code for the given
233     *     stages, it is as if the pipeline object has no programmable stage
234     *     configured for the indicated shader stages."
235     */
236    if ((stages & GL_VERTEX_SHADER_BIT) != 0)
237       use_program_stage(ctx, GL_VERTEX_SHADER, shProg, pipe);
238 
239    if ((stages & GL_FRAGMENT_SHADER_BIT) != 0)
240       use_program_stage(ctx, GL_FRAGMENT_SHADER, shProg, pipe);
241 
242    if ((stages & GL_GEOMETRY_SHADER_BIT) != 0)
243       use_program_stage(ctx, GL_GEOMETRY_SHADER, shProg, pipe);
244 
245    if ((stages & GL_TESS_CONTROL_SHADER_BIT) != 0)
246       use_program_stage(ctx, GL_TESS_CONTROL_SHADER, shProg, pipe);
247 
248    if ((stages & GL_TESS_EVALUATION_SHADER_BIT) != 0)
249       use_program_stage(ctx, GL_TESS_EVALUATION_SHADER, shProg, pipe);
250 
251    if ((stages & GL_COMPUTE_SHADER_BIT) != 0)
252       use_program_stage(ctx, GL_COMPUTE_SHADER, shProg, pipe);
253 
254    pipe->Validated = pipe->UserValidated = false;
255 
256    if (pipe == ctx->_Shader)
257       _mesa_update_valid_to_render_state(ctx);
258 }
259 
260 void GLAPIENTRY
_mesa_UseProgramStages_no_error(GLuint pipeline,GLbitfield stages,GLuint prog)261 _mesa_UseProgramStages_no_error(GLuint pipeline, GLbitfield stages,
262                                 GLuint prog)
263 {
264    GET_CURRENT_CONTEXT(ctx);
265 
266    struct gl_pipeline_object *pipe =
267       _mesa_lookup_pipeline_object(ctx, pipeline);
268    struct gl_shader_program *shProg = NULL;
269 
270    if (prog)
271       shProg = _mesa_lookup_shader_program(ctx, prog);
272 
273    /* Object is created by any Pipeline call but glGenProgramPipelines,
274     * glIsProgramPipeline and GetProgramPipelineInfoLog
275     */
276    pipe->EverBound = GL_TRUE;
277 
278    use_program_stages(ctx, shProg, stages, pipe);
279 }
280 
281 /**
282  * Bound program to severals stages of the pipeline
283  */
284 void GLAPIENTRY
_mesa_UseProgramStages(GLuint pipeline,GLbitfield stages,GLuint program)285 _mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program)
286 {
287    GET_CURRENT_CONTEXT(ctx);
288 
289    struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
290    struct gl_shader_program *shProg = NULL;
291    GLbitfield any_valid_stages;
292 
293    if (MESA_VERBOSE & VERBOSE_API)
294       _mesa_debug(ctx, "glUseProgramStages(%u, 0x%x, %u)\n",
295                   pipeline, stages, program);
296 
297    if (!pipe) {
298       _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgramStages(pipeline)");
299       return;
300    }
301 
302    /* Object is created by any Pipeline call but glGenProgramPipelines,
303     * glIsProgramPipeline and GetProgramPipelineInfoLog
304     */
305    pipe->EverBound = GL_TRUE;
306 
307    /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec says:
308     *
309     *     "If stages is not the special value ALL_SHADER_BITS, and has a bit
310     *     set that is not recognized, the error INVALID_VALUE is generated."
311     */
312    any_valid_stages = GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT;
313    if (_mesa_has_geometry_shaders(ctx))
314       any_valid_stages |= GL_GEOMETRY_SHADER_BIT;
315    if (_mesa_has_tessellation(ctx))
316       any_valid_stages |= GL_TESS_CONTROL_SHADER_BIT |
317                           GL_TESS_EVALUATION_SHADER_BIT;
318    if (_mesa_has_compute_shaders(ctx))
319       any_valid_stages |= GL_COMPUTE_SHADER_BIT;
320 
321    if (stages != GL_ALL_SHADER_BITS && (stages & ~any_valid_stages) != 0) {
322       _mesa_error(ctx, GL_INVALID_VALUE, "glUseProgramStages(Stages)");
323       return;
324    }
325 
326    /* Section 2.17.2 (Transform Feedback Primitive Capture) of the OpenGL 4.1
327     * spec says:
328     *
329     *     "The error INVALID_OPERATION is generated:
330     *
331     *      ...
332     *
333     *         - by UseProgramStages if the program pipeline object it refers
334     *           to is current and the current transform feedback object is
335     *           active and not paused;
336     */
337    if (ctx->_Shader == pipe) {
338       if (_mesa_is_xfb_active_and_unpaused(ctx)) {
339          _mesa_error(ctx, GL_INVALID_OPERATION,
340                "glUseProgramStages(transform feedback active)");
341          return;
342       }
343    }
344 
345    if (program) {
346       shProg = _mesa_lookup_shader_program_err(ctx, program,
347                                                "glUseProgramStages");
348       if (shProg == NULL)
349          return;
350 
351       /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec
352        * says:
353        *
354        *     "If the program object named by program was linked without the
355        *     PROGRAM_SEPARABLE parameter set, or was not linked successfully,
356        *     the error INVALID_OPERATION is generated and the corresponding
357        *     shader stages in the pipeline program pipeline object are not
358        *     modified."
359        */
360       if (!shProg->data->LinkStatus) {
361          _mesa_error(ctx, GL_INVALID_OPERATION,
362                      "glUseProgramStages(program not linked)");
363          return;
364       }
365 
366       if (!shProg->SeparateShader) {
367          _mesa_error(ctx, GL_INVALID_OPERATION,
368                      "glUseProgramStages(program wasn't linked with the "
369                      "PROGRAM_SEPARABLE flag)");
370          return;
371       }
372    }
373 
374    use_program_stages(ctx, shProg, stages, pipe);
375 }
376 
377 static ALWAYS_INLINE void
active_shader_program(struct gl_context * ctx,GLuint pipeline,GLuint program,bool no_error)378 active_shader_program(struct gl_context *ctx, GLuint pipeline, GLuint program,
379                       bool no_error)
380 {
381    struct gl_shader_program *shProg = NULL;
382    struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
383 
384    if (program) {
385       if (no_error) {
386          shProg = _mesa_lookup_shader_program(ctx, program);
387       } else {
388          shProg = _mesa_lookup_shader_program_err(ctx, program,
389                                                   "glActiveShaderProgram(program)");
390          if (shProg == NULL)
391             return;
392       }
393    }
394 
395    if (!no_error && !pipe) {
396       _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(pipeline)");
397       return;
398    }
399 
400    /* Object is created by any Pipeline call but glGenProgramPipelines,
401     * glIsProgramPipeline and GetProgramPipelineInfoLog
402     */
403    pipe->EverBound = GL_TRUE;
404 
405    if (!no_error && shProg != NULL && !shProg->data->LinkStatus) {
406       _mesa_error(ctx, GL_INVALID_OPERATION,
407             "glActiveShaderProgram(program %u not linked)", shProg->Name);
408       return;
409    }
410 
411    _mesa_reference_shader_program(ctx, &pipe->ActiveProgram, shProg);
412    if (pipe == ctx->_Shader)
413       _mesa_update_valid_to_render_state(ctx);
414 }
415 
416 void GLAPIENTRY
_mesa_ActiveShaderProgram_no_error(GLuint pipeline,GLuint program)417 _mesa_ActiveShaderProgram_no_error(GLuint pipeline, GLuint program)
418 {
419    GET_CURRENT_CONTEXT(ctx);
420    active_shader_program(ctx, pipeline, program, true);
421 }
422 
423 /**
424  * Use the named shader program for subsequent glUniform calls (if pipeline
425  * bound)
426  */
427 void GLAPIENTRY
_mesa_ActiveShaderProgram(GLuint pipeline,GLuint program)428 _mesa_ActiveShaderProgram(GLuint pipeline, GLuint program)
429 {
430    GET_CURRENT_CONTEXT(ctx);
431 
432    if (MESA_VERBOSE & VERBOSE_API)
433       _mesa_debug(ctx, "glActiveShaderProgram(%u, %u)\n", pipeline, program);
434 
435    active_shader_program(ctx, pipeline, program, false);
436 }
437 
438 static ALWAYS_INLINE void
bind_program_pipeline(struct gl_context * ctx,GLuint pipeline,bool no_error)439 bind_program_pipeline(struct gl_context *ctx, GLuint pipeline, bool no_error)
440 {
441    struct gl_pipeline_object *newObj = NULL;
442 
443    if (MESA_VERBOSE & VERBOSE_API)
444       _mesa_debug(ctx, "glBindProgramPipeline(%u)\n", pipeline);
445 
446    /* Rebinding the same pipeline object: no change.
447     */
448    if (ctx->_Shader->Name == pipeline)
449       return;
450 
451    /* Section 2.17.2 (Transform Feedback Primitive Capture) of the OpenGL 4.1
452     * spec says:
453     *
454     *     "The error INVALID_OPERATION is generated:
455     *
456     *      ...
457     *
458     *         - by BindProgramPipeline if the current transform feedback
459     *           object is active and not paused;
460     */
461    if (!no_error && _mesa_is_xfb_active_and_unpaused(ctx)) {
462       _mesa_error(ctx, GL_INVALID_OPERATION,
463             "glBindProgramPipeline(transform feedback active)");
464       return;
465    }
466 
467    /* Get pointer to new pipeline object (newObj)
468     */
469    if (pipeline) {
470       /* non-default pipeline object */
471       newObj = _mesa_lookup_pipeline_object(ctx, pipeline);
472       if (!no_error && !newObj) {
473          _mesa_error(ctx, GL_INVALID_OPERATION,
474                      "glBindProgramPipeline(non-gen name)");
475          return;
476       }
477 
478       /* Object is created by any Pipeline call but glGenProgramPipelines,
479        * glIsProgramPipeline and GetProgramPipelineInfoLog
480        */
481       newObj->EverBound = GL_TRUE;
482    }
483 
484    _mesa_bind_pipeline(ctx, newObj);
485 }
486 
487 void GLAPIENTRY
_mesa_BindProgramPipeline_no_error(GLuint pipeline)488 _mesa_BindProgramPipeline_no_error(GLuint pipeline)
489 {
490    GET_CURRENT_CONTEXT(ctx);
491    bind_program_pipeline(ctx, pipeline, true);
492 }
493 
494 /**
495  * Make program of the pipeline current
496  */
497 void GLAPIENTRY
_mesa_BindProgramPipeline(GLuint pipeline)498 _mesa_BindProgramPipeline(GLuint pipeline)
499 {
500    GET_CURRENT_CONTEXT(ctx);
501    bind_program_pipeline(ctx, pipeline, false);
502 }
503 
504 void
_mesa_bind_pipeline(struct gl_context * ctx,struct gl_pipeline_object * pipe)505 _mesa_bind_pipeline(struct gl_context *ctx,
506                     struct gl_pipeline_object *pipe)
507 {
508    int i;
509    /* First bind the Pipeline to pipeline binding point */
510    _mesa_reference_pipeline_object(ctx, &ctx->Pipeline.Current, pipe);
511 
512    /* Section 2.11.3 (Program Objects) of the OpenGL 4.1 spec says:
513     *
514     *     "If there is a current program object established by UseProgram,
515     *     that program is considered current for all stages. Otherwise, if
516     *     there is a bound program pipeline object (see section 2.11.4), the
517     *     program bound to the appropriate stage of the pipeline object is
518     *     considered current."
519     */
520    if (&ctx->Shader != ctx->_Shader) {
521       FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS, 0);
522 
523       if (pipe != NULL) {
524          /* Bound the pipeline to the current program and
525           * restore the pipeline state
526           */
527          _mesa_reference_pipeline_object(ctx, &ctx->_Shader, pipe);
528       } else {
529          /* Unbind the pipeline */
530          _mesa_reference_pipeline_object(ctx, &ctx->_Shader,
531                                          ctx->Pipeline.Default);
532       }
533 
534       for (i = 0; i < MESA_SHADER_STAGES; i++) {
535          struct gl_program *prog = ctx->_Shader->CurrentProgram[i];
536          if (prog) {
537             _mesa_program_init_subroutine_defaults(ctx, prog);
538          }
539       }
540 
541       _mesa_update_vertex_processing_mode(ctx);
542       _mesa_update_allow_draw_out_of_order(ctx);
543       _mesa_update_valid_to_render_state(ctx);
544    }
545 }
546 
547 /**
548  * Delete a set of pipeline objects.
549  *
550  * \param n      Number of pipeline objects to delete.
551  * \param ids    pipeline of \c n pipeline object IDs.
552  */
553 void GLAPIENTRY
_mesa_DeleteProgramPipelines(GLsizei n,const GLuint * pipelines)554 _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines)
555 {
556    GET_CURRENT_CONTEXT(ctx);
557    GLsizei i;
558 
559    if (MESA_VERBOSE & VERBOSE_API)
560       _mesa_debug(ctx, "glDeleteProgramPipelines(%d, %p)\n", n, pipelines);
561 
562    if (n < 0) {
563       _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgramPipelines(n<0)");
564       return;
565    }
566 
567    for (i = 0; i < n; i++) {
568       struct gl_pipeline_object *obj =
569          _mesa_lookup_pipeline_object(ctx, pipelines[i]);
570 
571       if (obj) {
572          assert(obj->Name == pipelines[i]);
573 
574          /* If the pipeline object is currently bound, the spec says "If an
575           * object that is currently bound is deleted, the binding for that
576           * object reverts to zero and no program pipeline object becomes
577           * current."
578           */
579          if (obj == ctx->Pipeline.Current) {
580             _mesa_BindProgramPipeline(0);
581          }
582 
583          /* The ID is immediately freed for re-use */
584          remove_pipeline_object(ctx, obj);
585 
586          /* Unreference the pipeline object.
587           * If refcount hits zero, the object will be deleted.
588           */
589          _mesa_reference_pipeline_object(ctx, &obj, NULL);
590       }
591    }
592 }
593 
594 /**
595  * Generate a set of unique pipeline object IDs and store them in \c pipelines.
596  * \param n       Number of IDs to generate.
597  * \param pipelines  pipeline of \c n locations to store the IDs.
598  */
599 static void
create_program_pipelines(struct gl_context * ctx,GLsizei n,GLuint * pipelines,bool dsa)600 create_program_pipelines(struct gl_context *ctx, GLsizei n, GLuint *pipelines,
601                          bool dsa)
602 {
603    const char *func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines";
604    GLint i;
605 
606    if (!pipelines)
607       return;
608 
609    _mesa_HashFindFreeKeys(&ctx->Pipeline.Objects, pipelines, n);
610 
611    for (i = 0; i < n; i++) {
612       struct gl_pipeline_object *obj;
613 
614       obj = _mesa_new_pipeline_object(ctx, pipelines[i]);
615       if (!obj) {
616          _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
617          return;
618       }
619 
620       if (dsa) {
621          /* make dsa-allocated objects behave like program objects */
622          obj->EverBound = GL_TRUE;
623       }
624 
625       save_pipeline_object(ctx, obj);
626    }
627 }
628 
629 static void
create_program_pipelines_err(struct gl_context * ctx,GLsizei n,GLuint * pipelines,bool dsa)630 create_program_pipelines_err(struct gl_context *ctx, GLsizei n,
631                              GLuint *pipelines, bool dsa)
632 {
633    const char *func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines";
634 
635    if (n < 0) {
636       _mesa_error(ctx, GL_INVALID_VALUE, "%s (n < 0)", func);
637       return;
638    }
639 
640    create_program_pipelines(ctx, n, pipelines, dsa);
641 }
642 
643 void GLAPIENTRY
_mesa_GenProgramPipelines_no_error(GLsizei n,GLuint * pipelines)644 _mesa_GenProgramPipelines_no_error(GLsizei n, GLuint *pipelines)
645 {
646    GET_CURRENT_CONTEXT(ctx);
647    create_program_pipelines(ctx, n, pipelines, false);
648 }
649 
650 void GLAPIENTRY
_mesa_GenProgramPipelines(GLsizei n,GLuint * pipelines)651 _mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines)
652 {
653    GET_CURRENT_CONTEXT(ctx);
654 
655    if (MESA_VERBOSE & VERBOSE_API)
656       _mesa_debug(ctx, "glGenProgramPipelines(%d, %p)\n", n, pipelines);
657 
658    create_program_pipelines_err(ctx, n, pipelines, false);
659 }
660 
661 void GLAPIENTRY
_mesa_CreateProgramPipelines_no_error(GLsizei n,GLuint * pipelines)662 _mesa_CreateProgramPipelines_no_error(GLsizei n, GLuint *pipelines)
663 {
664    GET_CURRENT_CONTEXT(ctx);
665    create_program_pipelines(ctx, n, pipelines, true);
666 }
667 
668 void GLAPIENTRY
_mesa_CreateProgramPipelines(GLsizei n,GLuint * pipelines)669 _mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines)
670 {
671    GET_CURRENT_CONTEXT(ctx);
672 
673    if (MESA_VERBOSE & VERBOSE_API)
674       _mesa_debug(ctx, "glCreateProgramPipelines(%d, %p)\n", n, pipelines);
675 
676    create_program_pipelines_err(ctx, n, pipelines, true);
677 }
678 
679 /**
680  * Determine if ID is the name of an pipeline object.
681  *
682  * \param id  ID of the potential pipeline object.
683  * \return  \c GL_TRUE if \c id is the name of a pipeline object,
684  *          \c GL_FALSE otherwise.
685  */
686 GLboolean GLAPIENTRY
_mesa_IsProgramPipeline(GLuint pipeline)687 _mesa_IsProgramPipeline(GLuint pipeline)
688 {
689    GET_CURRENT_CONTEXT(ctx);
690 
691    if (MESA_VERBOSE & VERBOSE_API)
692       _mesa_debug(ctx, "glIsProgramPipeline(%u)\n", pipeline);
693 
694    struct gl_pipeline_object *obj = _mesa_lookup_pipeline_object(ctx, pipeline);
695    if (obj == NULL)
696       return GL_FALSE;
697 
698    return obj->EverBound;
699 }
700 
701 /**
702  * glGetProgramPipelineiv() - get pipeline shader state.
703  */
704 void GLAPIENTRY
_mesa_GetProgramPipelineiv(GLuint pipeline,GLenum pname,GLint * params)705 _mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params)
706 {
707    GET_CURRENT_CONTEXT(ctx);
708    struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
709 
710    if (MESA_VERBOSE & VERBOSE_API)
711       _mesa_debug(ctx, "glGetProgramPipelineiv(%u, %d, %p)\n",
712                   pipeline, pname, params);
713 
714    /* Are geometry shaders available in this context?
715     */
716    const bool has_gs = _mesa_has_geometry_shaders(ctx);
717    const bool has_tess = _mesa_has_tessellation(ctx);
718 
719    if (!pipe) {
720       _mesa_error(ctx, GL_INVALID_OPERATION,
721                   "glGetProgramPipelineiv(pipeline)");
722       return;
723    }
724 
725    /* Object is created by any Pipeline call but glGenProgramPipelines,
726     * glIsProgramPipeline and GetProgramPipelineInfoLog
727     */
728    pipe->EverBound = GL_TRUE;
729 
730    switch (pname) {
731    case GL_ACTIVE_PROGRAM:
732       *params = pipe->ActiveProgram ? pipe->ActiveProgram->Name : 0;
733       return;
734    case GL_INFO_LOG_LENGTH:
735       *params = (pipe->InfoLog && pipe->InfoLog[0] != '\0') ?
736          strlen(pipe->InfoLog) + 1 : 0;
737       return;
738    case GL_VALIDATE_STATUS:
739       *params = pipe->UserValidated;
740       return;
741    case GL_VERTEX_SHADER:
742       *params = pipe->CurrentProgram[MESA_SHADER_VERTEX]
743          ? pipe->CurrentProgram[MESA_SHADER_VERTEX]->Id : 0;
744       return;
745    case GL_TESS_EVALUATION_SHADER:
746       if (!has_tess)
747          break;
748       *params = pipe->CurrentProgram[MESA_SHADER_TESS_EVAL]
749          ? pipe->CurrentProgram[MESA_SHADER_TESS_EVAL]->Id : 0;
750       return;
751    case GL_TESS_CONTROL_SHADER:
752       if (!has_tess)
753          break;
754       *params = pipe->CurrentProgram[MESA_SHADER_TESS_CTRL]
755          ? pipe->CurrentProgram[MESA_SHADER_TESS_CTRL]->Id : 0;
756       return;
757    case GL_GEOMETRY_SHADER:
758       if (!has_gs)
759          break;
760       *params = pipe->CurrentProgram[MESA_SHADER_GEOMETRY]
761          ? pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Id : 0;
762       return;
763    case GL_FRAGMENT_SHADER:
764       *params = pipe->CurrentProgram[MESA_SHADER_FRAGMENT]
765          ? pipe->CurrentProgram[MESA_SHADER_FRAGMENT]->Id : 0;
766       return;
767    case GL_COMPUTE_SHADER:
768       if (!_mesa_has_compute_shaders(ctx))
769          break;
770       *params = pipe->CurrentProgram[MESA_SHADER_COMPUTE]
771          ? pipe->CurrentProgram[MESA_SHADER_COMPUTE]->Id : 0;
772       return;
773    default:
774       break;
775    }
776 
777    _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramPipelineiv(pname=%s)",
778                _mesa_enum_to_string(pname));
779 }
780 
781 /**
782  * Determines whether every stage in a linked program is active in the
783  * specified pipeline.
784  */
785 static bool
program_stages_all_active(struct gl_pipeline_object * pipe,const struct gl_program * prog)786 program_stages_all_active(struct gl_pipeline_object *pipe,
787                           const struct gl_program *prog)
788 {
789    bool status = true;
790 
791    if (!prog)
792       return true;
793 
794    unsigned mask = prog->sh.data->linked_stages;
795    while (mask) {
796       const int i = u_bit_scan(&mask);
797       if (pipe->CurrentProgram[i]) {
798          if (prog->Id != pipe->CurrentProgram[i]->Id) {
799             status = false;
800          }
801       } else {
802          status = false;
803       }
804    }
805 
806    if (!status) {
807       pipe->InfoLog = ralloc_asprintf(pipe,
808                                       "Program %d is not active for all "
809                                       "shaders that was linked",
810                                       prog->Id);
811    }
812 
813    return status;
814 }
815 
816 static bool
program_stages_interleaved_illegally(const struct gl_pipeline_object * pipe)817 program_stages_interleaved_illegally(const struct gl_pipeline_object *pipe)
818 {
819    unsigned prev_linked_stages = 0;
820 
821    /* Look for programs bound to stages: A -> B -> A, with any intervening
822     * sequence of unrelated programs or empty stages.
823     */
824    for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
825       struct gl_program *cur = pipe->CurrentProgram[i];
826 
827       /* Empty stages anywhere in the pipe are OK.  Also we can be confident
828        * that if the linked_stages mask matches we are looking at the same
829        * linked program because a previous validation call to
830        * program_stages_all_active() will have already failed if two different
831        * programs with the sames stages linked are not active for all linked
832        * stages.
833        */
834       if (!cur || cur->sh.data->linked_stages == prev_linked_stages)
835          continue;
836 
837       if (prev_linked_stages) {
838          /* We've seen an A -> B transition; look at the rest of the pipe
839           * to see if we ever see A again.
840           */
841          if (prev_linked_stages >> (i + 1))
842             return true;
843       }
844 
845       prev_linked_stages = cur->sh.data->linked_stages;
846    }
847 
848    return false;
849 }
850 
851 extern GLboolean
_mesa_validate_program_pipeline(struct gl_context * ctx,struct gl_pipeline_object * pipe)852 _mesa_validate_program_pipeline(struct gl_context* ctx,
853                                 struct gl_pipeline_object *pipe)
854 {
855    unsigned i;
856    bool program_empty = true;
857 
858    pipe->Validated = GL_FALSE;
859 
860    /* Release and reset the info log.
861     */
862    if (pipe->InfoLog != NULL)
863       ralloc_free(pipe->InfoLog);
864 
865    pipe->InfoLog = NULL;
866 
867    /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
868     * OpenGL 4.1 spec says:
869     *
870     *     "[INVALID_OPERATION] is generated by any command that transfers
871     *     vertices to the GL if:
872     *
873     *         - A program object is active for at least one, but not all of
874     *           the shader stages that were present when the program was
875     *           linked."
876     *
877     * For each possible program stage, verify that the program bound to that
878     * stage has all of its stages active.  In other words, if the program
879     * bound to the vertex stage also has a fragment shader, the fragment
880     * shader must also be bound to the fragment stage.
881     */
882    for (i = 0; i < MESA_SHADER_STAGES; i++) {
883       if (!program_stages_all_active(pipe, pipe->CurrentProgram[i])) {
884          return GL_FALSE;
885       }
886    }
887 
888    /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
889     * OpenGL 4.1 spec says:
890     *
891     *     "[INVALID_OPERATION] is generated by any command that transfers
892     *     vertices to the GL if:
893     *
894     *         ...
895     *
896     *         - One program object is active for at least two shader stages
897     *           and a second program is active for a shader stage between two
898     *           stages for which the first program was active."
899     */
900    if (program_stages_interleaved_illegally(pipe)) {
901       pipe->InfoLog =
902          ralloc_strdup(pipe,
903                        "Program is active for multiple shader stages with an "
904                        "intervening stage provided by another program");
905       return GL_FALSE;
906    }
907 
908    /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
909     * OpenGL 4.1 spec says:
910     *
911     *     "[INVALID_OPERATION] is generated by any command that transfers
912     *     vertices to the GL if:
913     *
914     *         ...
915     *
916     *         - There is an active program for tessellation control,
917     *           tessellation evaluation, or geometry stages with corresponding
918     *           executable shader, but there is no active program with
919     *           executable vertex shader."
920     */
921    if (!pipe->CurrentProgram[MESA_SHADER_VERTEX]
922        && (pipe->CurrentProgram[MESA_SHADER_GEOMETRY] ||
923            pipe->CurrentProgram[MESA_SHADER_TESS_CTRL] ||
924            pipe->CurrentProgram[MESA_SHADER_TESS_EVAL])) {
925       pipe->InfoLog = ralloc_strdup(pipe, "Program lacks a vertex shader");
926       return GL_FALSE;
927    }
928 
929    /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
930     * OpenGL 4.1 spec says:
931     *
932     *     "[INVALID_OPERATION] is generated by any command that transfers
933     *     vertices to the GL if:
934     *
935     *         ...
936     *
937     *         - There is no current program object specified by UseProgram,
938     *           there is a current program pipeline object, and the current
939     *           program for any shader stage has been relinked since being
940     *           applied to the pipeline object via UseProgramStages with the
941     *           PROGRAM_SEPARABLE parameter set to FALSE.
942     */
943    for (i = 0; i < MESA_SHADER_STAGES; i++) {
944       if (pipe->CurrentProgram[i] &&
945           !pipe->CurrentProgram[i]->info.separate_shader) {
946          pipe->InfoLog = ralloc_asprintf(pipe,
947                                          "Program %d was relinked without "
948                                          "PROGRAM_SEPARABLE state",
949                                          pipe->CurrentProgram[i]->Id);
950          return GL_FALSE;
951       }
952    }
953 
954    /* Section 11.1.3.11 (Validation) of the OpenGL 4.5 spec says:
955     *
956     *    "An INVALID_OPERATION error is generated by any command that trans-
957     *    fers vertices to the GL or launches compute work if the current set
958     *    of active program objects cannot be executed, for reasons including:
959     *
960     *       ...
961     *
962     *       - There is no current program object specified by UseProgram,
963     *         there is a current program pipeline object, and that object is
964     *         empty (no executable code is installed for any stage).
965     */
966    for (i = 0; i < MESA_SHADER_STAGES; i++) {
967       if (pipe->CurrentProgram[i]) {
968          program_empty = false;
969          break;
970       }
971    }
972 
973    if (program_empty) {
974       return GL_FALSE;
975    }
976 
977    /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
978     * OpenGL 4.1 spec says:
979     *
980     *     "[INVALID_OPERATION] is generated by any command that transfers
981     *     vertices to the GL if:
982     *
983     *         ...
984     *
985     *         - Any two active samplers in the current program object are of
986     *           different types, but refer to the same texture image unit.
987     *
988     *         - The number of active samplers in the program exceeds the
989     *           maximum number of texture image units allowed."
990     */
991    if (!_mesa_sampler_uniforms_pipeline_are_valid(pipe))
992       return GL_FALSE;
993 
994    /* Validate inputs against outputs, this cannot be done during linking
995     * since programs have been linked separately from each other.
996     *
997     * Section 11.1.3.11 (Validation) of the OpenGL 4.5 Core Profile spec says:
998     *
999     *     "Separable program objects may have validation failures that cannot be
1000     *     detected without the complete program pipeline. Mismatched interfaces,
1001     *     improper usage of program objects together, and the same
1002     *     state-dependent failures can result in validation errors for such
1003     *     program objects."
1004     *
1005     * OpenGL ES 3.1 specification has the same text.
1006     *
1007     * Section 11.1.3.11 (Validation) of the OpenGL ES spec also says:
1008     *
1009     *    An INVALID_OPERATION error is generated by any command that transfers
1010     *    vertices to the GL or launches compute work if the current set of
1011     *    active program objects cannot be executed, for reasons including:
1012     *
1013     *    * The current program pipeline object contains a shader interface
1014     *      that doesn't have an exact match (see section 7.4.1)
1015     *
1016     * Based on this, only perform the most-strict checking on ES or when the
1017     * application has created a debug context.
1018     */
1019    if ((_mesa_is_gles(ctx) || (ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT)) &&
1020        !_mesa_validate_pipeline_io(pipe)) {
1021       if (_mesa_is_gles(ctx))
1022          return GL_FALSE;
1023 
1024       static GLuint msg_id = 0;
1025 
1026       _mesa_gl_debugf(ctx, &msg_id,
1027                       MESA_DEBUG_SOURCE_API,
1028                       MESA_DEBUG_TYPE_PORTABILITY,
1029                       MESA_DEBUG_SEVERITY_MEDIUM,
1030                       "glValidateProgramPipeline: pipeline %u does not meet "
1031                       "strict OpenGL ES 3.1 requirements and may not be "
1032                       "portable across desktop hardware\n",
1033                       pipe->Name);
1034    }
1035 
1036    pipe->Validated = GL_TRUE;
1037    return GL_TRUE;
1038 }
1039 
1040 /**
1041  * Check compatibility of pipeline's program
1042  */
1043 void GLAPIENTRY
_mesa_ValidateProgramPipeline(GLuint pipeline)1044 _mesa_ValidateProgramPipeline(GLuint pipeline)
1045 {
1046    GET_CURRENT_CONTEXT(ctx);
1047 
1048    if (MESA_VERBOSE & VERBOSE_API)
1049       _mesa_debug(ctx, "glValidateProgramPipeline(%u)\n", pipeline);
1050 
1051    struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
1052 
1053    if (!pipe) {
1054       _mesa_error(ctx, GL_INVALID_OPERATION,
1055                   "glValidateProgramPipeline(pipeline)");
1056       return;
1057    }
1058 
1059    _mesa_validate_program_pipeline(ctx, pipe);
1060    pipe->UserValidated = pipe->Validated;
1061 }
1062 
1063 void GLAPIENTRY
_mesa_GetProgramPipelineInfoLog(GLuint pipeline,GLsizei bufSize,GLsizei * length,GLchar * infoLog)1064 _mesa_GetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize,
1065                                 GLsizei *length, GLchar *infoLog)
1066 {
1067    GET_CURRENT_CONTEXT(ctx);
1068 
1069    if (MESA_VERBOSE & VERBOSE_API)
1070       _mesa_debug(ctx, "glGetProgramPipelineInfoLog(%u, %d, %p, %p)\n",
1071                   pipeline, bufSize, length, infoLog);
1072 
1073    struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
1074 
1075    if (!pipe) {
1076       _mesa_error(ctx, GL_INVALID_VALUE,
1077                   "glGetProgramPipelineInfoLog(pipeline)");
1078       return;
1079    }
1080 
1081    if (bufSize < 0) {
1082       _mesa_error(ctx, GL_INVALID_VALUE,
1083                   "glGetProgramPipelineInfoLog(bufSize)");
1084       return;
1085    }
1086 
1087    _mesa_copy_string(infoLog, bufSize, length, pipe->InfoLog);
1088 }
1089