r600g: take into account force_add_cf in pops
[mesa.git] / src / gallium / drivers / nvfx / nvfx_vertprog.c
index 6e5b6c093630b3caa560a6ee68f5dd3140b9b6f2..a11941f3d51ee89b0f43d098e1e382c451ba5ba1 100644 (file)
@@ -40,6 +40,7 @@ struct nvfx_vpc {
        struct nvfx_context* nvfx;
        struct pipe_shader_state pipe;
        struct nvfx_vertex_program *vp;
+       struct tgsi_shader_info* info;
 
        struct nvfx_vertex_program_exec *vpi;
 
@@ -376,6 +377,8 @@ tgsi_src(struct nvfx_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
        src.swz[2] = fsrc->Register.SwizzleZ;
        src.swz[3] = fsrc->Register.SwizzleW;
        src.indirect = 0;
+       src.indirect_reg = 0;
+       src.indirect_swz = 0;
 
        if(fsrc->Register.Indirect) {
                if(fsrc->Indirect.File == TGSI_FILE_ADDRESS &&
@@ -448,9 +451,7 @@ nvfx_vertprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_vpc *vpc,
        int mask;
        int ai = -1, ci = -1, ii = -1;
        int i;
-
-       if (finst->Instruction.Opcode == TGSI_OPCODE_END)
-               return TRUE;
+       unsigned sub_depth = 0;
 
        for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
                const struct tgsi_full_src_register *fsrc;
@@ -705,13 +706,24 @@ nvfx_vertprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_vpc *vpc,
                break;
 
        case TGSI_OPCODE_RET:
-               tmp = none;
-               tmp.swz[0] = tmp.swz[1] = tmp.swz[2] = tmp.swz[3] = 0;
-               nvfx_vp_emit(vpc, arith(0, SCA, RET, none.reg, 0, none, none, tmp));
+               if(sub_depth || !nvfx->use_vp_clipping) {
+                       tmp = none;
+                       tmp.swz[0] = tmp.swz[1] = tmp.swz[2] = tmp.swz[3] = 0;
+                       nvfx_vp_emit(vpc, arith(0, SCA, RET, none.reg, 0, none, none, tmp));
+               } else {
+                       reloc.location = vpc->vp->nr_insns;
+                       reloc.target = vpc->info->num_instructions;
+                       util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+                       nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
+               }
                break;
 
        case TGSI_OPCODE_BGNSUB:
+               ++sub_depth;
+               break;
        case TGSI_OPCODE_ENDSUB:
+               --sub_depth;
+               break;
        case TGSI_OPCODE_ENDIF:
                /* nothing to do here */
                break;
@@ -752,6 +764,23 @@ nvfx_vertprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_vpc *vpc,
                nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
                break;
 
+       case TGSI_OPCODE_END:
+               assert(!sub_depth);
+               if(nvfx->use_vp_clipping) {
+                       if(idx != (vpc->info->num_instructions - 1)) {
+                               reloc.location = vpc->vp->nr_insns;
+                               reloc.target = vpc->info->num_instructions;
+                               util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+                               nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
+                       }
+               } else {
+                       if(vpc->vp->nr_insns)
+                               vpc->vp->insns[vpc->vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
+                       nvfx_vp_emit(vpc, arith(0, VEC, NOP, none.reg, 0, none, none, none));
+                       vpc->vp->insns[vpc->vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
+               }
+               break;
+
        default:
                NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
                return FALSE;
@@ -851,7 +880,7 @@ nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc)
 
        /* hope 0xf is (0, 0, 0, 1) initialized; otherwise, we are _probably_ not required to do this */
        memset(vpc->vp->generic_to_fp_input, 0x0f, sizeof(vpc->vp->generic_to_fp_input));
-       for(int i = 0; i < 10; ++i) {
+       for(int i = 0; i < num_texcoords; ++i) {
                if(sem_layout[i] == 0xff)
                        continue;
                //printf("vp: GENERIC[%i] to fpreg %i\n", sem_layout[i], NVFX_FP_OP_INPUT_SRC_TC(0) + i);
@@ -859,7 +888,7 @@ nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc)
        }
 
        vpc->vp->sprite_fp_input = -1;
-       for(int i = 0; i < 10; ++i)
+       for(int i = 0; i < num_texcoords; ++i)
        {
                if(sem_layout[i] == 0xff)
                {
@@ -946,7 +975,7 @@ nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc)
 DEBUG_GET_ONCE_BOOL_OPTION(nvfx_dump_vp, "NVFX_DUMP_VP", FALSE)
 
 static struct nvfx_vertex_program*
-nvfx_vertprog_translate(struct nvfx_context *nvfx, const struct pipe_shader_state* vps)
+nvfx_vertprog_translate(struct nvfx_context *nvfx, const struct pipe_shader_state* vps, struct tgsi_shader_info* info)
 {
        struct tgsi_parse_context parse;
        struct nvfx_vertex_program* vp = NULL;
@@ -968,6 +997,7 @@ nvfx_vertprog_translate(struct nvfx_context *nvfx, const struct pipe_shader_stat
        vpc->nvfx = nvfx;
        vpc->vp = vp;
        vpc->pipe = *vps;
+       vpc->info = info;
 
        {
                // TODO: use a 64-bit atomic here!
@@ -1086,14 +1116,6 @@ nvfx_vertprog_translate(struct nvfx_context *nvfx, const struct pipe_shader_stat
                        nvfx_vp_emit(vpc, arith(0, VEC, DP4, cdst, mask, htmp, ceqn, none));
                }
        }
-       else
-       {
-               if(vp->nr_insns)
-                       vp->insns[vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
-
-               nvfx_vp_emit(vpc, arith(0, VEC, NOP, none.reg, 0, none, none, none));
-               vp->insns[vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
-       }
 
        if(debug_get_option_nvfx_dump_vp())
        {
@@ -1133,6 +1155,7 @@ nvfx_vertprog_translate_draw_vp(struct nvfx_context *nvfx, struct nvfx_pipe_vert
 {
        struct nvfx_vertex_program* vp = NULL;
        struct pipe_shader_state vps;
+       struct tgsi_shader_info info;
        struct ureg_program *ureg = NULL;
        unsigned num_outputs = MIN2(pvp->info.num_outputs, 16);
 
@@ -1146,7 +1169,8 @@ nvfx_vertprog_translate_draw_vp(struct nvfx_context *nvfx, struct nvfx_pipe_vert
        ureg_END( ureg );
 
        vps.tokens = ureg_get_tokens(ureg, 0);
-       vp = nvfx_vertprog_translate(nvfx, &vps);
+       tgsi_scan_shader(vps.tokens, &info);
+       vp = nvfx_vertprog_translate(nvfx, &vps, &info);
        ureg_free_tokens(vps.tokens);
        ureg_destroy(ureg);
 
@@ -1158,6 +1182,7 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
 {
        struct nvfx_screen *screen = nvfx->screen;
        struct nouveau_channel *chan = screen->base.channel;
+       struct nouveau_grobj *eng3d = screen->eng3d;
        struct nvfx_pipe_vertex_program *pvp = nvfx->vertprog;
        struct nvfx_vertex_program* vp;
        struct pipe_resource *constbuf;
@@ -1169,7 +1194,7 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
                vp = pvp->vp;
 
                if(!vp) {
-                       vp = nvfx_vertprog_translate(nvfx, &pvp->pipe);
+                       vp = nvfx_vertprog_translate(nvfx, &pvp->pipe, &pvp->info);
                        if(!vp)
                                vp = NVFX_VP_FAILED;
                        pvp->vp = vp;
@@ -1317,7 +1342,6 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
                }
                */
 
-               WAIT_RING(chan, 6 * vp->nr_consts);
                for (i = nvfx->use_vp_clipping ? 6 : 0; i < vp->nr_consts; i++) {
                        struct nvfx_vertex_program_data *vpd = &vp->consts[i];
 
@@ -1332,7 +1356,7 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
 
                        //printf("upload into %i + %i: %f %f %f %f\n", vp->data->start, i, vpd->value[0], vpd->value[1], vpd->value[2], vpd->value[3]);
 
-                       OUT_RING(chan, RING_3D(NV30_3D_VP_UPLOAD_CONST_ID, 5));
+                       BEGIN_RING(chan, eng3d, NV30_3D_VP_UPLOAD_CONST_ID, 5);
                        OUT_RING(chan, i + vp->data->start);
                        OUT_RINGp(chan, (uint32_t *)vpd->value, 4);
                }
@@ -1340,11 +1364,10 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
 
        /* Upload vtxprog */
        if (upload_code) {
-               WAIT_RING(chan, 2 + 5 * vp->nr_insns);
-               OUT_RING(chan, RING_3D(NV30_3D_VP_UPLOAD_FROM_ID, 1));
+               BEGIN_RING(chan, eng3d, NV30_3D_VP_UPLOAD_FROM_ID, 1);
                OUT_RING(chan, vp->exec->start);
                for (i = 0; i < vp->nr_insns; i++) {
-                       OUT_RING(chan, RING_3D(NV30_3D_VP_UPLOAD_INST(0), 4));
+                       BEGIN_RING(chan, eng3d, NV30_3D_VP_UPLOAD_INST(0), 4);
                        //printf("%08x %08x %08x %08x\n", vp->insns[i].data[0], vp->insns[i].data[1], vp->insns[i].data[2], vp->insns[i].data[3]);
                        OUT_RINGp(chan, vp->insns[i].data, 4);
                }
@@ -1353,11 +1376,10 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
 
        if(nvfx->dirty & (NVFX_NEW_VERTPROG))
        {
-               WAIT_RING(chan, 6);
-               OUT_RING(chan, RING_3D(NV30_3D_VP_START_FROM_ID, 1));
+               BEGIN_RING(chan, eng3d, NV30_3D_VP_START_FROM_ID, 1);
                OUT_RING(chan, vp->exec->start);
                if(nvfx->is_nv4x) {
-                       OUT_RING(chan, RING_3D(NV40_3D_VP_ATTRIB_EN, 1));
+                       BEGIN_RING(chan, eng3d, NV40_3D_VP_ATTRIB_EN, 1);
                        OUT_RING(chan, vp->ir);
                }
        }
@@ -1385,7 +1407,6 @@ nvfx_vertprog_destroy(struct nvfx_context *nvfx, struct nvfx_vertex_program *vp)
 static void *
 nvfx_vp_state_create(struct pipe_context *pipe, const struct pipe_shader_state *cso)
 {
-        struct nvfx_context *nvfx = nvfx_context(pipe);
         struct nvfx_pipe_vertex_program *pvp;
 
         pvp = CALLOC(1, sizeof(struct nvfx_pipe_vertex_program));