• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE 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/nvc0_context.h"
29 #include "nvc0/nvc0_query_hw.h"
30 
31 #include "nvc0/nvc0_compute.xml.h"
32 
33 static inline void
nvc0_program_update_context_state(struct nvc0_context * nvc0,struct nvc0_program * prog,int stage)34 nvc0_program_update_context_state(struct nvc0_context *nvc0,
35                                   struct nvc0_program *prog, int stage)
36 {
37    if (prog && prog->need_tls) {
38       const uint32_t flags = NV_VRAM_DOMAIN(&nvc0->screen->base) | NOUVEAU_BO_RDWR;
39       if (!nvc0->state.tls_required)
40          BCTX_REFN_bo(nvc0->bufctx_3d, 3D_TLS, flags, nvc0->screen->tls);
41       nvc0->state.tls_required |= 1 << stage;
42    } else {
43       if (nvc0->state.tls_required == (1 << stage))
44          nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TLS);
45       nvc0->state.tls_required &= ~(1 << stage);
46    }
47 }
48 
49 static inline bool
nvc0_program_validate(struct nvc0_context * nvc0,struct nvc0_program * prog)50 nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog)
51 {
52    if (prog->mem)
53       return true;
54 
55    if (!prog->translated) {
56       prog->translated = nvc0_program_translate(
57          prog, nvc0->screen->base.device->chipset, &nvc0->base.debug);
58       if (!prog->translated)
59          return false;
60    }
61 
62    if (likely(prog->code_size))
63       return nvc0_program_upload(nvc0, prog);
64    return true; /* stream output info only */
65 }
66 
67 void
nvc0_vertprog_validate(struct nvc0_context * nvc0)68 nvc0_vertprog_validate(struct nvc0_context *nvc0)
69 {
70    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
71    struct nvc0_program *vp = nvc0->vertprog;
72 
73    if (!nvc0_program_validate(nvc0, vp))
74          return;
75    nvc0_program_update_context_state(nvc0, vp, 0);
76 
77    BEGIN_NVC0(push, NVC0_3D(SP_SELECT(1)), 2);
78    PUSH_DATA (push, 0x11);
79    PUSH_DATA (push, vp->code_base);
80    BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(1)), 1);
81    PUSH_DATA (push, vp->num_gprs);
82 
83    // BEGIN_NVC0(push, NVC0_3D_(0x163c), 1);
84    // PUSH_DATA (push, 0);
85 }
86 
87 void
nvc0_fragprog_validate(struct nvc0_context * nvc0)88 nvc0_fragprog_validate(struct nvc0_context *nvc0)
89 {
90    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
91    struct nvc0_program *fp = nvc0->fragprog;
92    struct pipe_rasterizer_state *rast = &nvc0->rast->pipe;
93 
94    if (fp->fp.force_persample_interp != rast->force_persample_interp) {
95       /* Force the program to be reuploaded, which will trigger interp fixups
96        * to get applied
97        */
98       if (fp->mem)
99          nouveau_heap_free(&fp->mem);
100 
101       fp->fp.force_persample_interp = rast->force_persample_interp;
102    }
103 
104    /* Shade model works well enough when both colors follow it. However if one
105     * (or both) is explicitly set, then we have to go the patching route.
106     */
107    bool has_explicit_color = fp->fp.colors &&
108       (((fp->fp.colors & 1) && !fp->fp.color_interp[0]) ||
109        ((fp->fp.colors & 2) && !fp->fp.color_interp[1]));
110    bool hwflatshade = false;
111    if (has_explicit_color && fp->fp.flatshade != rast->flatshade) {
112       /* Force re-upload */
113       if (fp->mem)
114          nouveau_heap_free(&fp->mem);
115 
116       fp->fp.flatshade = rast->flatshade;
117 
118       /* Always smooth-shade in this mode, the shader will decide on its own
119        * when to flat-shade.
120        */
121    } else if (!has_explicit_color) {
122       hwflatshade = rast->flatshade;
123 
124       /* No need to binary-patch the shader each time, make sure that it's set
125        * up for the default behaviour.
126        */
127       fp->fp.flatshade = 0;
128    }
129 
130    if (hwflatshade != nvc0->state.flatshade) {
131       nvc0->state.flatshade = hwflatshade;
132       BEGIN_NVC0(push, NVC0_3D(SHADE_MODEL), 1);
133       PUSH_DATA (push, hwflatshade ? NVC0_3D_SHADE_MODEL_FLAT :
134                                      NVC0_3D_SHADE_MODEL_SMOOTH);
135    }
136 
137    if (fp->mem && !(nvc0->dirty_3d & NVC0_NEW_3D_FRAGPROG)) {
138       return;
139    }
140 
141    if (!nvc0_program_validate(nvc0, fp))
142          return;
143    nvc0_program_update_context_state(nvc0, fp, 4);
144 
145    if (fp->fp.early_z != nvc0->state.early_z_forced) {
146       nvc0->state.early_z_forced = fp->fp.early_z;
147       IMMED_NVC0(push, NVC0_3D(FORCE_EARLY_FRAGMENT_TESTS), fp->fp.early_z);
148    }
149 
150    BEGIN_NVC0(push, NVC0_3D(SP_SELECT(5)), 2);
151    PUSH_DATA (push, 0x51);
152    PUSH_DATA (push, fp->code_base);
153    BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(5)), 1);
154    PUSH_DATA (push, fp->num_gprs);
155 
156    BEGIN_NVC0(push, SUBC_3D(0x0360), 2);
157    PUSH_DATA (push, 0x20164010);
158    PUSH_DATA (push, 0x20);
159    BEGIN_NVC0(push, NVC0_3D(ZCULL_TEST_MASK), 1);
160    PUSH_DATA (push, fp->flags[0]);
161 }
162 
163 void
nvc0_tctlprog_validate(struct nvc0_context * nvc0)164 nvc0_tctlprog_validate(struct nvc0_context *nvc0)
165 {
166    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
167    struct nvc0_program *tp = nvc0->tctlprog;
168 
169    if (tp && nvc0_program_validate(nvc0, tp)) {
170       if (tp->tp.tess_mode != ~0) {
171          BEGIN_NVC0(push, NVC0_3D(TESS_MODE), 1);
172          PUSH_DATA (push, tp->tp.tess_mode);
173       }
174       BEGIN_NVC0(push, NVC0_3D(SP_SELECT(2)), 2);
175       PUSH_DATA (push, 0x21);
176       PUSH_DATA (push, tp->code_base);
177       BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(2)), 1);
178       PUSH_DATA (push, tp->num_gprs);
179    } else {
180       tp = nvc0->tcp_empty;
181       /* not a whole lot we can do to handle this failure */
182       if (!nvc0_program_validate(nvc0, tp))
183          assert(!"unable to validate empty tcp");
184       BEGIN_NVC0(push, NVC0_3D(SP_SELECT(2)), 2);
185       PUSH_DATA (push, 0x20);
186       PUSH_DATA (push, tp->code_base);
187    }
188    nvc0_program_update_context_state(nvc0, tp, 1);
189 }
190 
191 void
nvc0_tevlprog_validate(struct nvc0_context * nvc0)192 nvc0_tevlprog_validate(struct nvc0_context *nvc0)
193 {
194    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
195    struct nvc0_program *tp = nvc0->tevlprog;
196 
197    if (tp && nvc0_program_validate(nvc0, tp)) {
198       if (tp->tp.tess_mode != ~0) {
199          BEGIN_NVC0(push, NVC0_3D(TESS_MODE), 1);
200          PUSH_DATA (push, tp->tp.tess_mode);
201       }
202       BEGIN_NVC0(push, NVC0_3D(MACRO_TEP_SELECT), 1);
203       PUSH_DATA (push, 0x31);
204       BEGIN_NVC0(push, NVC0_3D(SP_START_ID(3)), 1);
205       PUSH_DATA (push, tp->code_base);
206       BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(3)), 1);
207       PUSH_DATA (push, tp->num_gprs);
208    } else {
209       BEGIN_NVC0(push, NVC0_3D(MACRO_TEP_SELECT), 1);
210       PUSH_DATA (push, 0x30);
211    }
212    nvc0_program_update_context_state(nvc0, tp, 2);
213 }
214 
215 void
nvc0_gmtyprog_validate(struct nvc0_context * nvc0)216 nvc0_gmtyprog_validate(struct nvc0_context *nvc0)
217 {
218    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
219    struct nvc0_program *gp = nvc0->gmtyprog;
220 
221    /* we allow GPs with no code for specifying stream output state only */
222    if (gp && nvc0_program_validate(nvc0, gp) && gp->code_size) {
223       const bool gp_selects_layer = !!(gp->hdr[13] & (1 << 9));
224 
225       BEGIN_NVC0(push, NVC0_3D(MACRO_GP_SELECT), 1);
226       PUSH_DATA (push, 0x41);
227       BEGIN_NVC0(push, NVC0_3D(SP_START_ID(4)), 1);
228       PUSH_DATA (push, gp->code_base);
229       BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(4)), 1);
230       PUSH_DATA (push, gp->num_gprs);
231       BEGIN_NVC0(push, NVC0_3D(LAYER), 1);
232       PUSH_DATA (push, gp_selects_layer ? NVC0_3D_LAYER_USE_GP : 0);
233    } else {
234       IMMED_NVC0(push, NVC0_3D(LAYER), 0);
235       BEGIN_NVC0(push, NVC0_3D(MACRO_GP_SELECT), 1);
236       PUSH_DATA (push, 0x40);
237    }
238    nvc0_program_update_context_state(nvc0, gp, 3);
239 }
240 
241 void
nvc0_compprog_validate(struct nvc0_context * nvc0)242 nvc0_compprog_validate(struct nvc0_context *nvc0)
243 {
244    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
245    struct nvc0_program *cp = nvc0->compprog;
246 
247    if (cp && !nvc0_program_validate(nvc0, cp))
248       return;
249 
250    BEGIN_NVC0(push, NVC0_CP(FLUSH), 1);
251    PUSH_DATA (push, NVC0_COMPUTE_FLUSH_CODE);
252 }
253 
254 void
nvc0_tfb_validate(struct nvc0_context * nvc0)255 nvc0_tfb_validate(struct nvc0_context *nvc0)
256 {
257    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
258    struct nvc0_transform_feedback_state *tfb;
259    unsigned b;
260 
261    if (nvc0->gmtyprog) tfb = nvc0->gmtyprog->tfb;
262    else
263    if (nvc0->tevlprog) tfb = nvc0->tevlprog->tfb;
264    else
265       tfb = nvc0->vertprog->tfb;
266 
267    IMMED_NVC0(push, NVC0_3D(TFB_ENABLE), (tfb && nvc0->num_tfbbufs) ? 1 : 0);
268 
269    if (tfb && tfb != nvc0->state.tfb) {
270       for (b = 0; b < 4; ++b) {
271          if (tfb->varying_count[b]) {
272             unsigned n = (tfb->varying_count[b] + 3) / 4;
273 
274             BEGIN_NVC0(push, NVC0_3D(TFB_STREAM(b)), 3);
275             PUSH_DATA (push, tfb->stream[b]);
276             PUSH_DATA (push, tfb->varying_count[b]);
277             PUSH_DATA (push, tfb->stride[b]);
278             BEGIN_NVC0(push, NVC0_3D(TFB_VARYING_LOCS(b, 0)), n);
279             PUSH_DATAp(push, tfb->varying_index[b], n);
280 
281             if (nvc0->tfbbuf[b])
282                nvc0_so_target(nvc0->tfbbuf[b])->stride = tfb->stride[b];
283          } else {
284             IMMED_NVC0(push, NVC0_3D(TFB_VARYING_COUNT(b)), 0);
285          }
286       }
287    }
288    nvc0->state.tfb = tfb;
289 
290    if (!(nvc0->dirty_3d & NVC0_NEW_3D_TFB_TARGETS))
291       return;
292 
293    for (b = 0; b < nvc0->num_tfbbufs; ++b) {
294       struct nvc0_so_target *targ = nvc0_so_target(nvc0->tfbbuf[b]);
295       struct nv04_resource *buf;
296 
297       if (!targ) {
298          IMMED_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 0);
299          continue;
300       }
301 
302       if (tfb)
303          targ->stride = tfb->stride[b];
304 
305       buf = nv04_resource(targ->pipe.buffer);
306 
307       BCTX_REFN(nvc0->bufctx_3d, 3D_TFB, buf, WR);
308 
309       if (!(nvc0->tfbbuf_dirty & (1 << b)))
310          continue;
311 
312       if (!targ->clean)
313          nvc0_hw_query_fifo_wait(nvc0, nvc0_query(targ->pq));
314       nouveau_pushbuf_space(push, 0, 0, 1);
315       BEGIN_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 5);
316       PUSH_DATA (push, 1);
317       PUSH_DATAh(push, buf->address + targ->pipe.buffer_offset);
318       PUSH_DATA (push, buf->address + targ->pipe.buffer_offset);
319       PUSH_DATA (push, targ->pipe.buffer_size);
320       if (!targ->clean) {
321          nvc0_hw_query_pushbuf_submit(push, nvc0_query(targ->pq), 0x4);
322       } else {
323          PUSH_DATA(push, 0); /* TFB_BUFFER_OFFSET */
324          targ->clean = false;
325       }
326    }
327    for (; b < 4; ++b)
328       IMMED_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 0);
329 }
330