On Fri, Feb 7, 2014 at 10:00 PM, Ian Romanick <i...@freedesktop.org> wrote: > From: Gregory Hainaut <gregory.hain...@gmail.com> > > 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. > > Reviewed-by: Ian Romanick <ian.d.roman...@intel.com> > --- > src/mesa/main/context.c | 3 + > src/mesa/main/mtypes.h | 22 +++++- > src/mesa/main/pipelineobj.c | 161 > ++++++++++++++++++++++++++++++++++++++++++++ > src/mesa/main/pipelineobj.h | 25 +++++++ > 4 files changed, 209 insertions(+), 2 deletions(-) > > diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c > index 8421a25..fe072ab 100644 > --- a/src/mesa/main/context.c > +++ b/src/mesa/main/context.c > @@ -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" > @@ -814,6 +815,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 ); > @@ -1219,6 +1221,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); > diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h > index 52aeb15..4b8749a 100644 > --- a/src/mesa/main/mtypes.h > +++ b/src/mesa/main/mtypes.h > @@ -2746,9 +2746,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; > @@ -2774,6 +2780,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 > @@ -4075,7 +4092,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 */ > diff --git a/src/mesa/main/pipelineobj.c b/src/mesa/main/pipelineobj.c > index 7454619..a82e3ed 100644 > --- a/src/mesa/main/pipelineobj.c > +++ b/src/mesa/main/pipelineobj.c > @@ -30,6 +30,9 @@ > * Implementation of pipeline object related API functions. Based on > * GL_ARB_separate_shader_objects extension. > * > + * \todo > + * Do we need to create CreatePipelineObject and DeletePipelineObject driver > + * functions? > */
I don't know. Another question .. do we need this todo comment? :) > #include "main/glheader.h" > @@ -50,6 +53,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 every really happen. Warn if it does. */ every => ever 1-7: Reviewed-by: Jordan Justen <jordan.l.jus...@intel.com> -Jordan > + _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 > diff --git a/src/mesa/main/pipelineobj.h b/src/mesa/main/pipelineobj.h > index 56d32cc..46d5fab 100644 > --- a/src/mesa/main/pipelineobj.h > +++ b/src/mesa/main/pipelineobj.h > @@ -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); > -- > 1.8.1.4 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev