b639e9bc913532ff2f5c227fd340aaee86b79383
[mesa.git] / src / mesa / main / pipelineobj.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright © 2013 Gregory Hainaut <gregory.hainaut@gmail.com>
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 <gregory.hainaut@gmail.com>
29 *
30 * Implementation of pipeline object related API functions. Based on
31 * GL_ARB_separate_shader_objects extension.
32 */
33
34 #include "main/glheader.h"
35 #include "main/context.h"
36 #include "main/dispatch.h"
37 #include "main/enums.h"
38 #include "main/hash.h"
39 #include "main/mtypes.h"
40 #include "main/pipelineobj.h"
41 #include "main/shaderapi.h"
42 #include "main/shaderobj.h"
43 #include "main/transformfeedback.h"
44 #include "main/uniforms.h"
45 #include "program/program.h"
46 #include "program/prog_parameter.h"
47 #include "ralloc.h"
48 #include <stdbool.h>
49 #include "../glsl/glsl_parser_extras.h"
50 #include "../glsl/ir_uniform.h"
51
52 /**
53 * Delete a pipeline object.
54 */
55 void
56 _mesa_delete_pipeline_object(struct gl_context *ctx,
57 struct gl_pipeline_object *obj)
58 {
59 unsigned i;
60
61 _mesa_reference_shader_program(ctx, &obj->_CurrentFragmentProgram, NULL);
62
63 for (i = 0; i < MESA_SHADER_STAGES; i++)
64 _mesa_reference_shader_program(ctx, &obj->CurrentProgram[i], NULL);
65
66 _mesa_reference_shader_program(ctx, &obj->ActiveProgram, NULL);
67 mtx_destroy(&obj->Mutex);
68 ralloc_free(obj);
69 }
70
71 /**
72 * Allocate and initialize a new pipeline object.
73 */
74 static struct gl_pipeline_object *
75 _mesa_new_pipeline_object(struct gl_context *ctx, GLuint name)
76 {
77 struct gl_pipeline_object *obj = rzalloc(NULL, struct gl_pipeline_object);
78 if (obj) {
79 obj->Name = name;
80 mtx_init(&obj->Mutex, mtx_plain);
81 obj->RefCount = 1;
82 obj->Flags = _mesa_get_shader_flags();
83 }
84
85 return obj;
86 }
87
88 /**
89 * Initialize pipeline object state for given context.
90 */
91 void
92 _mesa_init_pipeline(struct gl_context *ctx)
93 {
94 ctx->Pipeline.Objects = _mesa_NewHashTable();
95
96 ctx->Pipeline.Current = NULL;
97
98 /* Install a default Pipeline */
99 ctx->Pipeline.Default = _mesa_new_pipeline_object(ctx, 0);
100 _mesa_reference_pipeline_object(ctx, &ctx->_Shader, ctx->Pipeline.Default);
101 }
102
103
104 /**
105 * Callback for deleting a pipeline object. Called by _mesa_HashDeleteAll().
106 */
107 static void
108 delete_pipelineobj_cb(GLuint id, void *data, void *userData)
109 {
110 struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data;
111 struct gl_context *ctx = (struct gl_context *) userData;
112 _mesa_delete_pipeline_object(ctx, obj);
113 }
114
115
116 /**
117 * Free pipeline state for given context.
118 */
119 void
120 _mesa_free_pipeline_data(struct gl_context *ctx)
121 {
122 _mesa_HashDeleteAll(ctx->Pipeline.Objects, delete_pipelineobj_cb, ctx);
123 _mesa_DeleteHashTable(ctx->Pipeline.Objects);
124
125 _mesa_reference_pipeline_object(ctx, &ctx->_Shader, NULL);
126 _mesa_delete_pipeline_object(ctx, ctx->Pipeline.Default);
127
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 static inline struct gl_pipeline_object *
139 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_HashLookup(ctx->Pipeline.Objects, id);
146 }
147
148 /**
149 * Add the given pipeline object to the pipeline object pool.
150 */
151 static void
152 save_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
153 {
154 if (obj->Name > 0) {
155 _mesa_HashInsert(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
164 remove_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
165 {
166 if (obj->Name > 0) {
167 _mesa_HashRemove(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
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 GLboolean deleteFlag = GL_FALSE;
186 struct gl_pipeline_object *oldObj = *ptr;
187
188 mtx_lock(&oldObj->Mutex);
189 ASSERT(oldObj->RefCount > 0);
190 oldObj->RefCount--;
191 deleteFlag = (oldObj->RefCount == 0);
192 mtx_unlock(&oldObj->Mutex);
193
194 if (deleteFlag) {
195 _mesa_delete_pipeline_object(ctx, oldObj);
196 }
197
198 *ptr = NULL;
199 }
200 ASSERT(!*ptr);
201
202 if (obj) {
203 /* reference new pipeline object */
204 mtx_lock(&obj->Mutex);
205 if (obj->RefCount == 0) {
206 /* this pipeline's being deleted (look just above) */
207 /* Not sure this can ever really happen. Warn if it does. */
208 _mesa_problem(NULL, "referencing deleted pipeline object");
209 *ptr = NULL;
210 }
211 else {
212 obj->RefCount++;
213 *ptr = obj;
214 }
215 mtx_unlock(&obj->Mutex);
216 }
217 }
218
219 /**
220 * Bound program to severals stages of the pipeline
221 */
222 void GLAPIENTRY
223 _mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program)
224 {
225 GET_CURRENT_CONTEXT(ctx);
226
227 struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline);
228 struct gl_shader_program *shProg = NULL;
229
230 if (!pipe) {
231 _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgramStages(pipeline)");
232 return;
233 }
234
235 /* Object is created by any Pipeline call but glGenProgramPipelines,
236 * glIsProgramPipeline and GetProgramPipelineInfoLog
237 */
238 pipe->EverBound = GL_TRUE;
239
240 /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec says:
241 *
242 * "If stages is not the special value ALL_SHADER_BITS, and has a bit
243 * set that is not recognized, the error INVALID_VALUE is generated."
244 *
245 * NOT YET SUPPORTED:
246 * GL_TESS_CONTROL_SHADER_BIT
247 * GL_TESS_EVALUATION_SHADER_BIT
248 */
249 GLbitfield any_valid_stages = GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT;
250 if (_mesa_has_geometry_shaders(ctx))
251 any_valid_stages |= GL_GEOMETRY_SHADER_BIT;
252
253 if (stages != GL_ALL_SHADER_BITS && (stages & ~any_valid_stages) != 0) {
254 _mesa_error(ctx, GL_INVALID_VALUE, "glUseProgramStages(Stages)");
255 return;
256 }
257
258 /* Section 2.17.2 (Transform Feedback Primitive Capture) of the OpenGL 4.1
259 * spec says:
260 *
261 * "The error INVALID_OPERATION is generated:
262 *
263 * ...
264 *
265 * - by UseProgramStages if the program pipeline object it refers
266 * to is current and the current transform feedback object is
267 * active and not paused;
268 */
269 if (ctx->_Shader == pipe) {
270 if (_mesa_is_xfb_active_and_unpaused(ctx)) {
271 _mesa_error(ctx, GL_INVALID_OPERATION,
272 "glUseProgramStages(transform feedback active)");
273 return;
274 }
275 }
276
277 if (program) {
278 shProg = _mesa_lookup_shader_program_err(ctx, program,
279 "glUseProgramStages");
280 if (shProg == NULL)
281 return;
282
283 /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec
284 * says:
285 *
286 * "If the program object named by program was linked without the
287 * PROGRAM_SEPARABLE parameter set, or was not linked successfully,
288 * the error INVALID_OPERATION is generated and the corresponding
289 * shader stages in the pipeline program pipeline object are not
290 * modified."
291 */
292 if (!shProg->LinkStatus) {
293 _mesa_error(ctx, GL_INVALID_OPERATION,
294 "glUseProgramStages(program not linked)");
295 return;
296 }
297
298 if (!shProg->SeparateShader) {
299 _mesa_error(ctx, GL_INVALID_OPERATION,
300 "glUseProgramStages(program wasn't linked with the "
301 "PROGRAM_SEPARABLE flag)");
302 return;
303 }
304 }
305
306 /* Enable individual stages from the program as requested by the
307 * application. If there is no shader for a requested stage in the
308 * program, _mesa_use_shader_program will enable fixed-function processing
309 * as dictated by the spec.
310 *
311 * Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec
312 * says:
313 *
314 * "If UseProgramStages is called with program set to zero or with a
315 * program object that contains no executable code for the given
316 * stages, it is as if the pipeline object has no programmable stage
317 * configured for the indicated shader stages."
318 */
319 if ((stages & GL_VERTEX_SHADER_BIT) != 0)
320 _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, shProg, pipe);
321
322 if ((stages & GL_FRAGMENT_SHADER_BIT) != 0)
323 _mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg, pipe);
324
325 if ((stages & GL_GEOMETRY_SHADER_BIT) != 0)
326 _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER, shProg, pipe);
327 }
328
329 /**
330 * Use the named shader program for subsequent glUniform calls (if pipeline
331 * bound)
332 */
333 void GLAPIENTRY
334 _mesa_ActiveShaderProgram(GLuint pipeline, GLuint program)
335 {
336 GET_CURRENT_CONTEXT(ctx);
337 struct gl_shader_program *shProg = NULL;
338 struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline);
339
340 if (program != 0) {
341 shProg = _mesa_lookup_shader_program_err(ctx, program,
342 "glActiveShaderProgram(program)");
343 if (shProg == NULL)
344 return;
345 }
346
347 if (!pipe) {
348 _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(pipeline)");
349 return;
350 }
351
352 /* Object is created by any Pipeline call but glGenProgramPipelines,
353 * glIsProgramPipeline and GetProgramPipelineInfoLog
354 */
355 pipe->EverBound = GL_TRUE;
356
357 if ((shProg != NULL) && !shProg->LinkStatus) {
358 _mesa_error(ctx, GL_INVALID_OPERATION,
359 "glActiveShaderProgram(program %u not linked)", shProg->Name);
360 return;
361 }
362
363 _mesa_reference_shader_program(ctx, &pipe->ActiveProgram, shProg);
364 }
365
366 /**
367 * Make program of the pipeline current
368 */
369 void GLAPIENTRY
370 _mesa_BindProgramPipeline(GLuint pipeline)
371 {
372 }
373
374 /**
375 * Delete a set of pipeline objects.
376 *
377 * \param n Number of pipeline objects to delete.
378 * \param ids pipeline of \c n pipeline object IDs.
379 */
380 void GLAPIENTRY
381 _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines)
382 {
383 GET_CURRENT_CONTEXT(ctx);
384 GLsizei i;
385
386 if (n < 0) {
387 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgramPipelines(n<0)");
388 return;
389 }
390
391 for (i = 0; i < n; i++) {
392 struct gl_pipeline_object *obj =
393 lookup_pipeline_object(ctx, pipelines[i]);
394
395 if (obj) {
396 ASSERT(obj->Name == pipelines[i]);
397
398 /* If the pipeline object is currently bound, the spec says "If an
399 * object that is currently bound is deleted, the binding for that
400 * object reverts to zero and no program pipeline object becomes
401 * current."
402 */
403 if (obj == ctx->Pipeline.Current) {
404 _mesa_BindProgramPipeline(0);
405 }
406
407 /* The ID is immediately freed for re-use */
408 remove_pipeline_object(ctx, obj);
409
410 /* Unreference the pipeline object.
411 * If refcount hits zero, the object will be deleted.
412 */
413 _mesa_reference_pipeline_object(ctx, &obj, NULL);
414 }
415 }
416 }
417
418 /**
419 * Generate a set of unique pipeline object IDs and store them in \c pipelines.
420 * \param n Number of IDs to generate.
421 * \param pipelines pipeline of \c n locations to store the IDs.
422 */
423 void GLAPIENTRY
424 _mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines)
425 {
426 GET_CURRENT_CONTEXT(ctx);
427
428 GLuint first;
429 GLint i;
430
431 if (n < 0) {
432 _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramPipelines(n<0)");
433 return;
434 }
435
436 if (!pipelines) {
437 return;
438 }
439
440 first = _mesa_HashFindFreeKeyBlock(ctx->Pipeline.Objects, n);
441
442 for (i = 0; i < n; i++) {
443 struct gl_pipeline_object *obj;
444 GLuint name = first + i;
445
446 obj = _mesa_new_pipeline_object(ctx, name);
447 if (!obj) {
448 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramPipelines");
449 return;
450 }
451
452 save_pipeline_object(ctx, obj);
453 pipelines[i] = first + i;
454 }
455
456 }
457
458 /**
459 * Determine if ID is the name of an pipeline object.
460 *
461 * \param id ID of the potential pipeline object.
462 * \return \c GL_TRUE if \c id is the name of a pipeline object,
463 * \c GL_FALSE otherwise.
464 */
465 GLboolean GLAPIENTRY
466 _mesa_IsProgramPipeline(GLuint pipeline)
467 {
468 GET_CURRENT_CONTEXT(ctx);
469
470 struct gl_pipeline_object *obj = lookup_pipeline_object(ctx, pipeline);
471 if (obj == NULL)
472 return GL_FALSE;
473
474 return obj->EverBound;
475 }
476
477 /**
478 * glGetProgramPipelineiv() - get pipeline shader state.
479 */
480 void GLAPIENTRY
481 _mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params)
482 {
483 GET_CURRENT_CONTEXT(ctx);
484 struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline);
485
486 /* Are geometry shaders available in this context?
487 */
488 const bool has_gs = _mesa_has_geometry_shaders(ctx);
489
490 if (!pipe) {
491 _mesa_error(ctx, GL_INVALID_OPERATION,
492 "glGetProgramPipelineiv(pipeline)");
493 return;
494 }
495
496 /* Object is created by any Pipeline call but glGenProgramPipelines,
497 * glIsProgramPipeline and GetProgramPipelineInfoLog
498 */
499 pipe->EverBound = GL_TRUE;
500
501 switch (pname) {
502 case GL_ACTIVE_PROGRAM:
503 *params = pipe->ActiveProgram ? pipe->ActiveProgram->Name : 0;
504 return;
505 case GL_INFO_LOG_LENGTH:
506 /* FINISHME: Implement the info log.
507 */
508 *params = 0;
509 return;
510 case GL_VALIDATE_STATUS:
511 /* FINISHME: Implement validation status.
512 */
513 *params = 0;
514 return;
515 case GL_VERTEX_SHADER:
516 *params = pipe->CurrentProgram[MESA_SHADER_VERTEX]
517 ? pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name : 0;
518 return;
519 case GL_TESS_EVALUATION_SHADER:
520 /* NOT YET SUPPORTED */
521 break;
522 case GL_TESS_CONTROL_SHADER:
523 /* NOT YET SUPPORTED */
524 break;
525 case GL_GEOMETRY_SHADER:
526 if (!has_gs)
527 break;
528 *params = pipe->CurrentProgram[MESA_SHADER_GEOMETRY]
529 ? pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Name : 0;
530 return;
531 case GL_FRAGMENT_SHADER:
532 *params = pipe->CurrentProgram[MESA_SHADER_FRAGMENT]
533 ? pipe->CurrentProgram[MESA_SHADER_FRAGMENT]->Name : 0;
534 return;
535 default:
536 break;
537 }
538
539 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramPipelineiv(pname=%s)",
540 _mesa_lookup_enum_by_nr(pname));
541 }
542
543 /**
544 * Check compatibility of pipeline's program
545 */
546 void GLAPIENTRY
547 _mesa_ValidateProgramPipeline(GLuint pipeline)
548 {
549 }
550
551 void GLAPIENTRY
552 _mesa_GetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize,
553 GLsizei *length, GLchar *infoLog)
554 {
555 }