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:
committed by
Ian Romanick
parent
0f137a1d73
commit
f4c13a890f
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user