Mesa (mesa_7_6_branch): r600: enable caching of vertex programs

Alex Deucher agd5f at kemper.freedesktop.org
Thu Sep 24 14:06:27 UTC 2009


Module: Mesa
Branch: mesa_7_6_branch
Commit: 9edd1a441c3c0c3f018ae561cd5711398ca56f95
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=9edd1a441c3c0c3f018ae561cd5711398ca56f95

Author: Andre Maasikas <amaasikas at gmail.com>
Date:   Fri Sep 11 10:59:05 2009 -0400

r600: enable caching of vertex programs

---

 src/mesa/drivers/dri/r600/r600_context.h  |    3 +
 src/mesa/drivers/dri/r600/r700_chip.c     |   10 +--
 src/mesa/drivers/dri/r600/r700_oglprog.c  |   36 +++++-----
 src/mesa/drivers/dri/r600/r700_render.c   |    9 ++-
 src/mesa/drivers/dri/r600/r700_vertprog.c |  103 +++++++++++++++++++---------
 src/mesa/drivers/dri/r600/r700_vertprog.h |   11 +++-
 6 files changed, 110 insertions(+), 62 deletions(-)

diff --git a/src/mesa/drivers/dri/r600/r600_context.h b/src/mesa/drivers/dri/r600/r600_context.h
index 8ae05a3..c59df75 100644
--- a/src/mesa/drivers/dri/r600/r600_context.h
+++ b/src/mesa/drivers/dri/r600/r600_context.h
@@ -51,6 +51,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r700_chip.h"
 #include "r600_tex.h"
 #include "r700_oglprog.h"
+#include "r700_vertprog.h"
 
 struct r600_context;
 typedef struct r600_context context_t;
@@ -155,6 +156,8 @@ struct r600_context {
 
 	struct r600_hw_state atoms;
 
+	struct r700_vertex_program *selected_vp;
+
 	/* Vertex buffers
 	 */
 	GLvector4f dummy_attrib[_TNL_ATTRIB_MAX];
diff --git a/src/mesa/drivers/dri/r600/r700_chip.c b/src/mesa/drivers/dri/r600/r700_chip.c
index 312cacf..1b56059 100644
--- a/src/mesa/drivers/dri/r600/r700_chip.c
+++ b/src/mesa/drivers/dri/r600/r700_chip.c
@@ -211,8 +211,7 @@ static void r700SetupVTXConstants(GLcontext  * ctx,
 void r700SetupStreams(GLcontext *ctx)
 {
     context_t         *context = R700_CONTEXT(ctx);
-     struct r700_vertex_program *vpc
-             = (struct r700_vertex_program *)ctx->VertexProgram._Current;
+    struct r700_vertex_program *vp = context->selected_vp;
     TNLcontext *tnl = TNL_CONTEXT(ctx);
     struct vertex_buffer *vb = &tnl->vb;
     unsigned int i, j = 0;
@@ -221,7 +220,7 @@ void r700SetupStreams(GLcontext *ctx)
     R600_STATECHANGE(context, vtx);
 
     for(i=0; i<VERT_ATTRIB_MAX; i++) {
-	    if(vpc->mesa_program.Base.InputsRead & (1 << i)) {
+	    if(vp->mesa_program->Base.InputsRead & (1 << i)) {
 		    rcommon_emit_vector(ctx,
 					&context->radeon.tcl.aos[j],
 					vb->AttribPtr[i]->data,
@@ -237,8 +236,7 @@ void r700SetupStreams(GLcontext *ctx)
 static void r700SendVTXState(GLcontext *ctx, struct radeon_state_atom *atom)
 {
     context_t         *context = R700_CONTEXT(ctx);
-    struct r700_vertex_program *vpc
-             = (struct r700_vertex_program *)ctx->VertexProgram._Current;
+    struct r700_vertex_program *vp = context->selected_vp;
     unsigned int i, j = 0;
     BATCH_LOCALS(&context->radeon);
 	radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
@@ -258,7 +256,7 @@ static void r700SendVTXState(GLcontext *ctx, struct radeon_state_atom *atom)
     COMMIT_BATCH();
 
     for(i=0; i<VERT_ATTRIB_MAX; i++) {
-	    if(vpc->mesa_program.Base.InputsRead & (1 << i)) {
+	    if(vp->mesa_program->Base.InputsRead & (1 << i)) {
 		    /* currently aos are packed */
 		    r700SetupVTXConstants(ctx,
 					  i,
diff --git a/src/mesa/drivers/dri/r600/r700_oglprog.c b/src/mesa/drivers/dri/r600/r700_oglprog.c
index 3c8c1fd..5290ef3 100644
--- a/src/mesa/drivers/dri/r600/r700_oglprog.c
+++ b/src/mesa/drivers/dri/r600/r700_oglprog.c
@@ -46,7 +46,7 @@ static struct gl_program *r700NewProgram(GLcontext * ctx,
 {
 	struct gl_program *pProgram = NULL;
 
-    struct r700_vertex_program *vp;
+    struct r700_vertex_program_cont *vpc;
 	struct r700_fragment_program *fp;
 
 	radeon_print(RADEON_SHADER, RADEON_VERBOSE,
@@ -56,16 +56,11 @@ static struct gl_program *r700NewProgram(GLcontext * ctx,
     {
     case GL_VERTEX_STATE_PROGRAM_NV:
     case GL_VERTEX_PROGRAM_ARB:	    
-        vp       = CALLOC_STRUCT(r700_vertex_program);
+        vpc       = CALLOC_STRUCT(r700_vertex_program_cont);
 	    pProgram = _mesa_init_vertex_program(ctx, 
-                                             &vp->mesa_program,
+                                             &vpc->mesa_program,
 					                         target, 
                                              id);
-        vp->translated = GL_FALSE;
-        vp->loaded     = GL_FALSE;
- 
-        vp->shaderbo   = NULL;
-
 	    break;
     case GL_FRAGMENT_PROGRAM_NV:
     case GL_FRAGMENT_PROGRAM_ARB:
@@ -89,7 +84,8 @@ static struct gl_program *r700NewProgram(GLcontext * ctx,
 
 static void r700DeleteProgram(GLcontext * ctx, struct gl_program *prog)
 {
-    struct r700_vertex_program   * vp;
+    struct r700_vertex_program_cont   * vpc;
+    struct r700_vertex_program *vp, *tmp;
     struct r700_fragment_program * fp;
 
 	radeon_print(RADEON_SHADER, RADEON_VERBOSE,
@@ -99,14 +95,20 @@ static void r700DeleteProgram(GLcontext * ctx, struct gl_program *prog)
     {
     case GL_VERTEX_STATE_PROGRAM_NV:
     case GL_VERTEX_PROGRAM_ARB:	    
-        vp = (struct r700_vertex_program*)prog;
-        /* Release DMA region */
-
-        r600DeleteShader(ctx, vp->shaderbo);
-
-        /* Clean up */
-        Clean_Up_Assembler(&(vp->r700AsmCode));
-        Clean_Up_Shader(&(vp->r700Shader));
+        vpc = (struct r700_vertex_program_cont*)prog;
+        vp = vpc->progs;
+	while (vp) {
+		tmp = vp->next;
+		/* Release DMA region */
+	 
+	        r600DeleteShader(ctx, vp->shaderbo);
+
+	        /* Clean up */
+	        Clean_Up_Assembler(&(vp->r700AsmCode));
+	        Clean_Up_Shader(&(vp->r700Shader));
+		_mesa_free(vp);
+		vp = tmp;
+	}
 	    break;
     case GL_FRAGMENT_PROGRAM_NV:
     case GL_FRAGMENT_PROGRAM_ARB:
diff --git a/src/mesa/drivers/dri/r600/r700_render.c b/src/mesa/drivers/dri/r600/r700_render.c
index 3566bf3..b1c3648 100644
--- a/src/mesa/drivers/dri/r600/r700_render.c
+++ b/src/mesa/drivers/dri/r600/r700_render.c
@@ -319,14 +319,13 @@ static GLuint r700PredictRenderSize(GLcontext* ctx)
 {
     context_t *context = R700_CONTEXT(ctx);
     TNLcontext *tnl = TNL_CONTEXT(ctx);
-    struct r700_vertex_program *vpc
-        = (struct r700_vertex_program *)ctx->VertexProgram._Current;
+    struct r700_vertex_program *vp = context->selected_vp;
     struct vertex_buffer *vb = &tnl->vb;
     GLboolean flushed;
     GLuint dwords, i;
     GLuint state_size;
     /* pre calculate aos count so state prediction works */
-    context->radeon.tcl.aos_count = _mesa_bitcount(vpc->mesa_program.Base.InputsRead);
+    context->radeon.tcl.aos_count = _mesa_bitcount(vp->mesa_program->Base.InputsRead);
 
     dwords = PRE_EMIT_STATE_BUFSZ;
     for (i = 0; i < vb->PrimitiveCount; i++)
@@ -365,7 +364,6 @@ static GLboolean r700RunRender(GLcontext * ctx,
     /* mark vtx as dirty since it changes per-draw */
     R600_STATECHANGE(context, vtx);
 
-    r700UpdateShaders(ctx);
     r700SetScissor(context);
     r700SetupVertexProgram(ctx);
     r700SetupFragmentProgram(ctx);
@@ -427,7 +425,10 @@ static GLboolean r700RunTCLRender(GLcontext * ctx,  /*----------------------*/
 
     /* TODO : sw fallback */
 
+    /* Need shader bo's setup before bo check */
+    r700UpdateShaders(ctx);
     /**
+
     * Ensure all enabled and complete textures are uploaded along with any buffers being used.
     */
     if(!r600ValidateBuffers(ctx))
diff --git a/src/mesa/drivers/dri/r600/r700_vertprog.c b/src/mesa/drivers/dri/r600/r700_vertprog.c
index d107f99..8c2b007 100644
--- a/src/mesa/drivers/dri/r600/r700_vertprog.c
+++ b/src/mesa/drivers/dri/r600/r700_vertprog.c
@@ -35,6 +35,7 @@
 #include "main/mtypes.h"
 
 #include "tnl/t_context.h"
+#include "shader/program.h"
 #include "shader/prog_parameter.h"
 #include "shader/prog_statevars.h"
 
@@ -258,28 +259,54 @@ GLboolean Find_Instruction_Dependencies_vp(struct r700_vertex_program *vp,
     return GL_TRUE;
 }
 
-GLboolean r700TranslateVertexShader(struct r700_vertex_program *vp,
-							   struct gl_vertex_program   *mesa_vp)
+struct r700_vertex_program* r700TranslateVertexShader(GLcontext *ctx,
+						struct gl_vertex_program *mesa_vp)
 {
+	context_t *context = R700_CONTEXT(ctx);
+	struct r700_vertex_program *vp;
+	TNLcontext *tnl = TNL_CONTEXT(ctx);
+	struct vertex_buffer *vb = &tnl->vb;
+	unsigned int unBit;
+	unsigned int i;
+
+	vp = _mesa_calloc(sizeof(*vp));
+	vp->mesa_program = (struct gl_vertex_program *)_mesa_clone_program(ctx, &mesa_vp->Base);
+
+	for(i=0; i<VERT_ATTRIB_MAX; i++)
+	{
+		unBit = 1 << i;
+		if(vp->mesa_program->Base.InputsRead & unBit) /* ctx->Array.ArrayObj->xxxxxxx */
+		{
+			vp->aos_desc[i].size   = vb->AttribPtr[i]->size;
+			vp->aos_desc[i].stride = vb->AttribPtr[i]->size * sizeof(GL_FLOAT);/* when emit array, data is packed. vb->AttribPtr[i]->stride;*/
+			vp->aos_desc[i].type   = GL_FLOAT;
+		}
+	}
+	
+	if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
+	{
+		vp->r700AsmCode.bR6xx = 1;
+	}
+
 	//Init_Program
 	Init_r700_AssemblerBase(SPT_VP, &(vp->r700AsmCode), &(vp->r700Shader) );
 	Map_Vertex_Program( vp, mesa_vp );
 
 	if(GL_FALSE == Find_Instruction_Dependencies_vp(vp, mesa_vp))
 	{
-		return GL_FALSE;
+		return NULL;
     }
 
 	if(GL_FALSE == AssembleInstr(mesa_vp->Base.NumInstructions,
                                  &(mesa_vp->Base.Instructions[0]), 
                                  &(vp->r700AsmCode)) )
 	{
-		return GL_FALSE;
+		return NULL;
 	} 
 
     if(GL_FALSE == Process_Vertex_Exports(&(vp->r700AsmCode), mesa_vp->Base.OutputsWritten) )
     {
-        return GL_FALSE;
+        return NULL;
     }
 
     vp->r700Shader.nRegs = (vp->r700AsmCode.number_used_registers == 0) ? 0 
@@ -289,72 +316,82 @@ GLboolean r700TranslateVertexShader(struct r700_vertex_program *vp,
 
     vp->translated = GL_TRUE;
 
-	return GL_TRUE;
+	return vp;
 }
 
 void r700SelectVertexShader(GLcontext *ctx)
 {
     context_t *context = R700_CONTEXT(ctx);
-    struct r700_vertex_program *vpc
-             = (struct r700_vertex_program *)ctx->VertexProgram._Current;
+    struct r700_vertex_program_cont *vpc;
+    struct r700_vertex_program *vp;
     TNLcontext *tnl = TNL_CONTEXT(ctx);
     struct vertex_buffer *vb = &tnl->vb;
     unsigned int unBit;
     unsigned int i;
+    GLboolean match;
 
+    vpc = (struct r700_vertex_program_cont *)ctx->VertexProgram._Current;
+
+#if 0
     if (context->radeon.NewGLState & (_NEW_PROGRAM_CONSTANTS|_NEW_PROGRAM))
     {
 	vpc->needUpdateVF = 1;
     }
+#endif
 
-    if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
+    for (vp = vpc->progs; vp; vp = vp->next)
     {
-        vpc->r700AsmCode.bR6xx = 1;
-    }
-
+	match = GL_TRUE;	
 	for(i=0; i<VERT_ATTRIB_MAX; i++)
 	{
 		unBit = 1 << i;
-		if(vpc->mesa_program.Base.InputsRead & unBit) /* ctx->Array.ArrayObj->xxxxxxx */
+                if(vpc->mesa_program.Base.InputsRead & unBit)
 		{
-			vpc->aos_desc[i].size   = vb->AttribPtr[i]->size;
-			vpc->aos_desc[i].stride = vb->AttribPtr[i]->size * sizeof(GL_FLOAT);/* when emit array, data is packed. vb->AttribPtr[i]->stride;*/
-			vpc->aos_desc[i].type   = GL_FLOAT;
+			if (vp->aos_desc[i].size != vb->AttribPtr[i]->size)
+				match = GL_FALSE;
+				break;
 		}
 	}
-
-	if(GL_FALSE == vpc->translated) {
-		r700TranslateVertexShader(vpc, &(vpc->mesa_program) );
+	if (match) 
+	{
+		context->selected_vp = vp;
+		return;
 	}
+    }
+
+    vp = r700TranslateVertexShader(ctx, &(vpc->mesa_program) );
+    if(!vp)
+    {
+	radeon_error("Failed to translate vertex shader. \n");
+	return;
+    }
+    vp->next = vpc->progs;
+    vpc->progs = vp;
+    context->selected_vp = vp;
+    return;
 }
 
 void * r700GetActiveVpShaderBo(GLcontext * ctx)
 {
-    struct r700_vertex_program *vp
-             = (struct r700_vertex_program *)ctx->VertexProgram._Current;
+    context_t *context = R700_CONTEXT(ctx);
+    struct r700_vertex_program *vp = context->selected_vp;;
 
-    return vp->shaderbo;
+    if (vp)
+	return vp->shaderbo;
+    else
+	return NULL;
 }
 
 GLboolean r700SetupVertexProgram(GLcontext * ctx)
 {
     context_t *context = R700_CONTEXT(ctx);
     R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
-    struct r700_vertex_program *vp
-             = (struct r700_vertex_program *)ctx->VertexProgram._Current;
+    struct r700_vertex_program *vp = context->selected_vp;
 
     struct gl_program_parameter_list *paramList;
     unsigned int unNumParamData;
     unsigned int ui;
 
-    if (vp->needUpdateVF)
-    {
-	vp->loaded = GL_FALSE;
-	vp->r700Shader.bNeedsAssembly = GL_TRUE;
-	Process_Vertex_Program_Vfetch_Instructions(vp, &(vp->mesa_program));
-	r600DeleteShader(ctx, vp->shaderbo);
-    }
-
     if(GL_FALSE == vp->loaded)
     {
 	    if(vp->r700Shader.bNeedsAssembly == GL_TRUE)
@@ -410,7 +447,7 @@ GLboolean r700SetupVertexProgram(GLcontext * ctx)
     */
 
     /* sent out shader constants. */
-    paramList = vp->mesa_program.Base.Parameters;
+    paramList = vp->mesa_program->Base.Parameters;
 
     if(NULL != paramList) {
 	    _mesa_load_state_parameters(ctx, paramList);
diff --git a/src/mesa/drivers/dri/r600/r700_vertprog.h b/src/mesa/drivers/dri/r600/r700_vertprog.h
index e2e6502..c48764c 100644
--- a/src/mesa/drivers/dri/r600/r700_vertprog.h
+++ b/src/mesa/drivers/dri/r600/r700_vertprog.h
@@ -43,7 +43,7 @@ typedef struct ArrayDesc //TEMP
 
 struct r700_vertex_program 
 {
-    struct gl_vertex_program mesa_program; /* Must be first */
+    struct gl_vertex_program *mesa_program; /* Must be first */
 
     struct r700_vertex_program *next;
 
@@ -59,6 +59,13 @@ struct r700_vertex_program
     ArrayDesc              aos_desc[VERT_ATTRIB_MAX];
 };
 
+struct r700_vertex_program_cont
+{
+    struct gl_vertex_program mesa_program;
+
+    struct r700_vertex_program *progs;
+};
+
 //Internal
 unsigned int Map_Vertex_Output(r700_AssemblerBase       *pAsm, 
 			       struct gl_vertex_program *mesa_vp,
@@ -74,7 +81,7 @@ void Map_Vertex_Program(struct r700_vertex_program *vp,
 GLboolean Find_Instruction_Dependencies_vp(struct r700_vertex_program *vp,
 					   struct gl_vertex_program   *mesa_vp);
 
-GLboolean r700TranslateVertexShader(struct r700_vertex_program *vp,
+struct r700_vertex_program* r700TranslateVertexShader(GLcontext *ctx,
 				    struct gl_vertex_program   *mesa_vp);
 
 /* Interface */




More information about the mesa-commit mailing list