pipelineobj.c revision af69d88d
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 34af69d88dSmrg#include "main/glheader.h" 35af69d88dSmrg#include "main/context.h" 36af69d88dSmrg#include "main/dispatch.h" 37af69d88dSmrg#include "main/enums.h" 38af69d88dSmrg#include "main/hash.h" 39af69d88dSmrg#include "main/mtypes.h" 40af69d88dSmrg#include "main/pipelineobj.h" 41af69d88dSmrg#include "main/shaderapi.h" 42af69d88dSmrg#include "main/shaderobj.h" 43af69d88dSmrg#include "main/transformfeedback.h" 44af69d88dSmrg#include "main/uniforms.h" 45af69d88dSmrg#include "program/program.h" 46af69d88dSmrg#include "program/prog_parameter.h" 47af69d88dSmrg#include "util/ralloc.h" 48af69d88dSmrg#include <stdbool.h> 49af69d88dSmrg#include "../glsl/glsl_parser_extras.h" 50af69d88dSmrg#include "../glsl/ir_uniform.h" 51af69d88dSmrg 52af69d88dSmrg/** 53af69d88dSmrg * Delete a pipeline object. 54af69d88dSmrg */ 55af69d88dSmrgvoid 56af69d88dSmrg_mesa_delete_pipeline_object(struct gl_context *ctx, 57af69d88dSmrg struct gl_pipeline_object *obj) 58af69d88dSmrg{ 59af69d88dSmrg unsigned i; 60af69d88dSmrg 61af69d88dSmrg _mesa_reference_shader_program(ctx, &obj->_CurrentFragmentProgram, NULL); 62af69d88dSmrg 63af69d88dSmrg for (i = 0; i < MESA_SHADER_STAGES; i++) 64af69d88dSmrg _mesa_reference_shader_program(ctx, &obj->CurrentProgram[i], NULL); 65af69d88dSmrg 66af69d88dSmrg _mesa_reference_shader_program(ctx, &obj->ActiveProgram, NULL); 67af69d88dSmrg mtx_destroy(&obj->Mutex); 68af69d88dSmrg ralloc_free(obj); 69af69d88dSmrg} 70af69d88dSmrg 71af69d88dSmrg/** 72af69d88dSmrg * Allocate and initialize a new pipeline object. 73af69d88dSmrg */ 74af69d88dSmrgstatic struct gl_pipeline_object * 75af69d88dSmrg_mesa_new_pipeline_object(struct gl_context *ctx, GLuint name) 76af69d88dSmrg{ 77af69d88dSmrg struct gl_pipeline_object *obj = rzalloc(NULL, struct gl_pipeline_object); 78af69d88dSmrg if (obj) { 79af69d88dSmrg obj->Name = name; 80af69d88dSmrg mtx_init(&obj->Mutex, mtx_plain); 81af69d88dSmrg obj->RefCount = 1; 82af69d88dSmrg obj->Flags = _mesa_get_shader_flags(); 83af69d88dSmrg obj->InfoLog = NULL; 84af69d88dSmrg } 85af69d88dSmrg 86af69d88dSmrg return obj; 87af69d88dSmrg} 88af69d88dSmrg 89af69d88dSmrg/** 90af69d88dSmrg * Initialize pipeline object state for given context. 91af69d88dSmrg */ 92af69d88dSmrgvoid 93af69d88dSmrg_mesa_init_pipeline(struct gl_context *ctx) 94af69d88dSmrg{ 95af69d88dSmrg ctx->Pipeline.Objects = _mesa_NewHashTable(); 96af69d88dSmrg 97af69d88dSmrg ctx->Pipeline.Current = NULL; 98af69d88dSmrg 99af69d88dSmrg /* Install a default Pipeline */ 100af69d88dSmrg ctx->Pipeline.Default = _mesa_new_pipeline_object(ctx, 0); 101af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->_Shader, ctx->Pipeline.Default); 102af69d88dSmrg} 103af69d88dSmrg 104af69d88dSmrg 105af69d88dSmrg/** 106af69d88dSmrg * Callback for deleting a pipeline object. Called by _mesa_HashDeleteAll(). 107af69d88dSmrg */ 108af69d88dSmrgstatic void 109af69d88dSmrgdelete_pipelineobj_cb(GLuint id, void *data, void *userData) 110af69d88dSmrg{ 111af69d88dSmrg struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data; 112af69d88dSmrg struct gl_context *ctx = (struct gl_context *) userData; 113af69d88dSmrg _mesa_delete_pipeline_object(ctx, obj); 114af69d88dSmrg} 115af69d88dSmrg 116af69d88dSmrg 117af69d88dSmrg/** 118af69d88dSmrg * Free pipeline state for given context. 119af69d88dSmrg */ 120af69d88dSmrgvoid 121af69d88dSmrg_mesa_free_pipeline_data(struct gl_context *ctx) 122af69d88dSmrg{ 123af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->_Shader, NULL); 124af69d88dSmrg 125af69d88dSmrg _mesa_HashDeleteAll(ctx->Pipeline.Objects, delete_pipelineobj_cb, ctx); 126af69d88dSmrg _mesa_DeleteHashTable(ctx->Pipeline.Objects); 127af69d88dSmrg 128af69d88dSmrg _mesa_delete_pipeline_object(ctx, ctx->Pipeline.Default); 129af69d88dSmrg} 130af69d88dSmrg 131af69d88dSmrg/** 132af69d88dSmrg * Look up the pipeline object for the given ID. 133af69d88dSmrg * 134af69d88dSmrg * \returns 135af69d88dSmrg * Either a pointer to the pipeline object with the specified ID or \c NULL for 136af69d88dSmrg * a non-existent ID. The spec defines ID 0 as being technically 137af69d88dSmrg * non-existent. 138af69d88dSmrg */ 139af69d88dSmrgstatic inline struct gl_pipeline_object * 140af69d88dSmrglookup_pipeline_object(struct gl_context *ctx, GLuint id) 141af69d88dSmrg{ 142af69d88dSmrg if (id == 0) 143af69d88dSmrg return NULL; 144af69d88dSmrg else 145af69d88dSmrg return (struct gl_pipeline_object *) 146af69d88dSmrg _mesa_HashLookup(ctx->Pipeline.Objects, id); 147af69d88dSmrg} 148af69d88dSmrg 149af69d88dSmrg/** 150af69d88dSmrg * Add the given pipeline object to the pipeline object pool. 151af69d88dSmrg */ 152af69d88dSmrgstatic void 153af69d88dSmrgsave_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj) 154af69d88dSmrg{ 155af69d88dSmrg if (obj->Name > 0) { 156af69d88dSmrg _mesa_HashInsert(ctx->Pipeline.Objects, obj->Name, obj); 157af69d88dSmrg } 158af69d88dSmrg} 159af69d88dSmrg 160af69d88dSmrg/** 161af69d88dSmrg * Remove the given pipeline object from the pipeline object pool. 162af69d88dSmrg * Do not deallocate the pipeline object though. 163af69d88dSmrg */ 164af69d88dSmrgstatic void 165af69d88dSmrgremove_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj) 166af69d88dSmrg{ 167af69d88dSmrg if (obj->Name > 0) { 168af69d88dSmrg _mesa_HashRemove(ctx->Pipeline.Objects, obj->Name); 169af69d88dSmrg } 170af69d88dSmrg} 171af69d88dSmrg 172af69d88dSmrg/** 173af69d88dSmrg * Set ptr to obj w/ reference counting. 174af69d88dSmrg * Note: this should only be called from the _mesa_reference_pipeline_object() 175af69d88dSmrg * inline function. 176af69d88dSmrg */ 177af69d88dSmrgvoid 178af69d88dSmrg_mesa_reference_pipeline_object_(struct gl_context *ctx, 179af69d88dSmrg struct gl_pipeline_object **ptr, 180af69d88dSmrg struct gl_pipeline_object *obj) 181af69d88dSmrg{ 182af69d88dSmrg assert(*ptr != obj); 183af69d88dSmrg 184af69d88dSmrg if (*ptr) { 185af69d88dSmrg /* Unreference the old pipeline object */ 186af69d88dSmrg GLboolean deleteFlag = GL_FALSE; 187af69d88dSmrg struct gl_pipeline_object *oldObj = *ptr; 188af69d88dSmrg 189af69d88dSmrg mtx_lock(&oldObj->Mutex); 190af69d88dSmrg ASSERT(oldObj->RefCount > 0); 191af69d88dSmrg oldObj->RefCount--; 192af69d88dSmrg deleteFlag = (oldObj->RefCount == 0); 193af69d88dSmrg mtx_unlock(&oldObj->Mutex); 194af69d88dSmrg 195af69d88dSmrg if (deleteFlag) { 196af69d88dSmrg _mesa_delete_pipeline_object(ctx, oldObj); 197af69d88dSmrg } 198af69d88dSmrg 199af69d88dSmrg *ptr = NULL; 200af69d88dSmrg } 201af69d88dSmrg ASSERT(!*ptr); 202af69d88dSmrg 203af69d88dSmrg if (obj) { 204af69d88dSmrg /* reference new pipeline object */ 205af69d88dSmrg mtx_lock(&obj->Mutex); 206af69d88dSmrg if (obj->RefCount == 0) { 207af69d88dSmrg /* this pipeline's being deleted (look just above) */ 208af69d88dSmrg /* Not sure this can ever really happen. Warn if it does. */ 209af69d88dSmrg _mesa_problem(NULL, "referencing deleted pipeline object"); 210af69d88dSmrg *ptr = NULL; 211af69d88dSmrg } 212af69d88dSmrg else { 213af69d88dSmrg obj->RefCount++; 214af69d88dSmrg *ptr = obj; 215af69d88dSmrg } 216af69d88dSmrg mtx_unlock(&obj->Mutex); 217af69d88dSmrg } 218af69d88dSmrg} 219af69d88dSmrg 220af69d88dSmrg/** 221af69d88dSmrg * Bound program to severals stages of the pipeline 222af69d88dSmrg */ 223af69d88dSmrgvoid GLAPIENTRY 224af69d88dSmrg_mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) 225af69d88dSmrg{ 226af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 227af69d88dSmrg 228af69d88dSmrg struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); 229af69d88dSmrg struct gl_shader_program *shProg = NULL; 230af69d88dSmrg GLbitfield any_valid_stages; 231af69d88dSmrg 232af69d88dSmrg if (!pipe) { 233af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgramStages(pipeline)"); 234af69d88dSmrg return; 235af69d88dSmrg } 236af69d88dSmrg 237af69d88dSmrg /* Object is created by any Pipeline call but glGenProgramPipelines, 238af69d88dSmrg * glIsProgramPipeline and GetProgramPipelineInfoLog 239af69d88dSmrg */ 240af69d88dSmrg pipe->EverBound = GL_TRUE; 241af69d88dSmrg 242af69d88dSmrg /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec says: 243af69d88dSmrg * 244af69d88dSmrg * "If stages is not the special value ALL_SHADER_BITS, and has a bit 245af69d88dSmrg * set that is not recognized, the error INVALID_VALUE is generated." 246af69d88dSmrg * 247af69d88dSmrg * NOT YET SUPPORTED: 248af69d88dSmrg * GL_TESS_CONTROL_SHADER_BIT 249af69d88dSmrg * GL_TESS_EVALUATION_SHADER_BIT 250af69d88dSmrg */ 251af69d88dSmrg any_valid_stages = GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT; 252af69d88dSmrg if (_mesa_has_geometry_shaders(ctx)) 253af69d88dSmrg any_valid_stages |= GL_GEOMETRY_SHADER_BIT; 254af69d88dSmrg 255af69d88dSmrg if (stages != GL_ALL_SHADER_BITS && (stages & ~any_valid_stages) != 0) { 256af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glUseProgramStages(Stages)"); 257af69d88dSmrg return; 258af69d88dSmrg } 259af69d88dSmrg 260af69d88dSmrg /* Section 2.17.2 (Transform Feedback Primitive Capture) of the OpenGL 4.1 261af69d88dSmrg * spec says: 262af69d88dSmrg * 263af69d88dSmrg * "The error INVALID_OPERATION is generated: 264af69d88dSmrg * 265af69d88dSmrg * ... 266af69d88dSmrg * 267af69d88dSmrg * - by UseProgramStages if the program pipeline object it refers 268af69d88dSmrg * to is current and the current transform feedback object is 269af69d88dSmrg * active and not paused; 270af69d88dSmrg */ 271af69d88dSmrg if (ctx->_Shader == pipe) { 272af69d88dSmrg if (_mesa_is_xfb_active_and_unpaused(ctx)) { 273af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 274af69d88dSmrg "glUseProgramStages(transform feedback active)"); 275af69d88dSmrg return; 276af69d88dSmrg } 277af69d88dSmrg } 278af69d88dSmrg 279af69d88dSmrg if (program) { 280af69d88dSmrg shProg = _mesa_lookup_shader_program_err(ctx, program, 281af69d88dSmrg "glUseProgramStages"); 282af69d88dSmrg if (shProg == NULL) 283af69d88dSmrg return; 284af69d88dSmrg 285af69d88dSmrg /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec 286af69d88dSmrg * says: 287af69d88dSmrg * 288af69d88dSmrg * "If the program object named by program was linked without the 289af69d88dSmrg * PROGRAM_SEPARABLE parameter set, or was not linked successfully, 290af69d88dSmrg * the error INVALID_OPERATION is generated and the corresponding 291af69d88dSmrg * shader stages in the pipeline program pipeline object are not 292af69d88dSmrg * modified." 293af69d88dSmrg */ 294af69d88dSmrg if (!shProg->LinkStatus) { 295af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 296af69d88dSmrg "glUseProgramStages(program not linked)"); 297af69d88dSmrg return; 298af69d88dSmrg } 299af69d88dSmrg 300af69d88dSmrg if (!shProg->SeparateShader) { 301af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 302af69d88dSmrg "glUseProgramStages(program wasn't linked with the " 303af69d88dSmrg "PROGRAM_SEPARABLE flag)"); 304af69d88dSmrg return; 305af69d88dSmrg } 306af69d88dSmrg } 307af69d88dSmrg 308af69d88dSmrg /* Enable individual stages from the program as requested by the 309af69d88dSmrg * application. If there is no shader for a requested stage in the 310af69d88dSmrg * program, _mesa_use_shader_program will enable fixed-function processing 311af69d88dSmrg * as dictated by the spec. 312af69d88dSmrg * 313af69d88dSmrg * Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec 314af69d88dSmrg * says: 315af69d88dSmrg * 316af69d88dSmrg * "If UseProgramStages is called with program set to zero or with a 317af69d88dSmrg * program object that contains no executable code for the given 318af69d88dSmrg * stages, it is as if the pipeline object has no programmable stage 319af69d88dSmrg * configured for the indicated shader stages." 320af69d88dSmrg */ 321af69d88dSmrg if ((stages & GL_VERTEX_SHADER_BIT) != 0) 322af69d88dSmrg _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, shProg, pipe); 323af69d88dSmrg 324af69d88dSmrg if ((stages & GL_FRAGMENT_SHADER_BIT) != 0) 325af69d88dSmrg _mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg, pipe); 326af69d88dSmrg 327af69d88dSmrg if ((stages & GL_GEOMETRY_SHADER_BIT) != 0) 328af69d88dSmrg _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER, shProg, pipe); 329af69d88dSmrg} 330af69d88dSmrg 331af69d88dSmrg/** 332af69d88dSmrg * Use the named shader program for subsequent glUniform calls (if pipeline 333af69d88dSmrg * bound) 334af69d88dSmrg */ 335af69d88dSmrgvoid GLAPIENTRY 336af69d88dSmrg_mesa_ActiveShaderProgram(GLuint pipeline, GLuint program) 337af69d88dSmrg{ 338af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 339af69d88dSmrg struct gl_shader_program *shProg = NULL; 340af69d88dSmrg struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); 341af69d88dSmrg 342af69d88dSmrg if (program != 0) { 343af69d88dSmrg shProg = _mesa_lookup_shader_program_err(ctx, program, 344af69d88dSmrg "glActiveShaderProgram(program)"); 345af69d88dSmrg if (shProg == NULL) 346af69d88dSmrg return; 347af69d88dSmrg } 348af69d88dSmrg 349af69d88dSmrg if (!pipe) { 350af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(pipeline)"); 351af69d88dSmrg return; 352af69d88dSmrg } 353af69d88dSmrg 354af69d88dSmrg /* Object is created by any Pipeline call but glGenProgramPipelines, 355af69d88dSmrg * glIsProgramPipeline and GetProgramPipelineInfoLog 356af69d88dSmrg */ 357af69d88dSmrg pipe->EverBound = GL_TRUE; 358af69d88dSmrg 359af69d88dSmrg if ((shProg != NULL) && !shProg->LinkStatus) { 360af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 361af69d88dSmrg "glActiveShaderProgram(program %u not linked)", shProg->Name); 362af69d88dSmrg return; 363af69d88dSmrg } 364af69d88dSmrg 365af69d88dSmrg _mesa_reference_shader_program(ctx, &pipe->ActiveProgram, shProg); 366af69d88dSmrg} 367af69d88dSmrg 368af69d88dSmrg/** 369af69d88dSmrg * Make program of the pipeline current 370af69d88dSmrg */ 371af69d88dSmrgvoid GLAPIENTRY 372af69d88dSmrg_mesa_BindProgramPipeline(GLuint pipeline) 373af69d88dSmrg{ 374af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 375af69d88dSmrg struct gl_pipeline_object *newObj = NULL; 376af69d88dSmrg 377af69d88dSmrg /* Rebinding the same pipeline object: no change. 378af69d88dSmrg */ 379af69d88dSmrg if (ctx->_Shader->Name == pipeline) 380af69d88dSmrg return; 381af69d88dSmrg 382af69d88dSmrg /* Section 2.17.2 (Transform Feedback Primitive Capture) of the OpenGL 4.1 383af69d88dSmrg * spec says: 384af69d88dSmrg * 385af69d88dSmrg * "The error INVALID_OPERATION is generated: 386af69d88dSmrg * 387af69d88dSmrg * ... 388af69d88dSmrg * 389af69d88dSmrg * - by BindProgramPipeline if the current transform feedback 390af69d88dSmrg * object is active and not paused; 391af69d88dSmrg */ 392af69d88dSmrg if (_mesa_is_xfb_active_and_unpaused(ctx)) { 393af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 394af69d88dSmrg "glBindProgramPipeline(transform feedback active)"); 395af69d88dSmrg return; 396af69d88dSmrg } 397af69d88dSmrg 398af69d88dSmrg /* Get pointer to new pipeline object (newObj) 399af69d88dSmrg */ 400af69d88dSmrg if (pipeline) { 401af69d88dSmrg /* non-default pipeline object */ 402af69d88dSmrg newObj = lookup_pipeline_object(ctx, pipeline); 403af69d88dSmrg if (!newObj) { 404af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 405af69d88dSmrg "glBindProgramPipeline(non-gen name)"); 406af69d88dSmrg return; 407af69d88dSmrg } 408af69d88dSmrg 409af69d88dSmrg /* Object is created by any Pipeline call but glGenProgramPipelines, 410af69d88dSmrg * glIsProgramPipeline and GetProgramPipelineInfoLog 411af69d88dSmrg */ 412af69d88dSmrg newObj->EverBound = GL_TRUE; 413af69d88dSmrg } 414af69d88dSmrg 415af69d88dSmrg _mesa_bind_pipeline(ctx, newObj); 416af69d88dSmrg} 417af69d88dSmrg 418af69d88dSmrgvoid 419af69d88dSmrg_mesa_bind_pipeline(struct gl_context *ctx, 420af69d88dSmrg struct gl_pipeline_object *pipe) 421af69d88dSmrg{ 422af69d88dSmrg /* First bind the Pipeline to pipeline binding point */ 423af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->Pipeline.Current, pipe); 424af69d88dSmrg 425af69d88dSmrg /* Section 2.11.3 (Program Objects) of the OpenGL 4.1 spec says: 426af69d88dSmrg * 427af69d88dSmrg * "If there is a current program object established by UseProgram, 428af69d88dSmrg * that program is considered current for all stages. Otherwise, if 429af69d88dSmrg * there is a bound program pipeline object (see section 2.11.4), the 430af69d88dSmrg * program bound to the appropriate stage of the pipeline object is 431af69d88dSmrg * considered current." 432af69d88dSmrg */ 433af69d88dSmrg if (&ctx->Shader != ctx->_Shader) { 434af69d88dSmrg if (pipe != NULL) { 435af69d88dSmrg /* Bound the pipeline to the current program and 436af69d88dSmrg * restore the pipeline state 437af69d88dSmrg */ 438af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->_Shader, pipe); 439af69d88dSmrg } else { 440af69d88dSmrg /* Unbind the pipeline */ 441af69d88dSmrg _mesa_reference_pipeline_object(ctx, &ctx->_Shader, 442af69d88dSmrg ctx->Pipeline.Default); 443af69d88dSmrg } 444af69d88dSmrg 445af69d88dSmrg FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); 446af69d88dSmrg 447af69d88dSmrg if (ctx->Driver.UseProgram) 448af69d88dSmrg ctx->Driver.UseProgram(ctx, NULL); 449af69d88dSmrg } 450af69d88dSmrg} 451af69d88dSmrg 452af69d88dSmrg/** 453af69d88dSmrg * Delete a set of pipeline objects. 454af69d88dSmrg * 455af69d88dSmrg * \param n Number of pipeline objects to delete. 456af69d88dSmrg * \param ids pipeline of \c n pipeline object IDs. 457af69d88dSmrg */ 458af69d88dSmrgvoid GLAPIENTRY 459af69d88dSmrg_mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines) 460af69d88dSmrg{ 461af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 462af69d88dSmrg GLsizei i; 463af69d88dSmrg 464af69d88dSmrg if (n < 0) { 465af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgramPipelines(n<0)"); 466af69d88dSmrg return; 467af69d88dSmrg } 468af69d88dSmrg 469af69d88dSmrg for (i = 0; i < n; i++) { 470af69d88dSmrg struct gl_pipeline_object *obj = 471af69d88dSmrg lookup_pipeline_object(ctx, pipelines[i]); 472af69d88dSmrg 473af69d88dSmrg if (obj) { 474af69d88dSmrg ASSERT(obj->Name == pipelines[i]); 475af69d88dSmrg 476af69d88dSmrg /* If the pipeline object is currently bound, the spec says "If an 477af69d88dSmrg * object that is currently bound is deleted, the binding for that 478af69d88dSmrg * object reverts to zero and no program pipeline object becomes 479af69d88dSmrg * current." 480af69d88dSmrg */ 481af69d88dSmrg if (obj == ctx->Pipeline.Current) { 482af69d88dSmrg _mesa_BindProgramPipeline(0); 483af69d88dSmrg } 484af69d88dSmrg 485af69d88dSmrg /* The ID is immediately freed for re-use */ 486af69d88dSmrg remove_pipeline_object(ctx, obj); 487af69d88dSmrg 488af69d88dSmrg /* Unreference the pipeline object. 489af69d88dSmrg * If refcount hits zero, the object will be deleted. 490af69d88dSmrg */ 491af69d88dSmrg _mesa_reference_pipeline_object(ctx, &obj, NULL); 492af69d88dSmrg } 493af69d88dSmrg } 494af69d88dSmrg} 495af69d88dSmrg 496af69d88dSmrg/** 497af69d88dSmrg * Generate a set of unique pipeline object IDs and store them in \c pipelines. 498af69d88dSmrg * \param n Number of IDs to generate. 499af69d88dSmrg * \param pipelines pipeline of \c n locations to store the IDs. 500af69d88dSmrg */ 501af69d88dSmrgvoid GLAPIENTRY 502af69d88dSmrg_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines) 503af69d88dSmrg{ 504af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 505af69d88dSmrg 506af69d88dSmrg GLuint first; 507af69d88dSmrg GLint i; 508af69d88dSmrg 509af69d88dSmrg if (n < 0) { 510af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramPipelines(n<0)"); 511af69d88dSmrg return; 512af69d88dSmrg } 513af69d88dSmrg 514af69d88dSmrg if (!pipelines) { 515af69d88dSmrg return; 516af69d88dSmrg } 517af69d88dSmrg 518af69d88dSmrg first = _mesa_HashFindFreeKeyBlock(ctx->Pipeline.Objects, n); 519af69d88dSmrg 520af69d88dSmrg for (i = 0; i < n; i++) { 521af69d88dSmrg struct gl_pipeline_object *obj; 522af69d88dSmrg GLuint name = first + i; 523af69d88dSmrg 524af69d88dSmrg obj = _mesa_new_pipeline_object(ctx, name); 525af69d88dSmrg if (!obj) { 526af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramPipelines"); 527af69d88dSmrg return; 528af69d88dSmrg } 529af69d88dSmrg 530af69d88dSmrg save_pipeline_object(ctx, obj); 531af69d88dSmrg pipelines[i] = first + i; 532af69d88dSmrg } 533af69d88dSmrg 534af69d88dSmrg} 535af69d88dSmrg 536af69d88dSmrg/** 537af69d88dSmrg * Determine if ID is the name of an pipeline object. 538af69d88dSmrg * 539af69d88dSmrg * \param id ID of the potential pipeline object. 540af69d88dSmrg * \return \c GL_TRUE if \c id is the name of a pipeline object, 541af69d88dSmrg * \c GL_FALSE otherwise. 542af69d88dSmrg */ 543af69d88dSmrgGLboolean GLAPIENTRY 544af69d88dSmrg_mesa_IsProgramPipeline(GLuint pipeline) 545af69d88dSmrg{ 546af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 547af69d88dSmrg 548af69d88dSmrg struct gl_pipeline_object *obj = lookup_pipeline_object(ctx, pipeline); 549af69d88dSmrg if (obj == NULL) 550af69d88dSmrg return GL_FALSE; 551af69d88dSmrg 552af69d88dSmrg return obj->EverBound; 553af69d88dSmrg} 554af69d88dSmrg 555af69d88dSmrg/** 556af69d88dSmrg * glGetProgramPipelineiv() - get pipeline shader state. 557af69d88dSmrg */ 558af69d88dSmrgvoid GLAPIENTRY 559af69d88dSmrg_mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params) 560af69d88dSmrg{ 561af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 562af69d88dSmrg struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); 563af69d88dSmrg 564af69d88dSmrg /* Are geometry shaders available in this context? 565af69d88dSmrg */ 566af69d88dSmrg const bool has_gs = _mesa_has_geometry_shaders(ctx); 567af69d88dSmrg 568af69d88dSmrg if (!pipe) { 569af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 570af69d88dSmrg "glGetProgramPipelineiv(pipeline)"); 571af69d88dSmrg return; 572af69d88dSmrg } 573af69d88dSmrg 574af69d88dSmrg /* Object is created by any Pipeline call but glGenProgramPipelines, 575af69d88dSmrg * glIsProgramPipeline and GetProgramPipelineInfoLog 576af69d88dSmrg */ 577af69d88dSmrg pipe->EverBound = GL_TRUE; 578af69d88dSmrg 579af69d88dSmrg switch (pname) { 580af69d88dSmrg case GL_ACTIVE_PROGRAM: 581af69d88dSmrg *params = pipe->ActiveProgram ? pipe->ActiveProgram->Name : 0; 582af69d88dSmrg return; 583af69d88dSmrg case GL_INFO_LOG_LENGTH: 584af69d88dSmrg *params = pipe->InfoLog ? strlen(pipe->InfoLog) + 1 : 0; 585af69d88dSmrg return; 586af69d88dSmrg case GL_VALIDATE_STATUS: 587af69d88dSmrg *params = pipe->Validated; 588af69d88dSmrg return; 589af69d88dSmrg case GL_VERTEX_SHADER: 590af69d88dSmrg *params = pipe->CurrentProgram[MESA_SHADER_VERTEX] 591af69d88dSmrg ? pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name : 0; 592af69d88dSmrg return; 593af69d88dSmrg case GL_TESS_EVALUATION_SHADER: 594af69d88dSmrg /* NOT YET SUPPORTED */ 595af69d88dSmrg break; 596af69d88dSmrg case GL_TESS_CONTROL_SHADER: 597af69d88dSmrg /* NOT YET SUPPORTED */ 598af69d88dSmrg break; 599af69d88dSmrg case GL_GEOMETRY_SHADER: 600af69d88dSmrg if (!has_gs) 601af69d88dSmrg break; 602af69d88dSmrg *params = pipe->CurrentProgram[MESA_SHADER_GEOMETRY] 603af69d88dSmrg ? pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Name : 0; 604af69d88dSmrg return; 605af69d88dSmrg case GL_FRAGMENT_SHADER: 606af69d88dSmrg *params = pipe->CurrentProgram[MESA_SHADER_FRAGMENT] 607af69d88dSmrg ? pipe->CurrentProgram[MESA_SHADER_FRAGMENT]->Name : 0; 608af69d88dSmrg return; 609af69d88dSmrg default: 610af69d88dSmrg break; 611af69d88dSmrg } 612af69d88dSmrg 613af69d88dSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramPipelineiv(pname=%s)", 614af69d88dSmrg _mesa_lookup_enum_by_nr(pname)); 615af69d88dSmrg} 616af69d88dSmrg 617af69d88dSmrg/** 618af69d88dSmrg * Determines whether every stage in a linked program is active in the 619af69d88dSmrg * specified pipeline. 620af69d88dSmrg */ 621af69d88dSmrgstatic bool 622af69d88dSmrgprogram_stages_all_active(struct gl_pipeline_object *pipe, 623af69d88dSmrg const struct gl_shader_program *prog) 624af69d88dSmrg{ 625af69d88dSmrg unsigned i; 626af69d88dSmrg bool status = true; 627af69d88dSmrg 628af69d88dSmrg if (!prog) 629af69d88dSmrg return true; 630af69d88dSmrg 631af69d88dSmrg for (i = 0; i < MESA_SHADER_STAGES; i++) { 632af69d88dSmrg if (prog->_LinkedShaders[i]) { 633af69d88dSmrg if (pipe->CurrentProgram[i]) { 634af69d88dSmrg if (prog->Name != pipe->CurrentProgram[i]->Name) { 635af69d88dSmrg status = false; 636af69d88dSmrg } 637af69d88dSmrg } else { 638af69d88dSmrg status = false; 639af69d88dSmrg } 640af69d88dSmrg } 641af69d88dSmrg } 642af69d88dSmrg 643af69d88dSmrg if (!status) { 644af69d88dSmrg pipe->InfoLog = ralloc_asprintf(pipe, 645af69d88dSmrg "Program %d is not active for all " 646af69d88dSmrg "shaders that was linked", 647af69d88dSmrg prog->Name); 648af69d88dSmrg } 649af69d88dSmrg 650af69d88dSmrg return status; 651af69d88dSmrg} 652af69d88dSmrg 653af69d88dSmrgextern GLboolean 654af69d88dSmrg_mesa_validate_program_pipeline(struct gl_context* ctx, 655af69d88dSmrg struct gl_pipeline_object *pipe, 656af69d88dSmrg GLboolean IsBound) 657af69d88dSmrg{ 658af69d88dSmrg unsigned i; 659af69d88dSmrg 660af69d88dSmrg pipe->Validated = GL_FALSE; 661af69d88dSmrg 662af69d88dSmrg /* Release and reset the info log. 663af69d88dSmrg */ 664af69d88dSmrg if (pipe->InfoLog != NULL) 665af69d88dSmrg ralloc_free(pipe->InfoLog); 666af69d88dSmrg 667af69d88dSmrg pipe->InfoLog = NULL; 668af69d88dSmrg 669af69d88dSmrg /* Section 2.11.11 (Shader Execution), subheading "Validation," of the 670af69d88dSmrg * OpenGL 4.1 spec says: 671af69d88dSmrg * 672af69d88dSmrg * "[INVALID_OPERATION] is generated by any command that transfers 673af69d88dSmrg * vertices to the GL if: 674af69d88dSmrg * 675af69d88dSmrg * - A program object is active for at least one, but not all of 676af69d88dSmrg * the shader stages that were present when the program was 677af69d88dSmrg * linked." 678af69d88dSmrg * 679af69d88dSmrg * For each possible program stage, verify that the program bound to that 680af69d88dSmrg * stage has all of its stages active. In other words, if the program 681af69d88dSmrg * bound to the vertex stage also has a fragment shader, the fragment 682af69d88dSmrg * shader must also be bound to the fragment stage. 683af69d88dSmrg */ 684af69d88dSmrg for (i = 0; i < MESA_SHADER_STAGES; i++) { 685af69d88dSmrg if (!program_stages_all_active(pipe, pipe->CurrentProgram[i])) { 686af69d88dSmrg goto err; 687af69d88dSmrg } 688af69d88dSmrg } 689af69d88dSmrg 690af69d88dSmrg /* Section 2.11.11 (Shader Execution), subheading "Validation," of the 691af69d88dSmrg * OpenGL 4.1 spec says: 692af69d88dSmrg * 693af69d88dSmrg * "[INVALID_OPERATION] is generated by any command that transfers 694af69d88dSmrg * vertices to the GL if: 695af69d88dSmrg * 696af69d88dSmrg * ... 697af69d88dSmrg * 698af69d88dSmrg * - One program object is active for at least two shader stages 699af69d88dSmrg * and a second program is active for a shader stage between two 700af69d88dSmrg * stages for which the first program was active." 701af69d88dSmrg * 702af69d88dSmrg * Without Tesselation, the only case where this can occur is the geometry 703af69d88dSmrg * shader between the fragment shader and vertex shader. 704af69d88dSmrg */ 705af69d88dSmrg if (pipe->CurrentProgram[MESA_SHADER_GEOMETRY] 706af69d88dSmrg && pipe->CurrentProgram[MESA_SHADER_FRAGMENT] 707af69d88dSmrg && pipe->CurrentProgram[MESA_SHADER_VERTEX]) { 708af69d88dSmrg if (pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name == pipe->CurrentProgram[MESA_SHADER_FRAGMENT]->Name && 709af69d88dSmrg pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Name != pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name) { 710af69d88dSmrg pipe->InfoLog = 711af69d88dSmrg ralloc_asprintf(pipe, 712af69d88dSmrg "Program %d is active for geometry stage between " 713af69d88dSmrg "two stages for which another program %d is " 714af69d88dSmrg "active", 715af69d88dSmrg pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Name, 716af69d88dSmrg pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name); 717af69d88dSmrg goto err; 718af69d88dSmrg } 719af69d88dSmrg } 720af69d88dSmrg 721af69d88dSmrg /* Section 2.11.11 (Shader Execution), subheading "Validation," of the 722af69d88dSmrg * OpenGL 4.1 spec says: 723af69d88dSmrg * 724af69d88dSmrg * "[INVALID_OPERATION] is generated by any command that transfers 725af69d88dSmrg * vertices to the GL if: 726af69d88dSmrg * 727af69d88dSmrg * ... 728af69d88dSmrg * 729af69d88dSmrg * - There is an active program for tessellation control, 730af69d88dSmrg * tessellation evaluation, or geometry stages with corresponding 731af69d88dSmrg * executable shader, but there is no active program with 732af69d88dSmrg * executable vertex shader." 733af69d88dSmrg */ 734af69d88dSmrg if (!pipe->CurrentProgram[MESA_SHADER_VERTEX] 735af69d88dSmrg && pipe->CurrentProgram[MESA_SHADER_GEOMETRY]) { 736af69d88dSmrg pipe->InfoLog = ralloc_strdup(pipe, "Program lacks a vertex shader"); 737af69d88dSmrg goto err; 738af69d88dSmrg } 739af69d88dSmrg 740af69d88dSmrg /* Section 2.11.11 (Shader Execution), subheading "Validation," of the 741af69d88dSmrg * OpenGL 4.1 spec says: 742af69d88dSmrg * 743af69d88dSmrg * "[INVALID_OPERATION] is generated by any command that transfers 744af69d88dSmrg * vertices to the GL if: 745af69d88dSmrg * 746af69d88dSmrg * ... 747af69d88dSmrg * 748af69d88dSmrg * - There is no current program object specified by UseProgram, 749af69d88dSmrg * there is a current program pipeline object, and the current 750af69d88dSmrg * program for any shader stage has been relinked since being 751af69d88dSmrg * applied to the pipeline object via UseProgramStages with the 752af69d88dSmrg * PROGRAM_SEPARABLE parameter set to FALSE. 753af69d88dSmrg */ 754af69d88dSmrg for (i = 0; i < MESA_SHADER_STAGES; i++) { 755af69d88dSmrg if (pipe->CurrentProgram[i] && !pipe->CurrentProgram[i]->SeparateShader) { 756af69d88dSmrg pipe->InfoLog = ralloc_asprintf(pipe, 757af69d88dSmrg "Program %d was relinked without " 758af69d88dSmrg "PROGRAM_SEPARABLE state", 759af69d88dSmrg pipe->CurrentProgram[i]->Name); 760af69d88dSmrg goto err; 761af69d88dSmrg } 762af69d88dSmrg } 763af69d88dSmrg 764af69d88dSmrg /* Section 2.11.11 (Shader Execution), subheading "Validation," of the 765af69d88dSmrg * OpenGL 4.1 spec says: 766af69d88dSmrg * 767af69d88dSmrg * "[INVALID_OPERATION] is generated by any command that transfers 768af69d88dSmrg * vertices to the GL if: 769af69d88dSmrg * 770af69d88dSmrg * ... 771af69d88dSmrg * 772af69d88dSmrg * - Any two active samplers in the current program object are of 773af69d88dSmrg * different types, but refer to the same texture image unit. 774af69d88dSmrg * 775af69d88dSmrg * - The number of active samplers in the program exceeds the 776af69d88dSmrg * maximum number of texture image units allowed." 777af69d88dSmrg */ 778af69d88dSmrg if (!_mesa_sampler_uniforms_pipeline_are_valid(pipe)) 779af69d88dSmrg goto err; 780af69d88dSmrg 781af69d88dSmrg pipe->Validated = GL_TRUE; 782af69d88dSmrg return GL_TRUE; 783af69d88dSmrg 784af69d88dSmrgerr: 785af69d88dSmrg if (IsBound) 786af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 787af69d88dSmrg "glValidateProgramPipeline failed to validate the pipeline"); 788af69d88dSmrg 789af69d88dSmrg return GL_FALSE; 790af69d88dSmrg} 791af69d88dSmrg 792af69d88dSmrg/** 793af69d88dSmrg * Check compatibility of pipeline's program 794af69d88dSmrg */ 795af69d88dSmrgvoid GLAPIENTRY 796af69d88dSmrg_mesa_ValidateProgramPipeline(GLuint pipeline) 797af69d88dSmrg{ 798af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 799af69d88dSmrg 800af69d88dSmrg struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); 801af69d88dSmrg 802af69d88dSmrg if (!pipe) { 803af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 804af69d88dSmrg "glValidateProgramPipeline(pipeline)"); 805af69d88dSmrg return; 806af69d88dSmrg } 807af69d88dSmrg 808af69d88dSmrg _mesa_validate_program_pipeline(ctx, pipe, 809af69d88dSmrg (ctx->_Shader->Name == pipe->Name)); 810af69d88dSmrg} 811af69d88dSmrg 812af69d88dSmrgvoid GLAPIENTRY 813af69d88dSmrg_mesa_GetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, 814af69d88dSmrg GLsizei *length, GLchar *infoLog) 815af69d88dSmrg{ 816af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 817af69d88dSmrg 818af69d88dSmrg struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); 819af69d88dSmrg 820af69d88dSmrg if (!pipe) { 821af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 822af69d88dSmrg "glGetProgramPipelineInfoLog(pipeline)"); 823af69d88dSmrg return; 824af69d88dSmrg } 825af69d88dSmrg 826af69d88dSmrg if (bufSize < 0) { 827af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 828af69d88dSmrg "glGetProgramPipelineInfoLog(bufSize)"); 829af69d88dSmrg return; 830af69d88dSmrg } 831af69d88dSmrg 832af69d88dSmrg if (pipe->InfoLog) 833af69d88dSmrg _mesa_copy_string(infoLog, bufSize, length, pipe->InfoLog); 834af69d88dSmrg else 835af69d88dSmrg *length = 0; 836af69d88dSmrg} 837