2 #include "util/u_format.h"
3 #include "util/u_framebuffer.h"
4 #include "util/u_math.h"
5 #include "util/u_viewport.h"
7 #include "nvc0/nvc0_context.h"
11 nvc0_validate_zcull(struct nvc0_context
*nvc0
)
13 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
14 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
15 struct nv50_surface
*sf
= nv50_surface(fb
->zsbuf
);
16 struct nv50_miptree
*mt
= nv50_miptree(sf
->base
.texture
);
17 struct nouveau_bo
*bo
= mt
->base
.bo
;
19 uint32_t offset
= align(mt
->total_size
, 1 << 17);
20 unsigned width
, height
;
22 assert(mt
->base
.base
.depth0
== 1 && mt
->base
.base
.array_size
< 2);
24 size
= mt
->total_size
* 2;
26 height
= align(fb
->height
, 32);
27 width
= fb
->width
% 224;
29 width
= fb
->width
+ (224 - width
);
33 BEGIN_NVC0(push
, NVC0_3D(ZCULL_REGION
), 1);
35 BEGIN_NVC0(push
, NVC0_3D(ZCULL_ADDRESS_HIGH
), 2);
36 PUSH_DATAh(push
, bo
->offset
+ offset
);
37 PUSH_DATA (push
, bo
->offset
+ offset
);
39 BEGIN_NVC0(push
, NVC0_3D(ZCULL_LIMIT_HIGH
), 2);
40 PUSH_DATAh(push
, bo
->offset
+ offset
);
41 PUSH_DATA (push
, bo
->offset
+ offset
);
42 BEGIN_NVC0(push
, SUBC_3D(0x07e0), 2);
43 PUSH_DATA (push
, size
);
44 PUSH_DATA (push
, size
>> 16);
45 BEGIN_NVC0(push
, SUBC_3D(0x15c8), 1); /* bits 0x3 */
47 BEGIN_NVC0(push
, NVC0_3D(ZCULL_WIDTH
), 4);
48 PUSH_DATA (push
, width
);
49 PUSH_DATA (push
, height
);
52 BEGIN_NVC0(push
, NVC0_3D(ZCULL_WINDOW_OFFSET_X
), 2);
55 BEGIN_NVC0(push
, NVC0_3D(ZCULL_INVALIDATE
), 1);
61 nvc0_fb_set_null_rt(struct nouveau_pushbuf
*push
, unsigned i
, unsigned layers
)
63 BEGIN_NVC0(push
, NVC0_3D(RT_ADDRESS_HIGH(i
)), 9);
66 PUSH_DATA (push
, 64); // width
67 PUSH_DATA (push
, 0); // height
68 PUSH_DATA (push
, 0); // format
69 PUSH_DATA (push
, 0); // tile mode
70 PUSH_DATA (push
, layers
); // layers
71 PUSH_DATA (push
, 0); // layer stride
72 PUSH_DATA (push
, 0); // base layer
76 nvc0_validate_fb(struct nvc0_context
*nvc0
)
78 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
79 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
80 struct nvc0_screen
*screen
= nvc0
->screen
;
82 unsigned ms_mode
= NVC0_3D_MULTISAMPLE_MODE_MS1
;
83 unsigned nr_cbufs
= fb
->nr_cbufs
;
84 bool serialize
= false;
86 nouveau_bufctx_reset(nvc0
->bufctx_3d
, NVC0_BIND_3D_FB
);
88 BEGIN_NVC0(push
, NVC0_3D(SCREEN_SCISSOR_HORIZ
), 2);
89 PUSH_DATA (push
, fb
->width
<< 16);
90 PUSH_DATA (push
, fb
->height
<< 16);
92 for (i
= 0; i
< fb
->nr_cbufs
; ++i
) {
93 struct nv50_surface
*sf
;
94 struct nv04_resource
*res
;
95 struct nouveau_bo
*bo
;
98 nvc0_fb_set_null_rt(push
, i
, 0);
102 sf
= nv50_surface(fb
->cbufs
[i
]);
103 res
= nv04_resource(sf
->base
.texture
);
106 BEGIN_NVC0(push
, NVC0_3D(RT_ADDRESS_HIGH(i
)), 9);
107 PUSH_DATAh(push
, res
->address
+ sf
->offset
);
108 PUSH_DATA (push
, res
->address
+ sf
->offset
);
109 if (likely(nouveau_bo_memtype(bo
))) {
110 struct nv50_miptree
*mt
= nv50_miptree(sf
->base
.texture
);
112 assert(sf
->base
.texture
->target
!= PIPE_BUFFER
);
114 PUSH_DATA(push
, sf
->width
);
115 PUSH_DATA(push
, sf
->height
);
116 PUSH_DATA(push
, nvc0_format_table
[sf
->base
.format
].rt
);
117 PUSH_DATA(push
, (mt
->layout_3d
<< 16) |
118 mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
119 PUSH_DATA(push
, sf
->base
.u
.tex
.first_layer
+ sf
->depth
);
120 PUSH_DATA(push
, mt
->layer_stride
>> 2);
121 PUSH_DATA(push
, sf
->base
.u
.tex
.first_layer
);
123 ms_mode
= mt
->ms_mode
;
125 if (res
->base
.target
== PIPE_BUFFER
) {
126 PUSH_DATA(push
, 262144);
129 PUSH_DATA(push
, nv50_miptree(sf
->base
.texture
)->level
[0].pitch
);
130 PUSH_DATA(push
, sf
->height
);
132 PUSH_DATA(push
, nvc0_format_table
[sf
->base
.format
].rt
);
133 PUSH_DATA(push
, 1 << 12);
138 nvc0_resource_fence(res
, NOUVEAU_BO_WR
);
143 if (res
->status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
145 res
->status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
146 res
->status
&= ~NOUVEAU_BUFFER_STATUS_GPU_READING
;
148 /* only register for writing, otherwise we'd always serialize here */
149 BCTX_REFN(nvc0
->bufctx_3d
, 3D_FB
, res
, WR
);
153 struct nv50_miptree
*mt
= nv50_miptree(fb
->zsbuf
->texture
);
154 struct nv50_surface
*sf
= nv50_surface(fb
->zsbuf
);
155 int unk
= mt
->base
.base
.target
== PIPE_TEXTURE_2D
;
157 BEGIN_NVC0(push
, NVC0_3D(ZETA_ADDRESS_HIGH
), 5);
158 PUSH_DATAh(push
, mt
->base
.address
+ sf
->offset
);
159 PUSH_DATA (push
, mt
->base
.address
+ sf
->offset
);
160 PUSH_DATA (push
, nvc0_format_table
[fb
->zsbuf
->format
].rt
);
161 PUSH_DATA (push
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
162 PUSH_DATA (push
, mt
->layer_stride
>> 2);
163 BEGIN_NVC0(push
, NVC0_3D(ZETA_ENABLE
), 1);
165 BEGIN_NVC0(push
, NVC0_3D(ZETA_HORIZ
), 3);
166 PUSH_DATA (push
, sf
->width
);
167 PUSH_DATA (push
, sf
->height
);
168 PUSH_DATA (push
, (unk
<< 16) |
169 (sf
->base
.u
.tex
.first_layer
+ sf
->depth
));
170 BEGIN_NVC0(push
, NVC0_3D(ZETA_BASE_LAYER
), 1);
171 PUSH_DATA (push
, sf
->base
.u
.tex
.first_layer
);
173 ms_mode
= mt
->ms_mode
;
175 if (mt
->base
.status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
177 mt
->base
.status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
178 mt
->base
.status
&= ~NOUVEAU_BUFFER_STATUS_GPU_READING
;
180 BCTX_REFN(nvc0
->bufctx_3d
, 3D_FB
, &mt
->base
, WR
);
182 BEGIN_NVC0(push
, NVC0_3D(ZETA_ENABLE
), 1);
186 if (nr_cbufs
== 0 && !fb
->zsbuf
) {
187 assert(util_is_power_of_two(fb
->samples
));
188 assert(fb
->samples
<= 8);
190 nvc0_fb_set_null_rt(push
, 0, fb
->layers
);
193 ms_mode
= ffs(fb
->samples
) - 1;
197 BEGIN_NVC0(push
, NVC0_3D(RT_CONTROL
), 1);
198 PUSH_DATA (push
, (076543210 << 4) | nr_cbufs
);
199 IMMED_NVC0(push
, NVC0_3D(MULTISAMPLE_MODE
), ms_mode
);
202 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
203 PUSH_DATA (push
, NVC0_CB_AUX_SIZE
);
204 PUSH_DATAh(push
, screen
->uniform_bo
->offset
+ NVC0_CB_AUX_INFO(4));
205 PUSH_DATA (push
, screen
->uniform_bo
->offset
+ NVC0_CB_AUX_INFO(4));
206 BEGIN_1IC0(push
, NVC0_3D(CB_POS
), 1 + 2 * ms
);
207 PUSH_DATA (push
, NVC0_CB_AUX_SAMPLE_INFO
);
208 for (i
= 0; i
< ms
; i
++) {
210 nvc0
->base
.pipe
.get_sample_position(&nvc0
->base
.pipe
, ms
, i
, xy
);
211 PUSH_DATAf(push
, xy
[0]);
212 PUSH_DATAf(push
, xy
[1]);
215 if (screen
->base
.class_3d
>= GM200_3D_CLASS
) {
216 const uint8_t (*ptr
)[2] = nvc0_get_sample_locations(ms
);
217 uint32_t val
[4] = {};
219 for (i
= 0; i
< 16; i
++) {
220 val
[i
/ 4] |= ptr
[i
% ms
][0] << (((i
% 4) * 8) + 0);
221 val
[i
/ 4] |= ptr
[i
% ms
][1] << (((i
% 4) * 8) + 4);
224 BEGIN_NVC0(push
, SUBC_3D(0x11e0), 4);
225 PUSH_DATAp(push
, val
, 4);
229 IMMED_NVC0(push
, NVC0_3D(SERIALIZE
), 0);
231 NOUVEAU_DRV_STAT(&nvc0
->screen
->base
, gpu_serialize_count
, serialize
);
235 nvc0_validate_blend_colour(struct nvc0_context
*nvc0
)
237 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
239 BEGIN_NVC0(push
, NVC0_3D(BLEND_COLOR(0)), 4);
240 PUSH_DATAf(push
, nvc0
->blend_colour
.color
[0]);
241 PUSH_DATAf(push
, nvc0
->blend_colour
.color
[1]);
242 PUSH_DATAf(push
, nvc0
->blend_colour
.color
[2]);
243 PUSH_DATAf(push
, nvc0
->blend_colour
.color
[3]);
247 nvc0_validate_stencil_ref(struct nvc0_context
*nvc0
)
249 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
250 const ubyte
*ref
= &nvc0
->stencil_ref
.ref_value
[0];
252 IMMED_NVC0(push
, NVC0_3D(STENCIL_FRONT_FUNC_REF
), ref
[0]);
253 IMMED_NVC0(push
, NVC0_3D(STENCIL_BACK_FUNC_REF
), ref
[1]);
257 nvc0_validate_stipple(struct nvc0_context
*nvc0
)
259 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
262 BEGIN_NVC0(push
, NVC0_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
263 for (i
= 0; i
< 32; ++i
)
264 PUSH_DATA(push
, util_bswap32(nvc0
->stipple
.stipple
[i
]));
268 nvc0_validate_scissor(struct nvc0_context
*nvc0
)
271 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
273 if (!(nvc0
->dirty_3d
& NVC0_NEW_3D_SCISSOR
) &&
274 nvc0
->rast
->pipe
.scissor
== nvc0
->state
.scissor
)
277 if (nvc0
->state
.scissor
!= nvc0
->rast
->pipe
.scissor
)
278 nvc0
->scissors_dirty
= (1 << NVC0_MAX_VIEWPORTS
) - 1;
280 nvc0
->state
.scissor
= nvc0
->rast
->pipe
.scissor
;
282 for (i
= 0; i
< NVC0_MAX_VIEWPORTS
; i
++) {
283 struct pipe_scissor_state
*s
= &nvc0
->scissors
[i
];
284 if (!(nvc0
->scissors_dirty
& (1 << i
)))
287 BEGIN_NVC0(push
, NVC0_3D(SCISSOR_HORIZ(i
)), 2);
288 if (nvc0
->rast
->pipe
.scissor
) {
289 PUSH_DATA(push
, (s
->maxx
<< 16) | s
->minx
);
290 PUSH_DATA(push
, (s
->maxy
<< 16) | s
->miny
);
292 PUSH_DATA(push
, (0xffff << 16) | 0);
293 PUSH_DATA(push
, (0xffff << 16) | 0);
296 nvc0
->scissors_dirty
= 0;
300 nvc0_validate_viewport(struct nvc0_context
*nvc0
)
302 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
306 for (i
= 0; i
< NVC0_MAX_VIEWPORTS
; i
++) {
307 struct pipe_viewport_state
*vp
= &nvc0
->viewports
[i
];
309 if (!(nvc0
->viewports_dirty
& (1 << i
)))
312 BEGIN_NVC0(push
, NVC0_3D(VIEWPORT_TRANSLATE_X(i
)), 3);
313 PUSH_DATAf(push
, vp
->translate
[0]);
314 PUSH_DATAf(push
, vp
->translate
[1]);
315 PUSH_DATAf(push
, vp
->translate
[2]);
317 BEGIN_NVC0(push
, NVC0_3D(VIEWPORT_SCALE_X(i
)), 3);
318 PUSH_DATAf(push
, vp
->scale
[0]);
319 PUSH_DATAf(push
, vp
->scale
[1]);
320 PUSH_DATAf(push
, vp
->scale
[2]);
322 /* now set the viewport rectangle to viewport dimensions for clipping */
324 x
= util_iround(MAX2(0.0f
, vp
->translate
[0] - fabsf(vp
->scale
[0])));
325 y
= util_iround(MAX2(0.0f
, vp
->translate
[1] - fabsf(vp
->scale
[1])));
326 w
= util_iround(vp
->translate
[0] + fabsf(vp
->scale
[0])) - x
;
327 h
= util_iround(vp
->translate
[1] + fabsf(vp
->scale
[1])) - y
;
329 BEGIN_NVC0(push
, NVC0_3D(VIEWPORT_HORIZ(i
)), 2);
330 PUSH_DATA (push
, (w
<< 16) | x
);
331 PUSH_DATA (push
, (h
<< 16) | y
);
333 /* If the halfz setting ever changes, the viewports will also get
334 * updated. The rast will get updated before the validate function has a
335 * chance to hit, so we can just use it directly without an atom
338 util_viewport_zmin_zmax(vp
, nvc0
->rast
->pipe
.clip_halfz
, &zmin
, &zmax
);
340 BEGIN_NVC0(push
, NVC0_3D(DEPTH_RANGE_NEAR(i
)), 2);
341 PUSH_DATAf(push
, zmin
);
342 PUSH_DATAf(push
, zmax
);
344 nvc0
->viewports_dirty
= 0;
348 nvc0_validate_window_rects(struct nvc0_context
*nvc0
)
350 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
351 bool enable
= nvc0
->window_rect
.rects
> 0 || nvc0
->window_rect
.inclusive
;
354 IMMED_NVC0(push
, NVC0_3D(CLIP_RECTS_EN
), enable
);
358 IMMED_NVC0(push
, NVC0_3D(CLIP_RECTS_MODE
), !nvc0
->window_rect
.inclusive
);
359 BEGIN_NVC0(push
, NVC0_3D(CLIP_RECT_HORIZ(0)), NVC0_MAX_WINDOW_RECTANGLES
* 2);
360 for (i
= 0; i
< nvc0
->window_rect
.rects
; i
++) {
361 struct pipe_scissor_state
*s
= &nvc0
->window_rect
.rect
[i
];
362 PUSH_DATA(push
, (s
->maxx
<< 16) | s
->minx
);
363 PUSH_DATA(push
, (s
->maxy
<< 16) | s
->miny
);
365 for (; i
< NVC0_MAX_WINDOW_RECTANGLES
; i
++) {
372 nvc0_upload_uclip_planes(struct nvc0_context
*nvc0
, unsigned s
)
374 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
375 struct nvc0_screen
*screen
= nvc0
->screen
;
377 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
378 PUSH_DATA (push
, NVC0_CB_AUX_SIZE
);
379 PUSH_DATAh(push
, screen
->uniform_bo
->offset
+ NVC0_CB_AUX_INFO(s
));
380 PUSH_DATA (push
, screen
->uniform_bo
->offset
+ NVC0_CB_AUX_INFO(s
));
381 BEGIN_1IC0(push
, NVC0_3D(CB_POS
), PIPE_MAX_CLIP_PLANES
* 4 + 1);
382 PUSH_DATA (push
, NVC0_CB_AUX_UCP_INFO
);
383 PUSH_DATAp(push
, &nvc0
->clip
.ucp
[0][0], PIPE_MAX_CLIP_PLANES
* 4);
387 nvc0_check_program_ucps(struct nvc0_context
*nvc0
,
388 struct nvc0_program
*vp
, uint8_t mask
)
390 const unsigned n
= util_logbase2(mask
) + 1;
392 if (vp
->vp
.num_ucps
>= n
)
394 nvc0_program_destroy(nvc0
, vp
);
397 if (likely(vp
== nvc0
->vertprog
))
398 nvc0_vertprog_validate(nvc0
);
400 if (likely(vp
== nvc0
->gmtyprog
))
401 nvc0_gmtyprog_validate(nvc0
);
403 nvc0_tevlprog_validate(nvc0
);
407 nvc0_validate_clip(struct nvc0_context
*nvc0
)
409 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
410 struct nvc0_program
*vp
;
412 uint8_t clip_enable
= nvc0
->rast
->pipe
.clip_plane_enable
;
414 if (nvc0
->gmtyprog
) {
418 if (nvc0
->tevlprog
) {
426 if (clip_enable
&& vp
->vp
.num_ucps
< PIPE_MAX_CLIP_PLANES
)
427 nvc0_check_program_ucps(nvc0
, vp
, clip_enable
);
429 if (nvc0
->dirty_3d
& (NVC0_NEW_3D_CLIP
| (NVC0_NEW_3D_VERTPROG
<< stage
)))
430 if (vp
->vp
.num_ucps
> 0 && vp
->vp
.num_ucps
<= PIPE_MAX_CLIP_PLANES
)
431 nvc0_upload_uclip_planes(nvc0
, stage
);
433 clip_enable
&= vp
->vp
.clip_enable
;
434 clip_enable
|= vp
->vp
.cull_enable
;
436 if (nvc0
->state
.clip_enable
!= clip_enable
) {
437 nvc0
->state
.clip_enable
= clip_enable
;
438 IMMED_NVC0(push
, NVC0_3D(CLIP_DISTANCE_ENABLE
), clip_enable
);
440 if (nvc0
->state
.clip_mode
!= vp
->vp
.clip_mode
) {
441 nvc0
->state
.clip_mode
= vp
->vp
.clip_mode
;
442 BEGIN_NVC0(push
, NVC0_3D(CLIP_DISTANCE_MODE
), 1);
443 PUSH_DATA (push
, vp
->vp
.clip_mode
);
448 nvc0_validate_blend(struct nvc0_context
*nvc0
)
450 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
452 PUSH_SPACE(push
, nvc0
->blend
->size
);
453 PUSH_DATAp(push
, nvc0
->blend
->state
, nvc0
->blend
->size
);
457 nvc0_validate_zsa(struct nvc0_context
*nvc0
)
459 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
461 PUSH_SPACE(push
, nvc0
->zsa
->size
);
462 PUSH_DATAp(push
, nvc0
->zsa
->state
, nvc0
->zsa
->size
);
466 nvc0_validate_rasterizer(struct nvc0_context
*nvc0
)
468 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
470 PUSH_SPACE(push
, nvc0
->rast
->size
);
471 PUSH_DATAp(push
, nvc0
->rast
->state
, nvc0
->rast
->size
);
475 nvc0_constbufs_validate(struct nvc0_context
*nvc0
)
477 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
480 for (s
= 0; s
< 5; ++s
) {
481 while (nvc0
->constbuf_dirty
[s
]) {
482 int i
= ffs(nvc0
->constbuf_dirty
[s
]) - 1;
483 nvc0
->constbuf_dirty
[s
] &= ~(1 << i
);
485 if (nvc0
->constbuf
[s
][i
].user
) {
486 struct nouveau_bo
*bo
= nvc0
->screen
->uniform_bo
;
487 const unsigned base
= NVC0_CB_USR_INFO(s
);
488 const unsigned size
= nvc0
->constbuf
[s
][0].size
;
489 assert(i
== 0); /* we really only want OpenGL uniforms here */
490 assert(nvc0
->constbuf
[s
][0].u
.data
);
492 if (nvc0
->state
.uniform_buffer_bound
[s
] < size
) {
493 nvc0
->state
.uniform_buffer_bound
[s
] = align(size
, 0x100);
495 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
496 PUSH_DATA (push
, nvc0
->state
.uniform_buffer_bound
[s
]);
497 PUSH_DATAh(push
, bo
->offset
+ base
);
498 PUSH_DATA (push
, bo
->offset
+ base
);
499 BEGIN_NVC0(push
, NVC0_3D(CB_BIND(s
)), 1);
500 PUSH_DATA (push
, (0 << 4) | 1);
502 nvc0_cb_bo_push(&nvc0
->base
, bo
, NV_VRAM_DOMAIN(&nvc0
->screen
->base
),
503 base
, nvc0
->state
.uniform_buffer_bound
[s
],
505 nvc0
->constbuf
[s
][0].u
.data
);
507 struct nv04_resource
*res
=
508 nv04_resource(nvc0
->constbuf
[s
][i
].u
.buf
);
510 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
511 PUSH_DATA (push
, nvc0
->constbuf
[s
][i
].size
);
512 PUSH_DATAh(push
, res
->address
+ nvc0
->constbuf
[s
][i
].offset
);
513 PUSH_DATA (push
, res
->address
+ nvc0
->constbuf
[s
][i
].offset
);
514 BEGIN_NVC0(push
, NVC0_3D(CB_BIND(s
)), 1);
515 PUSH_DATA (push
, (i
<< 4) | 1);
517 BCTX_REFN(nvc0
->bufctx_3d
, 3D_CB(s
, i
), res
, RD
);
519 nvc0
->cb_dirty
= 1; /* Force cache flush for UBO. */
520 res
->cb_bindings
[s
] |= 1 << i
;
522 BEGIN_NVC0(push
, NVC0_3D(CB_BIND(s
)), 1);
523 PUSH_DATA (push
, (i
<< 4) | 0);
526 nvc0
->state
.uniform_buffer_bound
[s
] = 0;
531 if (nvc0
->screen
->base
.class_3d
< NVE4_3D_CLASS
) {
532 /* Invalidate all COMPUTE constbufs because they are aliased with 3D. */
533 nvc0
->dirty_cp
|= NVC0_NEW_CP_CONSTBUF
;
534 nvc0
->constbuf_dirty
[5] |= nvc0
->constbuf_valid
[5];
535 nvc0
->state
.uniform_buffer_bound
[5] = 0;
540 nvc0_validate_buffers(struct nvc0_context
*nvc0
)
542 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
543 struct nvc0_screen
*screen
= nvc0
->screen
;
546 for (s
= 0; s
< 5; s
++) {
547 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
548 PUSH_DATA (push
, NVC0_CB_AUX_SIZE
);
549 PUSH_DATAh(push
, screen
->uniform_bo
->offset
+ NVC0_CB_AUX_INFO(s
));
550 PUSH_DATA (push
, screen
->uniform_bo
->offset
+ NVC0_CB_AUX_INFO(s
));
551 BEGIN_1IC0(push
, NVC0_3D(CB_POS
), 1 + 4 * NVC0_MAX_BUFFERS
);
552 PUSH_DATA (push
, NVC0_CB_AUX_BUF_INFO(0));
553 for (i
= 0; i
< NVC0_MAX_BUFFERS
; i
++) {
554 if (nvc0
->buffers
[s
][i
].buffer
) {
555 struct nv04_resource
*res
=
556 nv04_resource(nvc0
->buffers
[s
][i
].buffer
);
557 PUSH_DATA (push
, res
->address
+ nvc0
->buffers
[s
][i
].buffer_offset
);
558 PUSH_DATAh(push
, res
->address
+ nvc0
->buffers
[s
][i
].buffer_offset
);
559 PUSH_DATA (push
, nvc0
->buffers
[s
][i
].buffer_size
);
561 BCTX_REFN(nvc0
->bufctx_3d
, 3D_BUF
, res
, RDWR
);
562 util_range_add(&res
->valid_buffer_range
,
563 nvc0
->buffers
[s
][i
].buffer_offset
,
564 nvc0
->buffers
[s
][i
].buffer_offset
+
565 nvc0
->buffers
[s
][i
].buffer_size
);
578 nvc0_validate_sample_mask(struct nvc0_context
*nvc0
)
580 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
584 nvc0
->sample_mask
& 0xffff,
585 nvc0
->sample_mask
& 0xffff,
586 nvc0
->sample_mask
& 0xffff,
587 nvc0
->sample_mask
& 0xffff
590 BEGIN_NVC0(push
, NVC0_3D(MSAA_MASK(0)), 4);
591 PUSH_DATA (push
, mask
[0]);
592 PUSH_DATA (push
, mask
[1]);
593 PUSH_DATA (push
, mask
[2]);
594 PUSH_DATA (push
, mask
[3]);
598 nvc0_validate_min_samples(struct nvc0_context
*nvc0
)
600 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
603 samples
= util_next_power_of_two(nvc0
->min_samples
);
605 // If we're using the incoming sample mask and doing sample shading, we
606 // have to do sample shading "to the max", otherwise there's no way to
607 // tell which sets of samples are covered by the current invocation.
608 if (nvc0
->fragprog
->fp
.sample_mask_in
)
609 samples
= util_framebuffer_get_num_samples(&nvc0
->framebuffer
);
610 samples
|= NVC0_3D_SAMPLE_SHADING_ENABLE
;
613 IMMED_NVC0(push
, NVC0_3D(SAMPLE_SHADING
), samples
);
617 nvc0_validate_driverconst(struct nvc0_context
*nvc0
)
619 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
620 struct nvc0_screen
*screen
= nvc0
->screen
;
623 for (i
= 0; i
< 5; ++i
) {
624 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
625 PUSH_DATA (push
, NVC0_CB_AUX_SIZE
);
626 PUSH_DATAh(push
, screen
->uniform_bo
->offset
+ NVC0_CB_AUX_INFO(i
));
627 PUSH_DATA (push
, screen
->uniform_bo
->offset
+ NVC0_CB_AUX_INFO(i
));
628 BEGIN_NVC0(push
, NVC0_3D(CB_BIND(i
)), 1);
629 PUSH_DATA (push
, (15 << 4) | 1);
632 nvc0
->dirty_cp
|= NVC0_NEW_CP_DRIVERCONST
;
636 nvc0_validate_fp_zsa_rast(struct nvc0_context
*nvc0
)
638 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
639 bool rasterizer_discard
;
641 if (nvc0
->rast
&& nvc0
->rast
->pipe
.rasterizer_discard
) {
642 rasterizer_discard
= true;
644 bool zs
= nvc0
->zsa
&&
645 (nvc0
->zsa
->pipe
.depth
.enabled
|| nvc0
->zsa
->pipe
.stencil
[0].enabled
);
646 rasterizer_discard
= !zs
&&
647 (!nvc0
->fragprog
|| !nvc0
->fragprog
->hdr
[18]);
650 if (rasterizer_discard
!= nvc0
->state
.rasterizer_discard
) {
651 nvc0
->state
.rasterizer_discard
= rasterizer_discard
;
652 IMMED_NVC0(push
, NVC0_3D(RASTERIZE_ENABLE
), !rasterizer_discard
);
656 /* alpha test is disabled if there are no color RTs, so make sure we have at
657 * least one if alpha test is enabled. Note that this must run after
658 * nvc0_validate_fb, otherwise that will override the RT count setting.
661 nvc0_validate_zsa_fb(struct nvc0_context
*nvc0
)
663 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
665 if (nvc0
->zsa
&& nvc0
->zsa
->pipe
.alpha
.enabled
&&
666 nvc0
->framebuffer
.zsbuf
&&
667 nvc0
->framebuffer
.nr_cbufs
== 0) {
668 nvc0_fb_set_null_rt(push
, 0, 0);
669 BEGIN_NVC0(push
, NVC0_3D(RT_CONTROL
), 1);
670 PUSH_DATA (push
, (076543210 << 4) | 1);
675 nvc0_validate_blend_fb(struct nvc0_context
*nvc0
)
677 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
678 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
681 if ((!fb
->nr_cbufs
|| !fb
->cbufs
[0] ||
682 !util_format_is_pure_integer(fb
->cbufs
[0]->format
)) && nvc0
->blend
) {
683 if (nvc0
->blend
->pipe
.alpha_to_coverage
)
684 ms
|= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE
;
685 if (nvc0
->blend
->pipe
.alpha_to_one
)
686 ms
|= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE
;
689 BEGIN_NVC0(push
, NVC0_3D(MULTISAMPLE_CTRL
), 1);
690 PUSH_DATA (push
, ms
);
694 nvc0_validate_rast_fb(struct nvc0_context
*nvc0
)
696 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
697 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
698 struct pipe_rasterizer_state
*rast
= &nvc0
->rast
->pipe
;
703 if (rast
->offset_units_unscaled
) {
704 BEGIN_NVC0(push
, NVC0_3D(POLYGON_OFFSET_UNITS
), 1);
705 if (fb
->zsbuf
&& fb
->zsbuf
->format
== PIPE_FORMAT_Z16_UNORM
)
706 PUSH_DATAf(push
, rast
->offset_units
* (1 << 16));
708 PUSH_DATAf(push
, rast
->offset_units
* (1 << 24));
714 nvc0_validate_tess_state(struct nvc0_context
*nvc0
)
716 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
718 BEGIN_NVC0(push
, NVC0_3D(TESS_LEVEL_OUTER(0)), 6);
719 PUSH_DATAp(push
, nvc0
->default_tess_outer
, 4);
720 PUSH_DATAp(push
, nvc0
->default_tess_inner
, 2);
724 nvc0_switch_pipe_context(struct nvc0_context
*ctx_to
)
726 struct nvc0_context
*ctx_from
= ctx_to
->screen
->cur_ctx
;
730 ctx_to
->state
= ctx_from
->state
;
732 ctx_to
->state
= ctx_to
->screen
->save_state
;
734 ctx_to
->dirty_3d
= ~0;
735 ctx_to
->dirty_cp
= ~0;
736 ctx_to
->viewports_dirty
= ~0;
737 ctx_to
->scissors_dirty
= ~0;
739 for (s
= 0; s
< 6; ++s
) {
740 ctx_to
->samplers_dirty
[s
] = ~0;
741 ctx_to
->textures_dirty
[s
] = ~0;
742 ctx_to
->constbuf_dirty
[s
] = (1 << NVC0_MAX_PIPE_CONSTBUFS
) - 1;
743 ctx_to
->buffers_dirty
[s
] = ~0;
744 ctx_to
->images_dirty
[s
] = ~0;
747 /* Reset tfb as the shader that owns it may have been deleted. */
748 ctx_to
->state
.tfb
= NULL
;
751 ctx_to
->dirty_3d
&= ~(NVC0_NEW_3D_VERTEX
| NVC0_NEW_3D_ARRAYS
);
752 if (!ctx_to
->idxbuf
.buffer
)
753 ctx_to
->dirty_3d
&= ~NVC0_NEW_3D_IDXBUF
;
755 if (!ctx_to
->vertprog
)
756 ctx_to
->dirty_3d
&= ~NVC0_NEW_3D_VERTPROG
;
757 if (!ctx_to
->fragprog
)
758 ctx_to
->dirty_3d
&= ~NVC0_NEW_3D_FRAGPROG
;
761 ctx_to
->dirty_3d
&= ~NVC0_NEW_3D_BLEND
;
763 ctx_to
->dirty_3d
&= ~(NVC0_NEW_3D_RASTERIZER
| NVC0_NEW_3D_SCISSOR
);
765 ctx_to
->dirty_3d
&= ~NVC0_NEW_3D_ZSA
;
767 ctx_to
->screen
->cur_ctx
= ctx_to
;
770 static struct nvc0_state_validate
771 validate_list_3d
[] = {
772 { nvc0_validate_fb
, NVC0_NEW_3D_FRAMEBUFFER
},
773 { nvc0_validate_blend
, NVC0_NEW_3D_BLEND
},
774 { nvc0_validate_zsa
, NVC0_NEW_3D_ZSA
},
775 { nvc0_validate_sample_mask
, NVC0_NEW_3D_SAMPLE_MASK
},
776 { nvc0_validate_rasterizer
, NVC0_NEW_3D_RASTERIZER
},
777 { nvc0_validate_blend_colour
, NVC0_NEW_3D_BLEND_COLOUR
},
778 { nvc0_validate_stencil_ref
, NVC0_NEW_3D_STENCIL_REF
},
779 { nvc0_validate_stipple
, NVC0_NEW_3D_STIPPLE
},
780 { nvc0_validate_scissor
, NVC0_NEW_3D_SCISSOR
| NVC0_NEW_3D_RASTERIZER
},
781 { nvc0_validate_viewport
, NVC0_NEW_3D_VIEWPORT
},
782 { nvc0_validate_window_rects
, NVC0_NEW_3D_WINDOW_RECTS
},
783 { nvc0_vertprog_validate
, NVC0_NEW_3D_VERTPROG
},
784 { nvc0_tctlprog_validate
, NVC0_NEW_3D_TCTLPROG
},
785 { nvc0_tevlprog_validate
, NVC0_NEW_3D_TEVLPROG
},
786 { nvc0_validate_tess_state
, NVC0_NEW_3D_TESSFACTOR
},
787 { nvc0_gmtyprog_validate
, NVC0_NEW_3D_GMTYPROG
},
788 { nvc0_validate_min_samples
, NVC0_NEW_3D_MIN_SAMPLES
|
789 NVC0_NEW_3D_FRAGPROG
|
790 NVC0_NEW_3D_FRAMEBUFFER
},
791 { nvc0_fragprog_validate
, NVC0_NEW_3D_FRAGPROG
| NVC0_NEW_3D_RASTERIZER
},
792 { nvc0_validate_fp_zsa_rast
, NVC0_NEW_3D_FRAGPROG
| NVC0_NEW_3D_ZSA
|
793 NVC0_NEW_3D_RASTERIZER
},
794 { nvc0_validate_zsa_fb
, NVC0_NEW_3D_ZSA
| NVC0_NEW_3D_FRAMEBUFFER
},
795 { nvc0_validate_blend_fb
, NVC0_NEW_3D_BLEND
| NVC0_NEW_3D_FRAMEBUFFER
},
796 { nvc0_validate_rast_fb
, NVC0_NEW_3D_RASTERIZER
| NVC0_NEW_3D_FRAMEBUFFER
},
797 { nvc0_validate_clip
, NVC0_NEW_3D_CLIP
| NVC0_NEW_3D_RASTERIZER
|
798 NVC0_NEW_3D_VERTPROG
|
799 NVC0_NEW_3D_TEVLPROG
|
800 NVC0_NEW_3D_GMTYPROG
},
801 { nvc0_constbufs_validate
, NVC0_NEW_3D_CONSTBUF
},
802 { nvc0_validate_textures
, NVC0_NEW_3D_TEXTURES
},
803 { nvc0_validate_samplers
, NVC0_NEW_3D_SAMPLERS
},
804 { nve4_set_tex_handles
, NVC0_NEW_3D_TEXTURES
| NVC0_NEW_3D_SAMPLERS
},
805 { nvc0_vertex_arrays_validate
, NVC0_NEW_3D_VERTEX
| NVC0_NEW_3D_ARRAYS
},
806 { nvc0_validate_surfaces
, NVC0_NEW_3D_SURFACES
},
807 { nvc0_validate_buffers
, NVC0_NEW_3D_BUFFERS
},
808 { nvc0_idxbuf_validate
, NVC0_NEW_3D_IDXBUF
},
809 { nvc0_tfb_validate
, NVC0_NEW_3D_TFB_TARGETS
| NVC0_NEW_3D_GMTYPROG
},
810 { nvc0_validate_driverconst
, NVC0_NEW_3D_DRIVERCONST
},
814 nvc0_state_validate(struct nvc0_context
*nvc0
, uint32_t mask
,
815 struct nvc0_state_validate
*validate_list
, int size
,
816 uint32_t *dirty
, struct nouveau_bufctx
*bufctx
)
822 if (nvc0
->screen
->cur_ctx
!= nvc0
)
823 nvc0_switch_pipe_context(nvc0
);
825 state_mask
= *dirty
& mask
;
828 for (i
= 0; i
< size
; ++i
) {
829 struct nvc0_state_validate
*validate
= &validate_list
[i
];
831 if (state_mask
& validate
->states
)
832 validate
->func(nvc0
);
834 *dirty
&= ~state_mask
;
836 nvc0_bufctx_fence(nvc0
, bufctx
, false);
839 nouveau_pushbuf_bufctx(nvc0
->base
.pushbuf
, bufctx
);
840 ret
= nouveau_pushbuf_validate(nvc0
->base
.pushbuf
);
846 nvc0_state_validate_3d(struct nvc0_context
*nvc0
, uint32_t mask
)
850 ret
= nvc0_state_validate(nvc0
, mask
, validate_list_3d
,
851 ARRAY_SIZE(validate_list_3d
), &nvc0
->dirty_3d
,
854 if (unlikely(nvc0
->state
.flushed
)) {
855 nvc0
->state
.flushed
= false;
856 nvc0_bufctx_fence(nvc0
, nvc0
->bufctx_3d
, true);