2 * Copyright 2010 Christoph Bumiller
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
23 #include "pipe/p_context.h"
24 #include "pipe/p_defines.h"
25 #include "pipe/p_state.h"
26 #include "util/u_inlines.h"
28 #include "nvc0/nvc0_context.h"
29 #include "nvc0/nvc0_query_hw.h"
31 #include "nvc0/nvc0_compute.xml.h"
34 nvc0_program_update_context_state(struct nvc0_context
*nvc0
,
35 struct nvc0_program
*prog
, int stage
)
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
;
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
);
50 nvc0_program_validate(struct nvc0_context
*nvc0
, struct nvc0_program
*prog
)
55 if (!prog
->translated
) {
56 prog
->translated
= nvc0_program_translate(
57 prog
, nvc0
->screen
->base
.device
->chipset
, &nvc0
->base
.debug
);
58 if (!prog
->translated
)
62 if (likely(prog
->code_size
))
63 return nvc0_program_upload(nvc0
, prog
);
64 return true; /* stream output info only */
68 nvc0_vertprog_validate(struct nvc0_context
*nvc0
)
70 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
71 struct nvc0_program
*vp
= nvc0
->vertprog
;
73 if (!nvc0_program_validate(nvc0
, vp
))
75 nvc0_program_update_context_state(nvc0
, vp
, 0);
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
);
83 // BEGIN_NVC0(push, NVC0_3D_(0x163c), 1);
84 // PUSH_DATA (push, 0);
88 nvc0_fragprog_validate(struct nvc0_context
*nvc0
)
90 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
91 struct nvc0_program
*fp
= nvc0
->fragprog
;
92 struct pipe_rasterizer_state
*rast
= &nvc0
->rast
->pipe
;
94 if (fp
->fp
.force_persample_interp
!= rast
->force_persample_interp
) {
95 /* Force the program to be reuploaded, which will trigger interp fixups
99 nouveau_heap_free(&fp
->mem
);
101 fp
->fp
.force_persample_interp
= rast
->force_persample_interp
;
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.
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 */
114 nouveau_heap_free(&fp
->mem
);
116 fp
->fp
.flatshade
= rast
->flatshade
;
118 /* Always smooth-shade in this mode, the shader will decide on its own
119 * when to flat-shade.
121 } else if (!has_explicit_color
) {
122 hwflatshade
= rast
->flatshade
;
124 /* No need to binary-patch the shader each time, make sure that it's set
125 * up for the default behaviour.
127 fp
->fp
.flatshade
= 0;
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
);
137 if (fp
->mem
&& !(nvc0
->dirty_3d
& NVC0_NEW_3D_FRAGPROG
)) {
141 if (!nvc0_program_validate(nvc0
, fp
))
143 nvc0_program_update_context_state(nvc0
, fp
, 4);
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
);
149 if (fp
->fp
.post_depth_coverage
!= nvc0
->state
.post_depth_coverage
) {
150 nvc0
->state
.post_depth_coverage
= fp
->fp
.post_depth_coverage
;
151 IMMED_NVC0(push
, NVC0_3D(POST_DEPTH_COVERAGE
),
152 fp
->fp
.post_depth_coverage
);
155 BEGIN_NVC0(push
, NVC0_3D(SP_SELECT(5)), 2);
156 PUSH_DATA (push
, 0x51);
157 PUSH_DATA (push
, fp
->code_base
);
158 BEGIN_NVC0(push
, NVC0_3D(SP_GPR_ALLOC(5)), 1);
159 PUSH_DATA (push
, fp
->num_gprs
);
161 BEGIN_NVC0(push
, SUBC_3D(0x0360), 2);
162 PUSH_DATA (push
, 0x20164010);
163 PUSH_DATA (push
, 0x20);
164 BEGIN_NVC0(push
, NVC0_3D(ZCULL_TEST_MASK
), 1);
165 PUSH_DATA (push
, fp
->flags
[0]);
169 nvc0_tctlprog_validate(struct nvc0_context
*nvc0
)
171 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
172 struct nvc0_program
*tp
= nvc0
->tctlprog
;
174 if (tp
&& nvc0_program_validate(nvc0
, tp
)) {
175 if (tp
->tp
.tess_mode
!= ~0) {
176 BEGIN_NVC0(push
, NVC0_3D(TESS_MODE
), 1);
177 PUSH_DATA (push
, tp
->tp
.tess_mode
);
179 BEGIN_NVC0(push
, NVC0_3D(SP_SELECT(2)), 2);
180 PUSH_DATA (push
, 0x21);
181 PUSH_DATA (push
, tp
->code_base
);
182 BEGIN_NVC0(push
, NVC0_3D(SP_GPR_ALLOC(2)), 1);
183 PUSH_DATA (push
, tp
->num_gprs
);
185 tp
= nvc0
->tcp_empty
;
186 /* not a whole lot we can do to handle this failure */
187 if (!nvc0_program_validate(nvc0
, tp
))
188 assert(!"unable to validate empty tcp");
189 BEGIN_NVC0(push
, NVC0_3D(SP_SELECT(2)), 2);
190 PUSH_DATA (push
, 0x20);
191 PUSH_DATA (push
, tp
->code_base
);
193 nvc0_program_update_context_state(nvc0
, tp
, 1);
197 nvc0_tevlprog_validate(struct nvc0_context
*nvc0
)
199 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
200 struct nvc0_program
*tp
= nvc0
->tevlprog
;
202 if (tp
&& nvc0_program_validate(nvc0
, tp
)) {
203 if (tp
->tp
.tess_mode
!= ~0) {
204 BEGIN_NVC0(push
, NVC0_3D(TESS_MODE
), 1);
205 PUSH_DATA (push
, tp
->tp
.tess_mode
);
207 BEGIN_NVC0(push
, NVC0_3D(MACRO_TEP_SELECT
), 1);
208 PUSH_DATA (push
, 0x31);
209 BEGIN_NVC0(push
, NVC0_3D(SP_START_ID(3)), 1);
210 PUSH_DATA (push
, tp
->code_base
);
211 BEGIN_NVC0(push
, NVC0_3D(SP_GPR_ALLOC(3)), 1);
212 PUSH_DATA (push
, tp
->num_gprs
);
214 BEGIN_NVC0(push
, NVC0_3D(MACRO_TEP_SELECT
), 1);
215 PUSH_DATA (push
, 0x30);
217 nvc0_program_update_context_state(nvc0
, tp
, 2);
221 nvc0_gmtyprog_validate(struct nvc0_context
*nvc0
)
223 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
224 struct nvc0_program
*gp
= nvc0
->gmtyprog
;
226 /* we allow GPs with no code for specifying stream output state only */
227 if (gp
&& nvc0_program_validate(nvc0
, gp
) && gp
->code_size
) {
228 BEGIN_NVC0(push
, NVC0_3D(MACRO_GP_SELECT
), 1);
229 PUSH_DATA (push
, 0x41);
230 BEGIN_NVC0(push
, NVC0_3D(SP_START_ID(4)), 1);
231 PUSH_DATA (push
, gp
->code_base
);
232 BEGIN_NVC0(push
, NVC0_3D(SP_GPR_ALLOC(4)), 1);
233 PUSH_DATA (push
, gp
->num_gprs
);
235 BEGIN_NVC0(push
, NVC0_3D(MACRO_GP_SELECT
), 1);
236 PUSH_DATA (push
, 0x40);
238 nvc0_program_update_context_state(nvc0
, gp
, 3);
242 nvc0_compprog_validate(struct nvc0_context
*nvc0
)
244 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
245 struct nvc0_program
*cp
= nvc0
->compprog
;
247 if (cp
&& !nvc0_program_validate(nvc0
, cp
))
250 BEGIN_NVC0(push
, NVC0_CP(FLUSH
), 1);
251 PUSH_DATA (push
, NVC0_COMPUTE_FLUSH_CODE
);
255 nvc0_layer_validate(struct nvc0_context
*nvc0
)
257 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
258 struct nvc0_program
*last
;
259 bool prog_selects_layer
= false;
262 last
= nvc0
->gmtyprog
;
263 else if (nvc0
->tevlprog
)
264 last
= nvc0
->tevlprog
;
266 last
= nvc0
->vertprog
;
269 prog_selects_layer
= !!(last
->hdr
[13] & (1 << 9));
271 BEGIN_NVC0(push
, NVC0_3D(LAYER
), 1);
272 PUSH_DATA (push
, prog_selects_layer
? NVC0_3D_LAYER_USE_GP
: 0);
276 nvc0_tfb_validate(struct nvc0_context
*nvc0
)
278 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
279 struct nvc0_transform_feedback_state
*tfb
;
282 if (nvc0
->gmtyprog
) tfb
= nvc0
->gmtyprog
->tfb
;
284 if (nvc0
->tevlprog
) tfb
= nvc0
->tevlprog
->tfb
;
286 tfb
= nvc0
->vertprog
->tfb
;
288 IMMED_NVC0(push
, NVC0_3D(TFB_ENABLE
), (tfb
&& nvc0
->num_tfbbufs
) ? 1 : 0);
290 if (tfb
&& tfb
!= nvc0
->state
.tfb
) {
291 for (b
= 0; b
< 4; ++b
) {
292 if (tfb
->varying_count
[b
]) {
293 unsigned n
= (tfb
->varying_count
[b
] + 3) / 4;
295 BEGIN_NVC0(push
, NVC0_3D(TFB_STREAM(b
)), 3);
296 PUSH_DATA (push
, tfb
->stream
[b
]);
297 PUSH_DATA (push
, tfb
->varying_count
[b
]);
298 PUSH_DATA (push
, tfb
->stride
[b
]);
299 BEGIN_NVC0(push
, NVC0_3D(TFB_VARYING_LOCS(b
, 0)), n
);
300 PUSH_DATAp(push
, tfb
->varying_index
[b
], n
);
303 nvc0_so_target(nvc0
->tfbbuf
[b
])->stride
= tfb
->stride
[b
];
305 IMMED_NVC0(push
, NVC0_3D(TFB_VARYING_COUNT(b
)), 0);
309 nvc0
->state
.tfb
= tfb
;
311 if (!(nvc0
->dirty_3d
& NVC0_NEW_3D_TFB_TARGETS
))
314 for (b
= 0; b
< nvc0
->num_tfbbufs
; ++b
) {
315 struct nvc0_so_target
*targ
= nvc0_so_target(nvc0
->tfbbuf
[b
]);
316 struct nv04_resource
*buf
;
319 IMMED_NVC0(push
, NVC0_3D(TFB_BUFFER_ENABLE(b
)), 0);
324 targ
->stride
= tfb
->stride
[b
];
326 buf
= nv04_resource(targ
->pipe
.buffer
);
328 BCTX_REFN(nvc0
->bufctx_3d
, 3D_TFB
, buf
, WR
);
330 if (!(nvc0
->tfbbuf_dirty
& (1 << b
)))
334 nvc0_hw_query_fifo_wait(nvc0
, nvc0_query(targ
->pq
));
335 nouveau_pushbuf_space(push
, 0, 0, 1);
336 BEGIN_NVC0(push
, NVC0_3D(TFB_BUFFER_ENABLE(b
)), 5);
338 PUSH_DATAh(push
, buf
->address
+ targ
->pipe
.buffer_offset
);
339 PUSH_DATA (push
, buf
->address
+ targ
->pipe
.buffer_offset
);
340 PUSH_DATA (push
, targ
->pipe
.buffer_size
);
342 nvc0_hw_query_pushbuf_submit(push
, nvc0_query(targ
->pq
), 0x4);
344 PUSH_DATA(push
, 0); /* TFB_BUFFER_OFFSET */
349 IMMED_NVC0(push
, NVC0_3D(TFB_BUFFER_ENABLE(b
)), 0);