mesa/sso: Add pipeline container/state

V1:
* Extend gl_shader_state as pipeline object state
* Add a new container gl_pipeline_shader_state that contains
   binding point of the previous object
* Update mesa init/free shader state due to the extension of
   the attibute
* Add an init/free pipeline function for the context

V2:
* Rename gl_shader_state to gl_pipeline_object
* Rename Pipeline.PipelineObj to Pipeline.Current
* Formatting improvement

V3 (idr):
* Split out from previous uber patch.
* Remove '#if 0' debug printfs.

V4 (idr):
* Fix some errors in comments.  Suggested by Jordan.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
This commit is contained in:
Gregory Hainaut
2013-06-28 13:54:06 -07:00
committed by Ian Romanick
parent 0f137a1d73
commit f4c13a890f
4 changed files with 206 additions and 3 deletions
+3
View File
@@ -106,6 +106,7 @@
#include "matrix.h"
#include "multisample.h"
#include "performance_monitor.h"
#include "pipelineobj.h"
#include "pixel.h"
#include "pixelstore.h"
#include "points.h"
@@ -811,6 +812,7 @@ init_attrib_groups(struct gl_context *ctx)
_mesa_init_matrix( ctx );
_mesa_init_multisample( ctx );
_mesa_init_performance_monitors( ctx );
_mesa_init_pipeline( ctx );
_mesa_init_pixel( ctx );
_mesa_init_pixelstore( ctx );
_mesa_init_point( ctx );
@@ -1216,6 +1218,7 @@ _mesa_free_context_data( struct gl_context *ctx )
_mesa_free_texture_data( ctx );
_mesa_free_matrix_data( ctx );
_mesa_free_viewport_data( ctx );
_mesa_free_pipeline_data(ctx);
_mesa_free_program_data(ctx);
_mesa_free_shader_state(ctx);
_mesa_free_queryobj_data(ctx);
+20 -2
View File
@@ -2757,9 +2757,15 @@ struct gl_shader_program
/**
* Context state for GLSL vertex/fragment shaders.
* Extended to support pipeline object
*/
struct gl_shader_state
struct gl_pipeline_object
{
/** Name of the pipeline object as received from glGenProgramPipelines.
* It would be 0 for shaders without separate shader objects.
*/
GLuint Name;
GLint RefCount;
_glthread_Mutex Mutex;
@@ -2785,6 +2791,17 @@ struct gl_shader_state
GLbitfield Flags; /**< Mask of GLSL_x flags */
};
/**
* Context state for GLSL pipeline shaders.
*/
struct gl_pipeline_shader_state
{
/** Currently bound pipeline object. See _mesa_BindProgramPipeline() */
struct gl_pipeline_object *Current;
/** Pipeline objects */
struct _mesa_HashTable *Objects;
};
/**
* Compiler options for a single GLSL shaders type
@@ -4085,7 +4102,8 @@ struct gl_context
struct gl_geometry_program_state GeometryProgram;
struct gl_ati_fragment_shader_state ATIFragmentShader;
struct gl_shader_state Shader; /**< GLSL shader object state */
struct gl_pipeline_shader_state Pipeline; /**< GLSL pipeline shader object state */
struct gl_pipeline_object Shader; /**< GLSL shader object state */
struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES];
struct gl_query_state Query; /**< occlusion, timer queries */
+158 -1
View File
@@ -29,7 +29,6 @@
*
* Implementation of pipeline object related API functions. Based on
* GL_ARB_separate_shader_objects extension.
*
*/
#include "main/glheader.h"
@@ -50,6 +49,164 @@
#include "../glsl/glsl_parser_extras.h"
#include "../glsl/ir_uniform.h"
/**
* Delete a pipeline object.
*/
void
_mesa_delete_pipeline_object(struct gl_context *ctx,
struct gl_pipeline_object *obj)
{
unsinged i;
_mesa_reference_shader_program(ctx, &obj->_CurrentFragmentProgram, NULL);
for (i = 0; i < MESA_SHADER_STAGES; i++)
_mesa_reference_shader_program(ctx, &obj->CurrentProgram[i], NULL);
_mesa_reference_shader_program(ctx, &obj->ActiveProgram, NULL);
_glthread_DESTROY_MUTEX(obj->Mutex);
ralloc_free(obj);
}
/**
* Allocate and initialize a new pipeline object.
*/
static struct gl_pipeline_object *
_mesa_new_pipeline_object(struct gl_context *ctx, GLuint name)
{
struct gl_pipeline_object *obj = rzalloc(NULL, struct gl_pipeline_object);
if (obj) {
obj->Name = name;
_glthread_INIT_MUTEX(obj->Mutex);
obj->RefCount = 1;
obj->Flags = _mesa_get_shader_flags();
}
return obj;
}
/**
* Initialize pipeline object state for given context.
*/
void
_mesa_init_pipeline(struct gl_context *ctx)
{
ctx->Pipeline.Objects = _mesa_NewHashTable();
ctx->Pipeline.Current = NULL;
}
/**
* Callback for deleting a pipeline object. Called by _mesa_HashDeleteAll().
*/
static void
delete_pipelineobj_cb(GLuint id, void *data, void *userData)
{
struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data;
struct gl_context *ctx = (struct gl_context *) userData;
_mesa_delete_pipeline_object(ctx, obj);
}
/**
* Free pipeline state for given context.
*/
void
_mesa_free_pipeline_data(struct gl_context *ctx)
{
_mesa_HashDeleteAll(ctx->Pipeline.Objects, delete_pipelineobj_cb, ctx);
_mesa_DeleteHashTable(ctx->Pipeline.Objects);
}
/**
* Look up the pipeline object for the given ID.
*
* \returns
* Either a pointer to the pipeline object with the specified ID or \c NULL for
* a non-existent ID. The spec defines ID 0 as being technically
* non-existent.
*/
static inline struct gl_pipeline_object *
lookup_pipeline_object(struct gl_context *ctx, GLuint id)
{
if (id == 0)
return NULL;
else
return (struct gl_pipeline_object *)
_mesa_HashLookup(ctx->Pipeline.Objects, id);
}
/**
* Add the given pipeline object to the pipeline object pool.
*/
static void
save_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
{
if (obj->Name > 0) {
_mesa_HashInsert(ctx->Pipeline.Objects, obj->Name, obj);
}
}
/**
* Remove the given pipeline object from the pipeline object pool.
* Do not deallocate the pipeline object though.
*/
static void
remove_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
{
if (obj->Name > 0) {
_mesa_HashRemove(ctx->Pipeline.Objects, obj->Name);
}
}
/**
* Set ptr to obj w/ reference counting.
* Note: this should only be called from the _mesa_reference_pipeline_object()
* inline function.
*/
void
_mesa_reference_pipeline_object_(struct gl_context *ctx,
struct gl_pipeline_object **ptr,
struct gl_pipeline_object *obj)
{
assert(*ptr != obj);
if (*ptr) {
/* Unreference the old pipeline object */
GLboolean deleteFlag = GL_FALSE;
struct gl_pipeline_object *oldObj = *ptr;
_glthread_LOCK_MUTEX(oldObj->Mutex);
ASSERT(oldObj->RefCount > 0);
oldObj->RefCount--;
deleteFlag = (oldObj->RefCount == 0);
_glthread_UNLOCK_MUTEX(oldObj->Mutex);
if (deleteFlag) {
_mesa_delete_pipeline_object(ctx, oldObj);
}
*ptr = NULL;
}
ASSERT(!*ptr);
if (obj) {
/* reference new pipeline object */
_glthread_LOCK_MUTEX(obj->Mutex);
if (obj->RefCount == 0) {
/* this pipeline's being deleted (look just above) */
/* Not sure this can ever really happen. Warn if it does. */
_mesa_problem(NULL, "referencing deleted pipeline object");
*ptr = NULL;
}
else {
obj->RefCount++;
*ptr = obj;
}
_glthread_UNLOCK_MUTEX(obj->Mutex);
}
}
/**
* Bound program to severals stages of the pipeline
+25
View File
@@ -34,6 +34,31 @@ extern "C" {
struct _glapi_table;
struct gl_context;
struct gl_pipeline_object;
extern void
_mesa_delete_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj);
extern void
_mesa_init_pipeline(struct gl_context *ctx);
extern void
_mesa_free_pipeline_data(struct gl_context *ctx);
extern void
_mesa_reference_pipeline_object_(struct gl_context *ctx,
struct gl_pipeline_object **ptr,
struct gl_pipeline_object *obj);
static inline void
_mesa_reference_pipeline_object(struct gl_context *ctx,
struct gl_pipeline_object **ptr,
struct gl_pipeline_object *obj)
{
if (*ptr != obj)
_mesa_reference_pipeline_object_(ctx, ptr, obj);
}
extern void GLAPIENTRY
_mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program);