1af69d88dSmrg/* 2af69d88dSmrg * Mesa 3-D graphics library 3af69d88dSmrg * 4af69d88dSmrg * Copyright © 2013 Gregory Hainaut <gregory.hainaut@gmail.com> 5af69d88dSmrg * 6af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 7af69d88dSmrg * copy of this software and associated documentation files (the "Software"), 8af69d88dSmrg * to deal in the Software without restriction, including without limitation 9af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the 11af69d88dSmrg * Software is furnished to do so, subject to the following conditions: 12af69d88dSmrg * 13af69d88dSmrg * The above copyright notice and this permission notice (including the next 14af69d88dSmrg * paragraph) shall be included in all copies or substantial portions of the 15af69d88dSmrg * Software. 16af69d88dSmrg * 17af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18af69d88dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21af69d88dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22af69d88dSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23af69d88dSmrg * IN THE SOFTWARE. 24af69d88dSmrg */ 25af69d88dSmrg 26af69d88dSmrg/** 27af69d88dSmrg * \file pipelineobj.c 28af69d88dSmrg * \author Hainaut Gregory <gregory.hainaut@gmail.com> 29af69d88dSmrg * 30af69d88dSmrg * Implementation of pipeline object related API functions. Based on 31af69d88dSmrg * GL_ARB_separate_shader_objects extension. 32af69d88dSmrg */ 33af69d88dSmrg 3401e04c3fSmrg#include <stdbool.h> 35af69d88dSmrg#include "main/glheader.h" 36af69d88dSmrg#include "main/context.h" 377ec681f3Smrg#include "main/draw_validate.h" 38af69d88dSmrg#include "main/enums.h" 39af69d88dSmrg#include "main/hash.h" 40af69d88dSmrg#include "main/mtypes.h" 41af69d88dSmrg#include "main/pipelineobj.h" 42af69d88dSmrg#include "main/shaderapi.h" 43af69d88dSmrg#include "main/shaderobj.h" 4401e04c3fSmrg#include "main/state.h" 45af69d88dSmrg#include "main/transformfeedback.h" 46af69d88dSmrg#include "main/uniforms.h" 4701e04c3fSmrg#include "compiler/glsl/glsl_parser_extras.h" 4801e04c3fSmrg#include "compiler/glsl/ir_uniform.h" 49af69d88dSmrg#include "program/program.h" 50af69d88dSmrg#include "program/prog_parameter.h" 51af69d88dSmrg#include "util/ralloc.h" 527ec681f3Smrg#include "util/bitscan.h" 53af69d88dSmrg 54af69d88dSmrg/** 55af69d88dSmrg * Delete a pipeline object. 56af69d88dSmrg */ 57af69d88dSmrgvoid 58af69d88dSmrg_mesa_delete_pipeline_object(struct gl_context *ctx, 59af69d88dSmrg struct gl_pipeline_object *obj) 60af69d88dSmrg{ 61af69d88dSmrg unsigned i; 62af69d88dSmrg 6301e04c3fSmrg for (i = 0; i < MESA_SHADER_STAGES; i++) { 6401e04c3fSmrg _mesa_reference_program(ctx, &obj->CurrentProgram[i], NULL); 6501e04c3fSmrg _mesa_reference_shader_program(ctx, &obj->ReferencedPrograms[i], NULL); 6601e04c3fSmrg } 67af69d88dSmrg 68af69d88dSmrg _mesa_reference_shader_program(ctx, &obj->ActiveProgram, NULL); 6901e04c3fSmrg free(obj->Label); 70af69d88dSmrg ralloc_free(obj); 71af69d88dSmrg} 72af69d88dSmrg 73af69d88dSmrg/** 74af69d88dSmrg * Allocate and initialize a new pipeline object. 75af69d88dSmrg */ 76af69d88dSmrgstatic struct gl_pipeline_object * 77af69d88dSmrg_mesa_new_pipeline_object(struct gl_context *ctx, GLuint name) 78af69d88dSmrg{ 79af69d88dSmrg struct gl_pipeline_object *obj = rzalloc(NULL, struct gl_pipeline_object); 80af69d88dSmrg if (obj) { 81af69d88dSmrg obj->Name = name; 82af69d88dSmrg obj->RefCount = 1; 83af69d88dSmrg obj->Flags = _mesa_get_shader_flags(); 84af69d88dSmrg obj->InfoLog = NULL; 85af69d88dSmrg } 86af69d88dSmrg 87af69d88dSmrg return obj; 88af69d88dSmrg} 89af69d88dSmrg 90af69d88dSmrg/** 91af69d88dSmrg * Initialize pipeline object state for given context. 92af69d88dSmrg */ 93af69d88dSmrgvoid 94af69d88dSmrg_mesa_init_pipeline(struct gl_context *ctx) 95af69d88dSmrg{ 96af69d88dSmrg ctx->Pipeline.Objects = _mesa_NewHashTable(); 97af69d88dSmrg 98af69d88dSmrg ctx->Pipeline.Current = NULL; 99af69d88dSmrg 100af69d88dSmrg /* Install a default Pipeline */ 101af69d88dSmrg ctx->Pipeline.Default = _mesa_new_pipeline_object(ctx, 0); 102af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->_Shader, ctx->Pipeline.Default); 103af69d88dSmrg} 104af69d88dSmrg 105af69d88dSmrg 106af69d88dSmrg/** 107af69d88dSmrg * Callback for deleting a pipeline object. Called by _mesa_HashDeleteAll(). 108af69d88dSmrg */ 109af69d88dSmrgstatic void 1107ec681f3Smrgdelete_pipelineobj_cb(void *data, void *userData) 111af69d88dSmrg{ 112af69d88dSmrg struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data; 113af69d88dSmrg struct gl_context *ctx = (struct gl_context *) userData; 114af69d88dSmrg _mesa_delete_pipeline_object(ctx, obj); 115af69d88dSmrg} 116af69d88dSmrg 117af69d88dSmrg 118af69d88dSmrg/** 119af69d88dSmrg * Free pipeline state for given context. 120af69d88dSmrg */ 121af69d88dSmrgvoid 122af69d88dSmrg_mesa_free_pipeline_data(struct gl_context *ctx) 123af69d88dSmrg{ 124af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->_Shader, NULL); 125af69d88dSmrg 126af69d88dSmrg _mesa_HashDeleteAll(ctx->Pipeline.Objects, delete_pipelineobj_cb, ctx); 127af69d88dSmrg _mesa_DeleteHashTable(ctx->Pipeline.Objects); 128af69d88dSmrg 129af69d88dSmrg _mesa_delete_pipeline_object(ctx, ctx->Pipeline.Default); 130af69d88dSmrg} 131af69d88dSmrg 132af69d88dSmrg/** 133af69d88dSmrg * Look up the pipeline object for the given ID. 134af69d88dSmrg * 135af69d88dSmrg * \returns 136af69d88dSmrg * Either a pointer to the pipeline object with the specified ID or \c NULL for 137af69d88dSmrg * a non-existent ID. The spec defines ID 0 as being technically 138af69d88dSmrg * non-existent. 139af69d88dSmrg */ 14001e04c3fSmrgstruct gl_pipeline_object * 14101e04c3fSmrg_mesa_lookup_pipeline_object(struct gl_context *ctx, GLuint id) 142af69d88dSmrg{ 143af69d88dSmrg if (id == 0) 144af69d88dSmrg return NULL; 145af69d88dSmrg else 146af69d88dSmrg return (struct gl_pipeline_object *) 14701e04c3fSmrg _mesa_HashLookupLocked(ctx->Pipeline.Objects, id); 148af69d88dSmrg} 149af69d88dSmrg 150af69d88dSmrg/** 151af69d88dSmrg * Add the given pipeline object to the pipeline object pool. 152af69d88dSmrg */ 153af69d88dSmrgstatic void 154af69d88dSmrgsave_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj) 155af69d88dSmrg{ 156af69d88dSmrg if (obj->Name > 0) { 1577ec681f3Smrg _mesa_HashInsertLocked(ctx->Pipeline.Objects, obj->Name, obj, true); 158af69d88dSmrg } 159af69d88dSmrg} 160af69d88dSmrg 161af69d88dSmrg/** 162af69d88dSmrg * Remove the given pipeline object from the pipeline object pool. 163af69d88dSmrg * Do not deallocate the pipeline object though. 164af69d88dSmrg */ 165af69d88dSmrgstatic void 166af69d88dSmrgremove_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj) 167af69d88dSmrg{ 168af69d88dSmrg if (obj->Name > 0) { 16901e04c3fSmrg _mesa_HashRemoveLocked(ctx->Pipeline.Objects, obj->Name); 170af69d88dSmrg } 171af69d88dSmrg} 172af69d88dSmrg 173af69d88dSmrg/** 174af69d88dSmrg * Set ptr to obj w/ reference counting. 175af69d88dSmrg * Note: this should only be called from the _mesa_reference_pipeline_object() 176af69d88dSmrg * inline function. 177af69d88dSmrg */ 178af69d88dSmrgvoid 179af69d88dSmrg_mesa_reference_pipeline_object_(struct gl_context *ctx, 180af69d88dSmrg struct gl_pipeline_object **ptr, 181af69d88dSmrg struct gl_pipeline_object *obj) 182af69d88dSmrg{ 183af69d88dSmrg assert(*ptr != obj); 184af69d88dSmrg 185af69d88dSmrg if (*ptr) { 186af69d88dSmrg /* Unreference the old pipeline object */ 187af69d88dSmrg struct gl_pipeline_object *oldObj = *ptr; 188af69d88dSmrg 18901e04c3fSmrg assert(oldObj->RefCount > 0); 190af69d88dSmrg oldObj->RefCount--; 191af69d88dSmrg 19201e04c3fSmrg if (oldObj->RefCount == 0) { 193af69d88dSmrg _mesa_delete_pipeline_object(ctx, oldObj); 194af69d88dSmrg } 195af69d88dSmrg 196af69d88dSmrg *ptr = NULL; 197af69d88dSmrg } 19801e04c3fSmrg assert(!*ptr); 199af69d88dSmrg 200af69d88dSmrg if (obj) { 201af69d88dSmrg /* reference new pipeline object */ 20201e04c3fSmrg assert(obj->RefCount > 0); 20301e04c3fSmrg 20401e04c3fSmrg obj->RefCount++; 20501e04c3fSmrg *ptr = obj; 206af69d88dSmrg } 207af69d88dSmrg} 208af69d88dSmrg 20901e04c3fSmrgstatic void 21001e04c3fSmrguse_program_stage(struct gl_context *ctx, GLenum type, 21101e04c3fSmrg struct gl_shader_program *shProg, 21201e04c3fSmrg struct gl_pipeline_object *pipe) { 21301e04c3fSmrg gl_shader_stage stage = _mesa_shader_enum_to_shader_stage(type); 21401e04c3fSmrg struct gl_program *prog = NULL; 21501e04c3fSmrg if (shProg && shProg->_LinkedShaders[stage]) 21601e04c3fSmrg prog = shProg->_LinkedShaders[stage]->Program; 21701e04c3fSmrg 21801e04c3fSmrg _mesa_use_program(ctx, stage, shProg, prog, pipe); 21901e04c3fSmrg} 22001e04c3fSmrg 22101e04c3fSmrgstatic void 22201e04c3fSmrguse_program_stages(struct gl_context *ctx, struct gl_shader_program *shProg, 22301e04c3fSmrg GLbitfield stages, struct gl_pipeline_object *pipe) { 22401e04c3fSmrg 22501e04c3fSmrg /* Enable individual stages from the program as requested by the 22601e04c3fSmrg * application. If there is no shader for a requested stage in the 22701e04c3fSmrg * program, _mesa_use_shader_program will enable fixed-function processing 22801e04c3fSmrg * as dictated by the spec. 22901e04c3fSmrg * 23001e04c3fSmrg * Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec 23101e04c3fSmrg * says: 23201e04c3fSmrg * 23301e04c3fSmrg * "If UseProgramStages is called with program set to zero or with a 23401e04c3fSmrg * program object that contains no executable code for the given 23501e04c3fSmrg * stages, it is as if the pipeline object has no programmable stage 23601e04c3fSmrg * configured for the indicated shader stages." 23701e04c3fSmrg */ 23801e04c3fSmrg if ((stages & GL_VERTEX_SHADER_BIT) != 0) 23901e04c3fSmrg use_program_stage(ctx, GL_VERTEX_SHADER, shProg, pipe); 24001e04c3fSmrg 24101e04c3fSmrg if ((stages & GL_FRAGMENT_SHADER_BIT) != 0) 24201e04c3fSmrg use_program_stage(ctx, GL_FRAGMENT_SHADER, shProg, pipe); 24301e04c3fSmrg 24401e04c3fSmrg if ((stages & GL_GEOMETRY_SHADER_BIT) != 0) 24501e04c3fSmrg use_program_stage(ctx, GL_GEOMETRY_SHADER, shProg, pipe); 24601e04c3fSmrg 24701e04c3fSmrg if ((stages & GL_TESS_CONTROL_SHADER_BIT) != 0) 24801e04c3fSmrg use_program_stage(ctx, GL_TESS_CONTROL_SHADER, shProg, pipe); 24901e04c3fSmrg 25001e04c3fSmrg if ((stages & GL_TESS_EVALUATION_SHADER_BIT) != 0) 25101e04c3fSmrg use_program_stage(ctx, GL_TESS_EVALUATION_SHADER, shProg, pipe); 25201e04c3fSmrg 25301e04c3fSmrg if ((stages & GL_COMPUTE_SHADER_BIT) != 0) 25401e04c3fSmrg use_program_stage(ctx, GL_COMPUTE_SHADER, shProg, pipe); 25501e04c3fSmrg 2567ec681f3Smrg pipe->Validated = pipe->UserValidated = false; 2577ec681f3Smrg 2587ec681f3Smrg if (pipe == ctx->_Shader) 2597ec681f3Smrg _mesa_update_valid_to_render_state(ctx); 26001e04c3fSmrg} 26101e04c3fSmrg 26201e04c3fSmrgvoid GLAPIENTRY 26301e04c3fSmrg_mesa_UseProgramStages_no_error(GLuint pipeline, GLbitfield stages, 26401e04c3fSmrg GLuint prog) 26501e04c3fSmrg{ 26601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 26701e04c3fSmrg 26801e04c3fSmrg struct gl_pipeline_object *pipe = 26901e04c3fSmrg _mesa_lookup_pipeline_object(ctx, pipeline); 27001e04c3fSmrg struct gl_shader_program *shProg = NULL; 27101e04c3fSmrg 27201e04c3fSmrg if (prog) 27301e04c3fSmrg shProg = _mesa_lookup_shader_program(ctx, prog); 27401e04c3fSmrg 27501e04c3fSmrg /* Object is created by any Pipeline call but glGenProgramPipelines, 27601e04c3fSmrg * glIsProgramPipeline and GetProgramPipelineInfoLog 27701e04c3fSmrg */ 27801e04c3fSmrg pipe->EverBound = GL_TRUE; 27901e04c3fSmrg 28001e04c3fSmrg use_program_stages(ctx, shProg, stages, pipe); 28101e04c3fSmrg} 28201e04c3fSmrg 283af69d88dSmrg/** 284af69d88dSmrg * Bound program to severals stages of the pipeline 285af69d88dSmrg */ 286af69d88dSmrgvoid GLAPIENTRY 287af69d88dSmrg_mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) 288af69d88dSmrg{ 289af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 290af69d88dSmrg 29101e04c3fSmrg struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); 292af69d88dSmrg struct gl_shader_program *shProg = NULL; 293af69d88dSmrg GLbitfield any_valid_stages; 294af69d88dSmrg 29501e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 29601e04c3fSmrg _mesa_debug(ctx, "glUseProgramStages(%u, 0x%x, %u)\n", 29701e04c3fSmrg pipeline, stages, program); 29801e04c3fSmrg 299af69d88dSmrg if (!pipe) { 300af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgramStages(pipeline)"); 301af69d88dSmrg return; 302af69d88dSmrg } 303af69d88dSmrg 304af69d88dSmrg /* Object is created by any Pipeline call but glGenProgramPipelines, 305af69d88dSmrg * glIsProgramPipeline and GetProgramPipelineInfoLog 306af69d88dSmrg */ 307af69d88dSmrg pipe->EverBound = GL_TRUE; 308af69d88dSmrg 309af69d88dSmrg /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec says: 310af69d88dSmrg * 311af69d88dSmrg * "If stages is not the special value ALL_SHADER_BITS, and has a bit 312af69d88dSmrg * set that is not recognized, the error INVALID_VALUE is generated." 313af69d88dSmrg */ 314af69d88dSmrg any_valid_stages = GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT; 315af69d88dSmrg if (_mesa_has_geometry_shaders(ctx)) 316af69d88dSmrg any_valid_stages |= GL_GEOMETRY_SHADER_BIT; 31701e04c3fSmrg if (_mesa_has_tessellation(ctx)) 31801e04c3fSmrg any_valid_stages |= GL_TESS_CONTROL_SHADER_BIT | 31901e04c3fSmrg GL_TESS_EVALUATION_SHADER_BIT; 32001e04c3fSmrg if (_mesa_has_compute_shaders(ctx)) 32101e04c3fSmrg any_valid_stages |= GL_COMPUTE_SHADER_BIT; 322af69d88dSmrg 323af69d88dSmrg if (stages != GL_ALL_SHADER_BITS && (stages & ~any_valid_stages) != 0) { 324af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glUseProgramStages(Stages)"); 325af69d88dSmrg return; 326af69d88dSmrg } 327af69d88dSmrg 328af69d88dSmrg /* Section 2.17.2 (Transform Feedback Primitive Capture) of the OpenGL 4.1 329af69d88dSmrg * spec says: 330af69d88dSmrg * 331af69d88dSmrg * "The error INVALID_OPERATION is generated: 332af69d88dSmrg * 333af69d88dSmrg * ... 334af69d88dSmrg * 335af69d88dSmrg * - by UseProgramStages if the program pipeline object it refers 336af69d88dSmrg * to is current and the current transform feedback object is 337af69d88dSmrg * active and not paused; 338af69d88dSmrg */ 339af69d88dSmrg if (ctx->_Shader == pipe) { 340af69d88dSmrg if (_mesa_is_xfb_active_and_unpaused(ctx)) { 341af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 342af69d88dSmrg "glUseProgramStages(transform feedback active)"); 343af69d88dSmrg return; 344af69d88dSmrg } 345af69d88dSmrg } 346af69d88dSmrg 347af69d88dSmrg if (program) { 348af69d88dSmrg shProg = _mesa_lookup_shader_program_err(ctx, program, 349af69d88dSmrg "glUseProgramStages"); 350af69d88dSmrg if (shProg == NULL) 351af69d88dSmrg return; 352af69d88dSmrg 353af69d88dSmrg /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec 354af69d88dSmrg * says: 355af69d88dSmrg * 356af69d88dSmrg * "If the program object named by program was linked without the 357af69d88dSmrg * PROGRAM_SEPARABLE parameter set, or was not linked successfully, 358af69d88dSmrg * the error INVALID_OPERATION is generated and the corresponding 359af69d88dSmrg * shader stages in the pipeline program pipeline object are not 360af69d88dSmrg * modified." 361af69d88dSmrg */ 36201e04c3fSmrg if (!shProg->data->LinkStatus) { 363af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 364af69d88dSmrg "glUseProgramStages(program not linked)"); 365af69d88dSmrg return; 366af69d88dSmrg } 367af69d88dSmrg 368af69d88dSmrg if (!shProg->SeparateShader) { 369af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 370af69d88dSmrg "glUseProgramStages(program wasn't linked with the " 371af69d88dSmrg "PROGRAM_SEPARABLE flag)"); 372af69d88dSmrg return; 373af69d88dSmrg } 374af69d88dSmrg } 375af69d88dSmrg 37601e04c3fSmrg use_program_stages(ctx, shProg, stages, pipe); 377af69d88dSmrg} 378af69d88dSmrg 37901e04c3fSmrgstatic ALWAYS_INLINE void 38001e04c3fSmrgactive_shader_program(struct gl_context *ctx, GLuint pipeline, GLuint program, 38101e04c3fSmrg bool no_error) 382af69d88dSmrg{ 383af69d88dSmrg struct gl_shader_program *shProg = NULL; 38401e04c3fSmrg struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); 385af69d88dSmrg 38601e04c3fSmrg if (program) { 38701e04c3fSmrg if (no_error) { 38801e04c3fSmrg shProg = _mesa_lookup_shader_program(ctx, program); 38901e04c3fSmrg } else { 39001e04c3fSmrg shProg = _mesa_lookup_shader_program_err(ctx, program, 39101e04c3fSmrg "glActiveShaderProgram(program)"); 39201e04c3fSmrg if (shProg == NULL) 39301e04c3fSmrg return; 39401e04c3fSmrg } 395af69d88dSmrg } 396af69d88dSmrg 39701e04c3fSmrg if (!no_error && !pipe) { 398af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(pipeline)"); 399af69d88dSmrg return; 400af69d88dSmrg } 401af69d88dSmrg 402af69d88dSmrg /* Object is created by any Pipeline call but glGenProgramPipelines, 403af69d88dSmrg * glIsProgramPipeline and GetProgramPipelineInfoLog 404af69d88dSmrg */ 405af69d88dSmrg pipe->EverBound = GL_TRUE; 406af69d88dSmrg 40701e04c3fSmrg if (!no_error && shProg != NULL && !shProg->data->LinkStatus) { 408af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 409af69d88dSmrg "glActiveShaderProgram(program %u not linked)", shProg->Name); 410af69d88dSmrg return; 411af69d88dSmrg } 412af69d88dSmrg 413af69d88dSmrg _mesa_reference_shader_program(ctx, &pipe->ActiveProgram, shProg); 4147ec681f3Smrg if (pipe == ctx->_Shader) 4157ec681f3Smrg _mesa_update_valid_to_render_state(ctx); 416af69d88dSmrg} 417af69d88dSmrg 41801e04c3fSmrgvoid GLAPIENTRY 41901e04c3fSmrg_mesa_ActiveShaderProgram_no_error(GLuint pipeline, GLuint program) 42001e04c3fSmrg{ 42101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 42201e04c3fSmrg active_shader_program(ctx, pipeline, program, true); 42301e04c3fSmrg} 42401e04c3fSmrg 425af69d88dSmrg/** 42601e04c3fSmrg * Use the named shader program for subsequent glUniform calls (if pipeline 42701e04c3fSmrg * bound) 428af69d88dSmrg */ 429af69d88dSmrgvoid GLAPIENTRY 43001e04c3fSmrg_mesa_ActiveShaderProgram(GLuint pipeline, GLuint program) 431af69d88dSmrg{ 432af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 43301e04c3fSmrg 43401e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 43501e04c3fSmrg _mesa_debug(ctx, "glActiveShaderProgram(%u, %u)\n", pipeline, program); 43601e04c3fSmrg 43701e04c3fSmrg active_shader_program(ctx, pipeline, program, false); 43801e04c3fSmrg} 43901e04c3fSmrg 44001e04c3fSmrgstatic ALWAYS_INLINE void 44101e04c3fSmrgbind_program_pipeline(struct gl_context *ctx, GLuint pipeline, bool no_error) 44201e04c3fSmrg{ 443af69d88dSmrg struct gl_pipeline_object *newObj = NULL; 444af69d88dSmrg 44501e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 44601e04c3fSmrg _mesa_debug(ctx, "glBindProgramPipeline(%u)\n", pipeline); 44701e04c3fSmrg 448af69d88dSmrg /* Rebinding the same pipeline object: no change. 449af69d88dSmrg */ 450af69d88dSmrg if (ctx->_Shader->Name == pipeline) 451af69d88dSmrg return; 452af69d88dSmrg 453af69d88dSmrg /* Section 2.17.2 (Transform Feedback Primitive Capture) of the OpenGL 4.1 454af69d88dSmrg * spec says: 455af69d88dSmrg * 456af69d88dSmrg * "The error INVALID_OPERATION is generated: 457af69d88dSmrg * 458af69d88dSmrg * ... 459af69d88dSmrg * 460af69d88dSmrg * - by BindProgramPipeline if the current transform feedback 461af69d88dSmrg * object is active and not paused; 462af69d88dSmrg */ 46301e04c3fSmrg if (!no_error && _mesa_is_xfb_active_and_unpaused(ctx)) { 464af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 465af69d88dSmrg "glBindProgramPipeline(transform feedback active)"); 466af69d88dSmrg return; 467af69d88dSmrg } 468af69d88dSmrg 469af69d88dSmrg /* Get pointer to new pipeline object (newObj) 470af69d88dSmrg */ 471af69d88dSmrg if (pipeline) { 472af69d88dSmrg /* non-default pipeline object */ 47301e04c3fSmrg newObj = _mesa_lookup_pipeline_object(ctx, pipeline); 47401e04c3fSmrg if (!no_error && !newObj) { 475af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 476af69d88dSmrg "glBindProgramPipeline(non-gen name)"); 477af69d88dSmrg return; 478af69d88dSmrg } 479af69d88dSmrg 480af69d88dSmrg /* Object is created by any Pipeline call but glGenProgramPipelines, 481af69d88dSmrg * glIsProgramPipeline and GetProgramPipelineInfoLog 482af69d88dSmrg */ 483af69d88dSmrg newObj->EverBound = GL_TRUE; 484af69d88dSmrg } 485af69d88dSmrg 486af69d88dSmrg _mesa_bind_pipeline(ctx, newObj); 487af69d88dSmrg} 488af69d88dSmrg 48901e04c3fSmrgvoid GLAPIENTRY 49001e04c3fSmrg_mesa_BindProgramPipeline_no_error(GLuint pipeline) 49101e04c3fSmrg{ 49201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 49301e04c3fSmrg bind_program_pipeline(ctx, pipeline, true); 49401e04c3fSmrg} 49501e04c3fSmrg 49601e04c3fSmrg/** 49701e04c3fSmrg * Make program of the pipeline current 49801e04c3fSmrg */ 49901e04c3fSmrgvoid GLAPIENTRY 50001e04c3fSmrg_mesa_BindProgramPipeline(GLuint pipeline) 50101e04c3fSmrg{ 50201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 50301e04c3fSmrg bind_program_pipeline(ctx, pipeline, false); 50401e04c3fSmrg} 50501e04c3fSmrg 506af69d88dSmrgvoid 507af69d88dSmrg_mesa_bind_pipeline(struct gl_context *ctx, 508af69d88dSmrg struct gl_pipeline_object *pipe) 509af69d88dSmrg{ 51001e04c3fSmrg int i; 511af69d88dSmrg /* First bind the Pipeline to pipeline binding point */ 512af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->Pipeline.Current, pipe); 513af69d88dSmrg 514af69d88dSmrg /* Section 2.11.3 (Program Objects) of the OpenGL 4.1 spec says: 515af69d88dSmrg * 516af69d88dSmrg * "If there is a current program object established by UseProgram, 517af69d88dSmrg * that program is considered current for all stages. Otherwise, if 518af69d88dSmrg * there is a bound program pipeline object (see section 2.11.4), the 519af69d88dSmrg * program bound to the appropriate stage of the pipeline object is 520af69d88dSmrg * considered current." 521af69d88dSmrg */ 522af69d88dSmrg if (&ctx->Shader != ctx->_Shader) { 5237ec681f3Smrg FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS, 0); 52401e04c3fSmrg 525af69d88dSmrg if (pipe != NULL) { 526af69d88dSmrg /* Bound the pipeline to the current program and 527af69d88dSmrg * restore the pipeline state 528af69d88dSmrg */ 529af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->_Shader, pipe); 530af69d88dSmrg } else { 531af69d88dSmrg /* Unbind the pipeline */ 532af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->_Shader, 533af69d88dSmrg ctx->Pipeline.Default); 534af69d88dSmrg } 535af69d88dSmrg 53601e04c3fSmrg for (i = 0; i < MESA_SHADER_STAGES; i++) { 53701e04c3fSmrg struct gl_program *prog = ctx->_Shader->CurrentProgram[i]; 53801e04c3fSmrg if (prog) { 53901e04c3fSmrg _mesa_program_init_subroutine_defaults(ctx, prog); 54001e04c3fSmrg } 54101e04c3fSmrg } 542af69d88dSmrg 54301e04c3fSmrg _mesa_update_vertex_processing_mode(ctx); 5447ec681f3Smrg _mesa_update_allow_draw_out_of_order(ctx); 5457ec681f3Smrg _mesa_update_valid_to_render_state(ctx); 546af69d88dSmrg } 547af69d88dSmrg} 548af69d88dSmrg 549af69d88dSmrg/** 550af69d88dSmrg * Delete a set of pipeline objects. 551af69d88dSmrg * 552af69d88dSmrg * \param n Number of pipeline objects to delete. 553af69d88dSmrg * \param ids pipeline of \c n pipeline object IDs. 554af69d88dSmrg */ 555af69d88dSmrgvoid GLAPIENTRY 556af69d88dSmrg_mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines) 557af69d88dSmrg{ 558af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 559af69d88dSmrg GLsizei i; 560af69d88dSmrg 56101e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 56201e04c3fSmrg _mesa_debug(ctx, "glDeleteProgramPipelines(%d, %p)\n", n, pipelines); 56301e04c3fSmrg 564af69d88dSmrg if (n < 0) { 565af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgramPipelines(n<0)"); 566af69d88dSmrg return; 567af69d88dSmrg } 568af69d88dSmrg 569af69d88dSmrg for (i = 0; i < n; i++) { 570af69d88dSmrg struct gl_pipeline_object *obj = 57101e04c3fSmrg _mesa_lookup_pipeline_object(ctx, pipelines[i]); 572af69d88dSmrg 573af69d88dSmrg if (obj) { 57401e04c3fSmrg assert(obj->Name == pipelines[i]); 575af69d88dSmrg 576af69d88dSmrg /* If the pipeline object is currently bound, the spec says "If an 577af69d88dSmrg * object that is currently bound is deleted, the binding for that 578af69d88dSmrg * object reverts to zero and no program pipeline object becomes 579af69d88dSmrg * current." 580af69d88dSmrg */ 581af69d88dSmrg if (obj == ctx->Pipeline.Current) { 582af69d88dSmrg _mesa_BindProgramPipeline(0); 583af69d88dSmrg } 584af69d88dSmrg 585af69d88dSmrg /* The ID is immediately freed for re-use */ 586af69d88dSmrg remove_pipeline_object(ctx, obj); 587af69d88dSmrg 588af69d88dSmrg /* Unreference the pipeline object. 589af69d88dSmrg * If refcount hits zero, the object will be deleted. 590af69d88dSmrg */ 591af69d88dSmrg _mesa_reference_pipeline_object(ctx, &obj, NULL); 592af69d88dSmrg } 593af69d88dSmrg } 594af69d88dSmrg} 595af69d88dSmrg 596af69d88dSmrg/** 597af69d88dSmrg * Generate a set of unique pipeline object IDs and store them in \c pipelines. 598af69d88dSmrg * \param n Number of IDs to generate. 599af69d88dSmrg * \param pipelines pipeline of \c n locations to store the IDs. 600af69d88dSmrg */ 60101e04c3fSmrgstatic void 60201e04c3fSmrgcreate_program_pipelines(struct gl_context *ctx, GLsizei n, GLuint *pipelines, 60301e04c3fSmrg bool dsa) 604af69d88dSmrg{ 60501e04c3fSmrg const char *func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines"; 606af69d88dSmrg GLint i; 607af69d88dSmrg 60801e04c3fSmrg if (!pipelines) 609af69d88dSmrg return; 610af69d88dSmrg 6117ec681f3Smrg _mesa_HashFindFreeKeys(ctx->Pipeline.Objects, pipelines, n); 612af69d88dSmrg 613af69d88dSmrg for (i = 0; i < n; i++) { 614af69d88dSmrg struct gl_pipeline_object *obj; 615af69d88dSmrg 6167ec681f3Smrg obj = _mesa_new_pipeline_object(ctx, pipelines[i]); 617af69d88dSmrg if (!obj) { 61801e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); 619af69d88dSmrg return; 620af69d88dSmrg } 621af69d88dSmrg 62201e04c3fSmrg if (dsa) { 62301e04c3fSmrg /* make dsa-allocated objects behave like program objects */ 62401e04c3fSmrg obj->EverBound = GL_TRUE; 62501e04c3fSmrg } 62601e04c3fSmrg 627af69d88dSmrg save_pipeline_object(ctx, obj); 628af69d88dSmrg } 62901e04c3fSmrg} 63001e04c3fSmrg 63101e04c3fSmrgstatic void 63201e04c3fSmrgcreate_program_pipelines_err(struct gl_context *ctx, GLsizei n, 63301e04c3fSmrg GLuint *pipelines, bool dsa) 63401e04c3fSmrg{ 63501e04c3fSmrg const char *func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines"; 63601e04c3fSmrg 63701e04c3fSmrg if (n < 0) { 63801e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s (n < 0)", func); 63901e04c3fSmrg return; 64001e04c3fSmrg } 641af69d88dSmrg 64201e04c3fSmrg create_program_pipelines(ctx, n, pipelines, dsa); 64301e04c3fSmrg} 64401e04c3fSmrg 64501e04c3fSmrgvoid GLAPIENTRY 64601e04c3fSmrg_mesa_GenProgramPipelines_no_error(GLsizei n, GLuint *pipelines) 64701e04c3fSmrg{ 64801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 64901e04c3fSmrg create_program_pipelines(ctx, n, pipelines, false); 65001e04c3fSmrg} 65101e04c3fSmrg 65201e04c3fSmrgvoid GLAPIENTRY 65301e04c3fSmrg_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines) 65401e04c3fSmrg{ 65501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 65601e04c3fSmrg 65701e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 65801e04c3fSmrg _mesa_debug(ctx, "glGenProgramPipelines(%d, %p)\n", n, pipelines); 65901e04c3fSmrg 66001e04c3fSmrg create_program_pipelines_err(ctx, n, pipelines, false); 66101e04c3fSmrg} 66201e04c3fSmrg 66301e04c3fSmrgvoid GLAPIENTRY 66401e04c3fSmrg_mesa_CreateProgramPipelines_no_error(GLsizei n, GLuint *pipelines) 66501e04c3fSmrg{ 66601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 66701e04c3fSmrg create_program_pipelines(ctx, n, pipelines, true); 66801e04c3fSmrg} 66901e04c3fSmrg 67001e04c3fSmrgvoid GLAPIENTRY 67101e04c3fSmrg_mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines) 67201e04c3fSmrg{ 67301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 67401e04c3fSmrg 67501e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 67601e04c3fSmrg _mesa_debug(ctx, "glCreateProgramPipelines(%d, %p)\n", n, pipelines); 67701e04c3fSmrg 67801e04c3fSmrg create_program_pipelines_err(ctx, n, pipelines, true); 679af69d88dSmrg} 680af69d88dSmrg 681af69d88dSmrg/** 682af69d88dSmrg * Determine if ID is the name of an pipeline object. 683af69d88dSmrg * 684af69d88dSmrg * \param id ID of the potential pipeline object. 685af69d88dSmrg * \return \c GL_TRUE if \c id is the name of a pipeline object, 686af69d88dSmrg * \c GL_FALSE otherwise. 687af69d88dSmrg */ 688af69d88dSmrgGLboolean GLAPIENTRY 689af69d88dSmrg_mesa_IsProgramPipeline(GLuint pipeline) 690af69d88dSmrg{ 691af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 692af69d88dSmrg 69301e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 69401e04c3fSmrg _mesa_debug(ctx, "glIsProgramPipeline(%u)\n", pipeline); 69501e04c3fSmrg 69601e04c3fSmrg struct gl_pipeline_object *obj = _mesa_lookup_pipeline_object(ctx, pipeline); 697af69d88dSmrg if (obj == NULL) 698af69d88dSmrg return GL_FALSE; 699af69d88dSmrg 700af69d88dSmrg return obj->EverBound; 701af69d88dSmrg} 702af69d88dSmrg 703af69d88dSmrg/** 704af69d88dSmrg * glGetProgramPipelineiv() - get pipeline shader state. 705af69d88dSmrg */ 706af69d88dSmrgvoid GLAPIENTRY 707af69d88dSmrg_mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params) 708af69d88dSmrg{ 709af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 71001e04c3fSmrg struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); 71101e04c3fSmrg 71201e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 71301e04c3fSmrg _mesa_debug(ctx, "glGetProgramPipelineiv(%u, %d, %p)\n", 71401e04c3fSmrg pipeline, pname, params); 715af69d88dSmrg 716af69d88dSmrg /* Are geometry shaders available in this context? 717af69d88dSmrg */ 718af69d88dSmrg const bool has_gs = _mesa_has_geometry_shaders(ctx); 71901e04c3fSmrg const bool has_tess = _mesa_has_tessellation(ctx); 720af69d88dSmrg 721af69d88dSmrg if (!pipe) { 722af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 723af69d88dSmrg "glGetProgramPipelineiv(pipeline)"); 724af69d88dSmrg return; 725af69d88dSmrg } 726af69d88dSmrg 727af69d88dSmrg /* Object is created by any Pipeline call but glGenProgramPipelines, 728af69d88dSmrg * glIsProgramPipeline and GetProgramPipelineInfoLog 729af69d88dSmrg */ 730af69d88dSmrg pipe->EverBound = GL_TRUE; 731af69d88dSmrg 732af69d88dSmrg switch (pname) { 733af69d88dSmrg case GL_ACTIVE_PROGRAM: 734af69d88dSmrg *params = pipe->ActiveProgram ? pipe->ActiveProgram->Name : 0; 735af69d88dSmrg return; 736af69d88dSmrg case GL_INFO_LOG_LENGTH: 73701e04c3fSmrg *params = (pipe->InfoLog && pipe->InfoLog[0] != '\0') ? 73801e04c3fSmrg strlen(pipe->InfoLog) + 1 : 0; 739af69d88dSmrg return; 740af69d88dSmrg case GL_VALIDATE_STATUS: 7417ec681f3Smrg *params = pipe->UserValidated; 742af69d88dSmrg return; 743af69d88dSmrg case GL_VERTEX_SHADER: 744af69d88dSmrg *params = pipe->CurrentProgram[MESA_SHADER_VERTEX] 74501e04c3fSmrg ? pipe->CurrentProgram[MESA_SHADER_VERTEX]->Id : 0; 746af69d88dSmrg return; 747af69d88dSmrg case GL_TESS_EVALUATION_SHADER: 74801e04c3fSmrg if (!has_tess) 74901e04c3fSmrg break; 75001e04c3fSmrg *params = pipe->CurrentProgram[MESA_SHADER_TESS_EVAL] 75101e04c3fSmrg ? pipe->CurrentProgram[MESA_SHADER_TESS_EVAL]->Id : 0; 75201e04c3fSmrg return; 753af69d88dSmrg case GL_TESS_CONTROL_SHADER: 75401e04c3fSmrg if (!has_tess) 75501e04c3fSmrg break; 75601e04c3fSmrg *params = pipe->CurrentProgram[MESA_SHADER_TESS_CTRL] 75701e04c3fSmrg ? pipe->CurrentProgram[MESA_SHADER_TESS_CTRL]->Id : 0; 75801e04c3fSmrg return; 759af69d88dSmrg case GL_GEOMETRY_SHADER: 760af69d88dSmrg if (!has_gs) 761af69d88dSmrg break; 762af69d88dSmrg *params = pipe->CurrentProgram[MESA_SHADER_GEOMETRY] 76301e04c3fSmrg ? pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Id : 0; 764af69d88dSmrg return; 765af69d88dSmrg case GL_FRAGMENT_SHADER: 766af69d88dSmrg *params = pipe->CurrentProgram[MESA_SHADER_FRAGMENT] 76701e04c3fSmrg ? pipe->CurrentProgram[MESA_SHADER_FRAGMENT]->Id : 0; 76801e04c3fSmrg return; 76901e04c3fSmrg case GL_COMPUTE_SHADER: 77001e04c3fSmrg if (!_mesa_has_compute_shaders(ctx)) 77101e04c3fSmrg break; 77201e04c3fSmrg *params = pipe->CurrentProgram[MESA_SHADER_COMPUTE] 77301e04c3fSmrg ? pipe->CurrentProgram[MESA_SHADER_COMPUTE]->Id : 0; 774af69d88dSmrg return; 775af69d88dSmrg default: 776af69d88dSmrg break; 777af69d88dSmrg } 778af69d88dSmrg 779af69d88dSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramPipelineiv(pname=%s)", 78001e04c3fSmrg _mesa_enum_to_string(pname)); 781af69d88dSmrg} 782af69d88dSmrg 783af69d88dSmrg/** 784af69d88dSmrg * Determines whether every stage in a linked program is active in the 785af69d88dSmrg * specified pipeline. 786af69d88dSmrg */ 787af69d88dSmrgstatic bool 788af69d88dSmrgprogram_stages_all_active(struct gl_pipeline_object *pipe, 78901e04c3fSmrg const struct gl_program *prog) 790af69d88dSmrg{ 791af69d88dSmrg bool status = true; 792af69d88dSmrg 793af69d88dSmrg if (!prog) 794af69d88dSmrg return true; 795af69d88dSmrg 79601e04c3fSmrg unsigned mask = prog->sh.data->linked_stages; 79701e04c3fSmrg while (mask) { 79801e04c3fSmrg const int i = u_bit_scan(&mask); 79901e04c3fSmrg if (pipe->CurrentProgram[i]) { 80001e04c3fSmrg if (prog->Id != pipe->CurrentProgram[i]->Id) { 801af69d88dSmrg status = false; 802af69d88dSmrg } 80301e04c3fSmrg } else { 80401e04c3fSmrg status = false; 805af69d88dSmrg } 806af69d88dSmrg } 807af69d88dSmrg 808af69d88dSmrg if (!status) { 809af69d88dSmrg pipe->InfoLog = ralloc_asprintf(pipe, 810af69d88dSmrg "Program %d is not active for all " 811af69d88dSmrg "shaders that was linked", 81201e04c3fSmrg prog->Id); 813af69d88dSmrg } 814af69d88dSmrg 815af69d88dSmrg return status; 816af69d88dSmrg} 817af69d88dSmrg 81801e04c3fSmrgstatic bool 81901e04c3fSmrgprogram_stages_interleaved_illegally(const struct gl_pipeline_object *pipe) 82001e04c3fSmrg{ 82101e04c3fSmrg unsigned prev_linked_stages = 0; 82201e04c3fSmrg 82301e04c3fSmrg /* Look for programs bound to stages: A -> B -> A, with any intervening 82401e04c3fSmrg * sequence of unrelated programs or empty stages. 82501e04c3fSmrg */ 82601e04c3fSmrg for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { 82701e04c3fSmrg struct gl_program *cur = pipe->CurrentProgram[i]; 82801e04c3fSmrg 82901e04c3fSmrg /* Empty stages anywhere in the pipe are OK. Also we can be confident 83001e04c3fSmrg * that if the linked_stages mask matches we are looking at the same 83101e04c3fSmrg * linked program because a previous validation call to 83201e04c3fSmrg * program_stages_all_active() will have already failed if two different 83301e04c3fSmrg * programs with the sames stages linked are not active for all linked 83401e04c3fSmrg * stages. 83501e04c3fSmrg */ 83601e04c3fSmrg if (!cur || cur->sh.data->linked_stages == prev_linked_stages) 83701e04c3fSmrg continue; 83801e04c3fSmrg 83901e04c3fSmrg if (prev_linked_stages) { 84001e04c3fSmrg /* We've seen an A -> B transition; look at the rest of the pipe 84101e04c3fSmrg * to see if we ever see A again. 84201e04c3fSmrg */ 84301e04c3fSmrg if (prev_linked_stages >> (i + 1)) 84401e04c3fSmrg return true; 84501e04c3fSmrg } 84601e04c3fSmrg 84701e04c3fSmrg prev_linked_stages = cur->sh.data->linked_stages; 84801e04c3fSmrg } 84901e04c3fSmrg 85001e04c3fSmrg return false; 85101e04c3fSmrg} 85201e04c3fSmrg 853af69d88dSmrgextern GLboolean 854af69d88dSmrg_mesa_validate_program_pipeline(struct gl_context* ctx, 85501e04c3fSmrg struct gl_pipeline_object *pipe) 856af69d88dSmrg{ 857af69d88dSmrg unsigned i; 85801e04c3fSmrg bool program_empty = true; 859af69d88dSmrg 860af69d88dSmrg pipe->Validated = GL_FALSE; 861af69d88dSmrg 862af69d88dSmrg /* Release and reset the info log. 863af69d88dSmrg */ 864af69d88dSmrg if (pipe->InfoLog != NULL) 865af69d88dSmrg ralloc_free(pipe->InfoLog); 866af69d88dSmrg 867af69d88dSmrg pipe->InfoLog = NULL; 868af69d88dSmrg 869af69d88dSmrg /* Section 2.11.11 (Shader Execution), subheading "Validation," of the 870af69d88dSmrg * OpenGL 4.1 spec says: 871af69d88dSmrg * 872af69d88dSmrg * "[INVALID_OPERATION] is generated by any command that transfers 873af69d88dSmrg * vertices to the GL if: 874af69d88dSmrg * 875af69d88dSmrg * - A program object is active for at least one, but not all of 876af69d88dSmrg * the shader stages that were present when the program was 877af69d88dSmrg * linked." 878af69d88dSmrg * 879af69d88dSmrg * For each possible program stage, verify that the program bound to that 880af69d88dSmrg * stage has all of its stages active. In other words, if the program 881af69d88dSmrg * bound to the vertex stage also has a fragment shader, the fragment 882af69d88dSmrg * shader must also be bound to the fragment stage. 883af69d88dSmrg */ 884af69d88dSmrg for (i = 0; i < MESA_SHADER_STAGES; i++) { 885af69d88dSmrg if (!program_stages_all_active(pipe, pipe->CurrentProgram[i])) { 88601e04c3fSmrg return GL_FALSE; 887af69d88dSmrg } 888af69d88dSmrg } 889af69d88dSmrg 890af69d88dSmrg /* Section 2.11.11 (Shader Execution), subheading "Validation," of the 891af69d88dSmrg * OpenGL 4.1 spec says: 892af69d88dSmrg * 893af69d88dSmrg * "[INVALID_OPERATION] is generated by any command that transfers 894af69d88dSmrg * vertices to the GL if: 895af69d88dSmrg * 896af69d88dSmrg * ... 897af69d88dSmrg * 898af69d88dSmrg * - One program object is active for at least two shader stages 899af69d88dSmrg * and a second program is active for a shader stage between two 900af69d88dSmrg * stages for which the first program was active." 901af69d88dSmrg */ 90201e04c3fSmrg if (program_stages_interleaved_illegally(pipe)) { 90301e04c3fSmrg pipe->InfoLog = 90401e04c3fSmrg ralloc_strdup(pipe, 90501e04c3fSmrg "Program is active for multiple shader stages with an " 90601e04c3fSmrg "intervening stage provided by another program"); 90701e04c3fSmrg return GL_FALSE; 908af69d88dSmrg } 909af69d88dSmrg 910af69d88dSmrg /* Section 2.11.11 (Shader Execution), subheading "Validation," of the 911af69d88dSmrg * OpenGL 4.1 spec says: 912af69d88dSmrg * 913af69d88dSmrg * "[INVALID_OPERATION] is generated by any command that transfers 914af69d88dSmrg * vertices to the GL if: 915af69d88dSmrg * 916af69d88dSmrg * ... 917af69d88dSmrg * 918af69d88dSmrg * - There is an active program for tessellation control, 919af69d88dSmrg * tessellation evaluation, or geometry stages with corresponding 920af69d88dSmrg * executable shader, but there is no active program with 921af69d88dSmrg * executable vertex shader." 922af69d88dSmrg */ 923af69d88dSmrg if (!pipe->CurrentProgram[MESA_SHADER_VERTEX] 92401e04c3fSmrg && (pipe->CurrentProgram[MESA_SHADER_GEOMETRY] || 92501e04c3fSmrg pipe->CurrentProgram[MESA_SHADER_TESS_CTRL] || 92601e04c3fSmrg pipe->CurrentProgram[MESA_SHADER_TESS_EVAL])) { 927af69d88dSmrg pipe->InfoLog = ralloc_strdup(pipe, "Program lacks a vertex shader"); 92801e04c3fSmrg return GL_FALSE; 929af69d88dSmrg } 930af69d88dSmrg 931af69d88dSmrg /* Section 2.11.11 (Shader Execution), subheading "Validation," of the 932af69d88dSmrg * OpenGL 4.1 spec says: 933af69d88dSmrg * 934af69d88dSmrg * "[INVALID_OPERATION] is generated by any command that transfers 935af69d88dSmrg * vertices to the GL if: 936af69d88dSmrg * 937af69d88dSmrg * ... 938af69d88dSmrg * 939af69d88dSmrg * - There is no current program object specified by UseProgram, 940af69d88dSmrg * there is a current program pipeline object, and the current 941af69d88dSmrg * program for any shader stage has been relinked since being 942af69d88dSmrg * applied to the pipeline object via UseProgramStages with the 943af69d88dSmrg * PROGRAM_SEPARABLE parameter set to FALSE. 944af69d88dSmrg */ 945af69d88dSmrg for (i = 0; i < MESA_SHADER_STAGES; i++) { 94601e04c3fSmrg if (pipe->CurrentProgram[i] && 94701e04c3fSmrg !pipe->CurrentProgram[i]->info.separate_shader) { 948af69d88dSmrg pipe->InfoLog = ralloc_asprintf(pipe, 949af69d88dSmrg "Program %d was relinked without " 950af69d88dSmrg "PROGRAM_SEPARABLE state", 95101e04c3fSmrg pipe->CurrentProgram[i]->Id); 95201e04c3fSmrg return GL_FALSE; 95301e04c3fSmrg } 95401e04c3fSmrg } 95501e04c3fSmrg 95601e04c3fSmrg /* Section 11.1.3.11 (Validation) of the OpenGL 4.5 spec says: 95701e04c3fSmrg * 95801e04c3fSmrg * "An INVALID_OPERATION error is generated by any command that trans- 95901e04c3fSmrg * fers vertices to the GL or launches compute work if the current set 96001e04c3fSmrg * of active program objects cannot be executed, for reasons including: 96101e04c3fSmrg * 96201e04c3fSmrg * ... 96301e04c3fSmrg * 96401e04c3fSmrg * - There is no current program object specified by UseProgram, 96501e04c3fSmrg * there is a current program pipeline object, and that object is 96601e04c3fSmrg * empty (no executable code is installed for any stage). 96701e04c3fSmrg */ 96801e04c3fSmrg for (i = 0; i < MESA_SHADER_STAGES; i++) { 96901e04c3fSmrg if (pipe->CurrentProgram[i]) { 97001e04c3fSmrg program_empty = false; 97101e04c3fSmrg break; 972af69d88dSmrg } 973af69d88dSmrg } 974af69d88dSmrg 97501e04c3fSmrg if (program_empty) { 97601e04c3fSmrg return GL_FALSE; 97701e04c3fSmrg } 97801e04c3fSmrg 979af69d88dSmrg /* Section 2.11.11 (Shader Execution), subheading "Validation," of the 980af69d88dSmrg * OpenGL 4.1 spec says: 981af69d88dSmrg * 982af69d88dSmrg * "[INVALID_OPERATION] is generated by any command that transfers 983af69d88dSmrg * vertices to the GL if: 984af69d88dSmrg * 985af69d88dSmrg * ... 986af69d88dSmrg * 987af69d88dSmrg * - Any two active samplers in the current program object are of 988af69d88dSmrg * different types, but refer to the same texture image unit. 989af69d88dSmrg * 990af69d88dSmrg * - The number of active samplers in the program exceeds the 991af69d88dSmrg * maximum number of texture image units allowed." 992af69d88dSmrg */ 993af69d88dSmrg if (!_mesa_sampler_uniforms_pipeline_are_valid(pipe)) 99401e04c3fSmrg return GL_FALSE; 99501e04c3fSmrg 99601e04c3fSmrg /* Validate inputs against outputs, this cannot be done during linking 99701e04c3fSmrg * since programs have been linked separately from each other. 99801e04c3fSmrg * 99901e04c3fSmrg * Section 11.1.3.11 (Validation) of the OpenGL 4.5 Core Profile spec says: 100001e04c3fSmrg * 100101e04c3fSmrg * "Separable program objects may have validation failures that cannot be 100201e04c3fSmrg * detected without the complete program pipeline. Mismatched interfaces, 100301e04c3fSmrg * improper usage of program objects together, and the same 100401e04c3fSmrg * state-dependent failures can result in validation errors for such 100501e04c3fSmrg * program objects." 100601e04c3fSmrg * 100701e04c3fSmrg * OpenGL ES 3.1 specification has the same text. 100801e04c3fSmrg * 100901e04c3fSmrg * Section 11.1.3.11 (Validation) of the OpenGL ES spec also says: 101001e04c3fSmrg * 101101e04c3fSmrg * An INVALID_OPERATION error is generated by any command that transfers 101201e04c3fSmrg * vertices to the GL or launches compute work if the current set of 101301e04c3fSmrg * active program objects cannot be executed, for reasons including: 101401e04c3fSmrg * 101501e04c3fSmrg * * The current program pipeline object contains a shader interface 101601e04c3fSmrg * that doesn't have an exact match (see section 7.4.1) 101701e04c3fSmrg * 101801e04c3fSmrg * Based on this, only perform the most-strict checking on ES or when the 101901e04c3fSmrg * application has created a debug context. 102001e04c3fSmrg */ 102101e04c3fSmrg if ((_mesa_is_gles(ctx) || (ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT)) && 102201e04c3fSmrg !_mesa_validate_pipeline_io(pipe)) { 102301e04c3fSmrg if (_mesa_is_gles(ctx)) 102401e04c3fSmrg return GL_FALSE; 102501e04c3fSmrg 102601e04c3fSmrg static GLuint msg_id = 0; 102701e04c3fSmrg 1028b9abf16eSmaya _mesa_gl_debugf(ctx, &msg_id, 1029b9abf16eSmaya MESA_DEBUG_SOURCE_API, 1030b9abf16eSmaya MESA_DEBUG_TYPE_PORTABILITY, 1031b9abf16eSmaya MESA_DEBUG_SEVERITY_MEDIUM, 1032b9abf16eSmaya "glValidateProgramPipeline: pipeline %u does not meet " 1033b9abf16eSmaya "strict OpenGL ES 3.1 requirements and may not be " 1034b9abf16eSmaya "portable across desktop hardware\n", 1035b9abf16eSmaya pipe->Name); 103601e04c3fSmrg } 1037af69d88dSmrg 1038af69d88dSmrg pipe->Validated = GL_TRUE; 1039af69d88dSmrg return GL_TRUE; 1040af69d88dSmrg} 1041af69d88dSmrg 1042af69d88dSmrg/** 1043af69d88dSmrg * Check compatibility of pipeline's program 1044af69d88dSmrg */ 1045af69d88dSmrgvoid GLAPIENTRY 1046af69d88dSmrg_mesa_ValidateProgramPipeline(GLuint pipeline) 1047af69d88dSmrg{ 1048af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 1049af69d88dSmrg 105001e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 105101e04c3fSmrg _mesa_debug(ctx, "glValidateProgramPipeline(%u)\n", pipeline); 105201e04c3fSmrg 105301e04c3fSmrg struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); 1054af69d88dSmrg 1055af69d88dSmrg if (!pipe) { 1056af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1057af69d88dSmrg "glValidateProgramPipeline(pipeline)"); 1058af69d88dSmrg return; 1059af69d88dSmrg } 1060af69d88dSmrg 106101e04c3fSmrg _mesa_validate_program_pipeline(ctx, pipe); 10627ec681f3Smrg pipe->UserValidated = pipe->Validated; 1063af69d88dSmrg} 1064af69d88dSmrg 1065af69d88dSmrgvoid GLAPIENTRY 1066af69d88dSmrg_mesa_GetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, 1067af69d88dSmrg GLsizei *length, GLchar *infoLog) 1068af69d88dSmrg{ 1069af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 1070af69d88dSmrg 107101e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 107201e04c3fSmrg _mesa_debug(ctx, "glGetProgramPipelineInfoLog(%u, %d, %p, %p)\n", 107301e04c3fSmrg pipeline, bufSize, length, infoLog); 107401e04c3fSmrg 107501e04c3fSmrg struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline); 1076af69d88dSmrg 1077af69d88dSmrg if (!pipe) { 1078af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1079af69d88dSmrg "glGetProgramPipelineInfoLog(pipeline)"); 1080af69d88dSmrg return; 1081af69d88dSmrg } 1082af69d88dSmrg 1083af69d88dSmrg if (bufSize < 0) { 1084af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1085af69d88dSmrg "glGetProgramPipelineInfoLog(bufSize)"); 1086af69d88dSmrg return; 1087af69d88dSmrg } 1088af69d88dSmrg 108901e04c3fSmrg _mesa_copy_string(infoLog, bufSize, length, pipe->InfoLog); 1090af69d88dSmrg} 1091