r600: enable caching of vertex programs
authorAndre Maasikas <amaasikas@gmail.com>
Fri, 11 Sep 2009 14:59:05 +0000 (10:59 -0400)
committerAlex Deucher <alexdeucher@gmail.com>
Thu, 24 Sep 2009 13:59:00 +0000 (09:59 -0400)
src/mesa/drivers/dri/r600/r600_context.h
src/mesa/drivers/dri/r600/r700_chip.c
src/mesa/drivers/dri/r600/r700_oglprog.c
src/mesa/drivers/dri/r600/r700_render.c
src/mesa/drivers/dri/r600/r700_vertprog.c
src/mesa/drivers/dri/r600/r700_vertprog.h

index 8ae05a301c7bc7d872333cbe3d9c055d370f8803..c59df7505af85bfc2fc8d4eab4cc10ee7895813d 100644 (file)
@@ -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];
index 312cacffda339c27f16b059b43bed9b54bed8277..1b560591974a6e30b0ab324c7d521f38473c1845 100644 (file)
@@ -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,
index 3c8c1fd7a34e5b3c96095b12c72cd7a0ffa551c7..5290ef31be3a4173ef560c47c2c0d26ebb7c1c1b 100644 (file)
@@ -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:
index 3566bf3ca78fb6c804ee88f78cd19fb80e425f5b..b1c3648ca568867685e29afac3fb875d97d4a4a8 100644 (file)
@@ -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))
index d107f99e7ba7f60d626a87717d0301f53d314fd1..8c2b0071df981f45edd7deec5ee802d6325c1408 100644 (file)
@@ -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);
index e2e65021fd32c5c3ff3d52802e97b66733e200b4..c48764c43ba423989f6173b4cc7066a7be191f31 100644 (file)
@@ -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 */