Home | History | Annotate | Download | only in nvc0
      1 /*
      2  * Copyright 2010 Christoph Bumiller
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     20  * SOFTWARE.
     21  */
     22 
     23 #include "pipe/p_context.h"
     24 #include "pipe/p_defines.h"
     25 #include "pipe/p_state.h"
     26 #include "util/u_inlines.h"
     27 
     28 #include "nvc0_context.h"
     29 
     30 static INLINE void
     31 nvc0_program_update_context_state(struct nvc0_context *nvc0,
     32                                   struct nvc0_program *prog, int stage)
     33 {
     34    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
     35 
     36    if (prog && prog->need_tls) {
     37       const uint32_t flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR;
     38       if (!nvc0->state.tls_required)
     39          BCTX_REFN_bo(nvc0->bufctx_3d, TLS, flags, nvc0->screen->tls);
     40       nvc0->state.tls_required |= 1 << stage;
     41    } else {
     42       if (nvc0->state.tls_required == (1 << stage))
     43          nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TLS);
     44       nvc0->state.tls_required &= ~(1 << stage);
     45    }
     46 
     47    if (prog && prog->immd_size) {
     48       BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
     49       /* NOTE: may overlap code of a different shader */
     50       PUSH_DATA (push, align(prog->immd_size, 0x100));
     51       PUSH_DATAh(push, nvc0->screen->text->offset + prog->immd_base);
     52       PUSH_DATA (push, nvc0->screen->text->offset + prog->immd_base);
     53       BEGIN_NVC0(push, NVC0_3D(CB_BIND(stage)), 1);
     54       PUSH_DATA (push, (14 << 4) | 1);
     55 
     56       nvc0->state.c14_bound |= 1 << stage;
     57    } else
     58    if (nvc0->state.c14_bound & (1 << stage)) {
     59       BEGIN_NVC0(push, NVC0_3D(CB_BIND(stage)), 1);
     60       PUSH_DATA (push, (14 << 4) | 0);
     61 
     62       nvc0->state.c14_bound &= ~(1 << stage);
     63    }
     64 }
     65 
     66 static INLINE boolean
     67 nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog)
     68 {
     69    if (prog->mem)
     70       return TRUE;
     71 
     72    if (!prog->translated) {
     73       prog->translated = nvc0_program_translate(
     74          prog, nvc0->screen->base.device->chipset);
     75       if (!prog->translated)
     76          return FALSE;
     77    }
     78 
     79    if (likely(prog->code_size))
     80       return nvc0_program_upload_code(nvc0, prog);
     81    return TRUE; /* stream output info only */
     82 }
     83 
     84 void
     85 nvc0_vertprog_validate(struct nvc0_context *nvc0)
     86 {
     87    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
     88    struct nvc0_program *vp = nvc0->vertprog;
     89 
     90    if (!nvc0_program_validate(nvc0, vp))
     91          return;
     92    nvc0_program_update_context_state(nvc0, vp, 0);
     93 
     94    BEGIN_NVC0(push, NVC0_3D(SP_SELECT(1)), 2);
     95    PUSH_DATA (push, 0x11);
     96    PUSH_DATA (push, vp->code_base);
     97    BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(1)), 1);
     98    PUSH_DATA (push, vp->max_gpr);
     99 
    100    // BEGIN_NVC0(push, NVC0_3D_(0x163c), 1);
    101    // PUSH_DATA (push, 0);
    102 }
    103 
    104 void
    105 nvc0_fragprog_validate(struct nvc0_context *nvc0)
    106 {
    107    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
    108    struct nvc0_program *fp = nvc0->fragprog;
    109 
    110    if (!nvc0_program_validate(nvc0, fp))
    111          return;
    112    nvc0_program_update_context_state(nvc0, fp, 4);
    113 
    114    if (fp->fp.early_z != nvc0->state.early_z_forced) {
    115       nvc0->state.early_z_forced = fp->fp.early_z;
    116       IMMED_NVC0(push, NVC0_3D(FORCE_EARLY_FRAGMENT_TESTS), fp->fp.early_z);
    117    }
    118 
    119    BEGIN_NVC0(push, NVC0_3D(SP_SELECT(5)), 2);
    120    PUSH_DATA (push, 0x51);
    121    PUSH_DATA (push, fp->code_base);
    122    BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(5)), 1);
    123    PUSH_DATA (push, fp->max_gpr);
    124 
    125    BEGIN_NVC0(push, SUBC_3D(0x0360), 2);
    126    PUSH_DATA (push, 0x20164010);
    127    PUSH_DATA (push, 0x20);
    128    BEGIN_NVC0(push, NVC0_3D(ZCULL_TEST_MASK), 1);
    129    PUSH_DATA (push, fp->flags[0]);
    130 }
    131 
    132 void
    133 nvc0_tctlprog_validate(struct nvc0_context *nvc0)
    134 {
    135    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
    136    struct nvc0_program *tp = nvc0->tctlprog;
    137 
    138    if (tp && nvc0_program_validate(nvc0, tp)) {
    139       if (tp->tp.tess_mode != ~0) {
    140          BEGIN_NVC0(push, NVC0_3D(TESS_MODE), 1);
    141          PUSH_DATA (push, tp->tp.tess_mode);
    142       }
    143       BEGIN_NVC0(push, NVC0_3D(SP_SELECT(2)), 2);
    144       PUSH_DATA (push, 0x21);
    145       PUSH_DATA (push, tp->code_base);
    146       BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(2)), 1);
    147       PUSH_DATA (push, tp->max_gpr);
    148 
    149       if (tp->tp.input_patch_size <= 32)
    150          IMMED_NVC0(push, NVC0_3D(PATCH_VERTICES), tp->tp.input_patch_size);
    151    } else {
    152       BEGIN_NVC0(push, NVC0_3D(SP_SELECT(2)), 1);
    153       PUSH_DATA (push, 0x20);
    154    }
    155    nvc0_program_update_context_state(nvc0, tp, 1);
    156 }
    157 
    158 void
    159 nvc0_tevlprog_validate(struct nvc0_context *nvc0)
    160 {
    161    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
    162    struct nvc0_program *tp = nvc0->tevlprog;
    163 
    164    if (tp && nvc0_program_validate(nvc0, tp)) {
    165       if (tp->tp.tess_mode != ~0) {
    166          BEGIN_NVC0(push, NVC0_3D(TESS_MODE), 1);
    167          PUSH_DATA (push, tp->tp.tess_mode);
    168       }
    169       BEGIN_NVC0(push, NVC0_3D(MACRO_TEP_SELECT), 1);
    170       PUSH_DATA (push, 0x31);
    171       BEGIN_NVC0(push, NVC0_3D(SP_START_ID(3)), 1);
    172       PUSH_DATA (push, tp->code_base);
    173       BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(3)), 1);
    174       PUSH_DATA (push, tp->max_gpr);
    175    } else {
    176       BEGIN_NVC0(push, NVC0_3D(MACRO_TEP_SELECT), 1);
    177       PUSH_DATA (push, 0x30);
    178    }
    179    nvc0_program_update_context_state(nvc0, tp, 2);
    180 }
    181 
    182 void
    183 nvc0_gmtyprog_validate(struct nvc0_context *nvc0)
    184 {
    185    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
    186    struct nvc0_program *gp = nvc0->gmtyprog;
    187 
    188    if (gp)
    189       nvc0_program_validate(nvc0, gp);
    190 
    191    /* we allow GPs with no code for specifying stream output state only */
    192    if (gp && gp->code_size) {
    193       const boolean gp_selects_layer = gp->hdr[13] & (1 << 9);
    194 
    195       BEGIN_NVC0(push, NVC0_3D(MACRO_GP_SELECT), 1);
    196       PUSH_DATA (push, 0x41);
    197       BEGIN_NVC0(push, NVC0_3D(SP_START_ID(4)), 1);
    198       PUSH_DATA (push, gp->code_base);
    199       BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(4)), 1);
    200       PUSH_DATA (push, gp->max_gpr);
    201       BEGIN_NVC0(push, NVC0_3D(LAYER), 1);
    202       PUSH_DATA (push, gp_selects_layer ? NVC0_3D_LAYER_USE_GP : 0);
    203    } else {
    204       IMMED_NVC0(push, NVC0_3D(LAYER), 0);
    205       BEGIN_NVC0(push, NVC0_3D(MACRO_GP_SELECT), 1);
    206       PUSH_DATA (push, 0x40);
    207    }
    208    nvc0_program_update_context_state(nvc0, gp, 3);
    209 }
    210 
    211 void
    212 nvc0_tfb_validate(struct nvc0_context *nvc0)
    213 {
    214    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
    215    struct nvc0_transform_feedback_state *tfb;
    216    unsigned b;
    217 
    218    if (nvc0->gmtyprog) tfb = nvc0->gmtyprog->tfb;
    219    else
    220    if (nvc0->tevlprog) tfb = nvc0->tevlprog->tfb;
    221    else
    222       tfb = nvc0->vertprog->tfb;
    223 
    224    IMMED_NVC0(push, NVC0_3D(TFB_ENABLE), (tfb && nvc0->num_tfbbufs) ? 1 : 0);
    225 
    226    if (tfb && tfb != nvc0->state.tfb) {
    227       for (b = 0; b < 4; ++b) {
    228          if (tfb->varying_count[b]) {
    229             unsigned n = (tfb->varying_count[b] + 3) / 4;
    230 
    231             BEGIN_NVC0(push, NVC0_3D(TFB_STREAM(b)), 3);
    232             PUSH_DATA (push, 0);
    233             PUSH_DATA (push, tfb->varying_count[b]);
    234             PUSH_DATA (push, tfb->stride[b]);
    235             BEGIN_NVC0(push, NVC0_3D(TFB_VARYING_LOCS(b, 0)), n);
    236             PUSH_DATAp(push, tfb->varying_index[b], n);
    237 
    238             if (nvc0->tfbbuf[b])
    239                nvc0_so_target(nvc0->tfbbuf[b])->stride = tfb->stride[b];
    240          } else {
    241             IMMED_NVC0(push, NVC0_3D(TFB_VARYING_COUNT(b)), 0);
    242          }
    243       }
    244    }
    245    nvc0->state.tfb = tfb;
    246 
    247    if (!(nvc0->dirty & NVC0_NEW_TFB_TARGETS))
    248       return;
    249    nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TFB);
    250 
    251    for (b = 0; b < nvc0->num_tfbbufs; ++b) {
    252       struct nvc0_so_target *targ = nvc0_so_target(nvc0->tfbbuf[b]);
    253       struct nv04_resource *buf = nv04_resource(targ->pipe.buffer);
    254 
    255       if (tfb)
    256          targ->stride = tfb->stride[b];
    257 
    258       if (!(nvc0->tfbbuf_dirty & (1 << b)))
    259          continue;
    260 
    261       if (!targ->clean)
    262          nvc0_query_fifo_wait(push, targ->pq);
    263       BEGIN_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 5);
    264       PUSH_DATA (push, 1);
    265       PUSH_DATAh(push, buf->address + targ->pipe.buffer_offset);
    266       PUSH_DATA (push, buf->address + targ->pipe.buffer_offset);
    267       PUSH_DATA (push, targ->pipe.buffer_size);
    268       if (!targ->clean) {
    269          nvc0_query_pushbuf_submit(push, targ->pq, 0x4);
    270       } else {
    271          PUSH_DATA(push, 0); /* TFB_BUFFER_OFFSET */
    272          targ->clean = FALSE;
    273       }
    274       BCTX_REFN(nvc0->bufctx_3d, TFB, buf, WR);
    275    }
    276    for (; b < 4; ++b)
    277       IMMED_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 0);
    278 }
    279