1 /*
2 * Copyright (c) 2008-2024 Broadcom. All Rights Reserved.
3 * The term “Broadcom” refers to Broadcom Inc.
4 * and/or its subsidiaries.
5 * SPDX-License-Identifier: MIT
6 */
7
8 #include "util/compiler.h"
9 #include "util/u_inlines.h"
10 #include "pipe/p_defines.h"
11 #include "util/u_helpers.h"
12 #include "util/u_memory.h"
13 #include "util/u_math.h"
14
15 #include "svga_context.h"
16 #include "svga_draw.h"
17 #include "svga_draw_private.h"
18 #include "svga_debug.h"
19 #include "svga_screen.h"
20 #include "svga_resource.h"
21 #include "svga_resource_buffer.h"
22 #include "svga_resource_texture.h"
23 #include "svga_sampler_view.h"
24 #include "svga_shader.h"
25 #include "svga_surface.h"
26 #include "svga_winsys.h"
27 #include "svga_cmd.h"
28
29
30 struct svga_hwtnl *
svga_hwtnl_create(struct svga_context * svga)31 svga_hwtnl_create(struct svga_context *svga)
32 {
33 struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl);
34 if (!hwtnl)
35 goto fail;
36
37 hwtnl->svga = svga;
38
39 hwtnl->cmd.swc = svga->swc;
40
41 return hwtnl;
42
43 fail:
44 return NULL;
45 }
46
47
48 void
svga_hwtnl_destroy(struct svga_hwtnl * hwtnl)49 svga_hwtnl_destroy(struct svga_hwtnl *hwtnl)
50 {
51 unsigned i, j;
52
53 for (i = 0; i < MESA_PRIM_COUNT; i++) {
54 for (j = 0; j < IDX_CACHE_MAX; j++) {
55 pipe_resource_reference(&hwtnl->index_cache[i][j].buffer, NULL);
56 }
57 }
58
59 for (i = 0; i < hwtnl->cmd.vbuf_count; i++)
60 pipe_vertex_buffer_unreference(&hwtnl->cmd.vbufs[i]);
61
62 for (i = 0; i < hwtnl->cmd.prim_count; i++)
63 pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
64
65 FREE(hwtnl);
66 }
67
68
69 void
svga_hwtnl_set_flatshade(struct svga_hwtnl * hwtnl,bool flatshade,bool flatshade_first)70 svga_hwtnl_set_flatshade(struct svga_hwtnl *hwtnl,
71 bool flatshade, bool flatshade_first)
72 {
73 struct svga_screen *svgascreen = svga_screen(hwtnl->svga->pipe.screen);
74
75 /* User-specified PV */
76 hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST;
77
78 /* Device supported PV */
79 if (svgascreen->haveProvokingVertex) {
80 /* use the mode specified by the user */
81 hwtnl->hw_pv = hwtnl->api_pv;
82 }
83 else {
84 /* the device only support first provoking vertex */
85 hwtnl->hw_pv = PV_FIRST;
86 }
87 }
88
89
90 void
svga_hwtnl_set_fillmode(struct svga_hwtnl * hwtnl,unsigned mode)91 svga_hwtnl_set_fillmode(struct svga_hwtnl *hwtnl, unsigned mode)
92 {
93 hwtnl->api_fillmode = mode;
94 }
95
96
97 void
svga_hwtnl_vertex_decls(struct svga_hwtnl * hwtnl,unsigned count,const SVGA3dVertexDecl * decls,const unsigned * buffer_indexes,SVGA3dElementLayoutId layout_id)98 svga_hwtnl_vertex_decls(struct svga_hwtnl *hwtnl,
99 unsigned count,
100 const SVGA3dVertexDecl * decls,
101 const unsigned *buffer_indexes,
102 SVGA3dElementLayoutId layout_id)
103 {
104 assert(hwtnl->cmd.prim_count == 0);
105 hwtnl->cmd.vdecl_count = count;
106 hwtnl->cmd.vdecl_layout_id = layout_id;
107 memcpy(hwtnl->cmd.vdecl, decls, count * sizeof(*decls));
108 memcpy(hwtnl->cmd.vdecl_buffer_index, buffer_indexes,
109 count * sizeof(unsigned));
110 }
111
112
113 /**
114 * Specify vertex buffers for hardware drawing.
115 */
116 void
svga_hwtnl_vertex_buffers(struct svga_hwtnl * hwtnl,unsigned count,struct pipe_vertex_buffer * buffers)117 svga_hwtnl_vertex_buffers(struct svga_hwtnl *hwtnl,
118 unsigned count, struct pipe_vertex_buffer *buffers)
119 {
120 struct pipe_vertex_buffer *dst = hwtnl->cmd.vbufs;
121 const struct pipe_vertex_buffer *src = buffers;
122 unsigned i;
123
124 for (i = 0; i < count; i++) {
125 pipe_vertex_buffer_reference(&dst[i], &src[i]);
126 }
127
128 /* release old buffer references */
129 for ( ; i < hwtnl->cmd.vbuf_count; i++) {
130 pipe_vertex_buffer_unreference(&dst[i]);
131 /* don't bother zeroing stride/offset fields */
132 }
133
134 hwtnl->cmd.vbuf_count = count;
135 }
136
137
138 /**
139 * Determine whether the specified buffer is referred in the primitive queue,
140 * for which no commands have been written yet.
141 */
142 bool
svga_hwtnl_is_buffer_referred(struct svga_hwtnl * hwtnl,struct pipe_resource * buffer)143 svga_hwtnl_is_buffer_referred(struct svga_hwtnl *hwtnl,
144 struct pipe_resource *buffer)
145 {
146 unsigned i;
147
148 if (svga_buffer_is_user_buffer(buffer)) {
149 return false;
150 }
151
152 if (!hwtnl->cmd.prim_count) {
153 return false;
154 }
155
156 for (i = 0; i < hwtnl->cmd.vbuf_count; ++i) {
157 if (hwtnl->cmd.vbufs[i].buffer.resource == buffer) {
158 return true;
159 }
160 }
161
162 for (i = 0; i < hwtnl->cmd.prim_count; ++i) {
163 if (hwtnl->cmd.prim_ib[i] == buffer) {
164 return true;
165 }
166 }
167
168 return false;
169 }
170
171
172 static enum pipe_error
draw_vgpu9(struct svga_hwtnl * hwtnl)173 draw_vgpu9(struct svga_hwtnl *hwtnl)
174 {
175 struct svga_winsys_context *swc = hwtnl->cmd.swc;
176 struct svga_context *svga = hwtnl->svga;
177 enum pipe_error ret;
178 struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
179 struct svga_winsys_surface *ib_handle[QSZ];
180 struct svga_winsys_surface *handle;
181 SVGA3dVertexDecl *vdecl;
182 SVGA3dPrimitiveRange *prim;
183 unsigned i;
184
185 /* Re-validate those sampler views with backing copy
186 * of texture whose original copy has been updated.
187 * This is done here at draw time because the texture binding might not
188 * have modified, hence validation is not triggered at state update time,
189 * and yet the texture might have been updated in another context, so
190 * we need to re-validate the sampler view in order to update the backing
191 * copy of the updated texture.
192 */
193 if (svga->state.hw_draw.num_backed_views) {
194 for (i = 0; i < svga->state.hw_draw.num_views; i++) {
195 struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
196 struct svga_texture *tex = svga_texture(view->texture);
197 struct svga_sampler_view *sv = view->v;
198 if (sv && tex && sv->handle != tex->handle && sv->age < tex->age)
199 svga_validate_sampler_view(svga, view->v);
200 }
201 }
202
203 for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
204 unsigned j = hwtnl->cmd.vdecl_buffer_index[i];
205 handle = svga_buffer_handle(svga, hwtnl->cmd.vbufs[j].buffer.resource,
206 PIPE_BIND_VERTEX_BUFFER);
207 if (!handle)
208 return PIPE_ERROR_OUT_OF_MEMORY;
209
210 vb_handle[i] = handle;
211 }
212
213 for (i = 0; i < hwtnl->cmd.prim_count; i++) {
214 if (hwtnl->cmd.prim_ib[i]) {
215 handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i],
216 PIPE_BIND_INDEX_BUFFER);
217 if (!handle)
218 return PIPE_ERROR_OUT_OF_MEMORY;
219 }
220 else
221 handle = NULL;
222
223 ib_handle[i] = handle;
224 }
225
226 if (svga->rebind.flags.rendertargets) {
227 ret = svga_reemit_framebuffer_bindings(svga);
228 if (ret != PIPE_OK) {
229 return ret;
230 }
231 }
232
233 if (svga->rebind.flags.texture_samplers) {
234 ret = svga_reemit_tss_bindings(svga);
235 if (ret != PIPE_OK) {
236 return ret;
237 }
238 }
239
240 if (svga->rebind.flags.vs) {
241 ret = svga_reemit_vs_bindings(svga);
242 if (ret != PIPE_OK) {
243 return ret;
244 }
245 }
246
247 if (svga->rebind.flags.fs) {
248 ret = svga_reemit_fs_bindings(svga);
249 if (ret != PIPE_OK) {
250 return ret;
251 }
252 }
253
254 SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
255 svga->curr.framebuffer.cbufs[0] ?
256 svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
257 hwtnl->cmd.prim_count);
258
259 ret = SVGA3D_BeginDrawPrimitives(swc,
260 &vdecl,
261 hwtnl->cmd.vdecl_count,
262 &prim, hwtnl->cmd.prim_count);
263 if (ret != PIPE_OK)
264 return ret;
265
266 memcpy(vdecl,
267 hwtnl->cmd.vdecl,
268 hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);
269
270 for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
271 /* check for 4-byte alignment */
272 assert(vdecl[i].array.offset % 4 == 0);
273 assert(vdecl[i].array.stride % 4 == 0);
274
275 /* Given rangeHint is considered to be relative to indexBias, and
276 * indexBias varies per primitive, we cannot accurately supply an
277 * rangeHint when emitting more than one primitive per draw command.
278 */
279 if (hwtnl->cmd.prim_count == 1) {
280 vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
281 vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
282 }
283 else {
284 vdecl[i].rangeHint.first = 0;
285 vdecl[i].rangeHint.last = 0;
286 }
287
288 swc->surface_relocation(swc,
289 &vdecl[i].array.surfaceId,
290 NULL, vb_handle[i], SVGA_RELOC_READ);
291 }
292
293 memcpy(prim,
294 hwtnl->cmd.prim, hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);
295
296 for (i = 0; i < hwtnl->cmd.prim_count; i++) {
297 swc->surface_relocation(swc,
298 &prim[i].indexArray.surfaceId,
299 NULL, ib_handle[i], SVGA_RELOC_READ);
300 pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
301 }
302
303 SVGA_FIFOCommitAll(swc);
304
305 hwtnl->cmd.prim_count = 0;
306
307 return PIPE_OK;
308 }
309
310
311 static SVGA3dSurfaceFormat
xlate_index_format(unsigned indexWidth)312 xlate_index_format(unsigned indexWidth)
313 {
314 if (indexWidth == 2) {
315 return SVGA3D_R16_UINT;
316 }
317 else if (indexWidth == 4) {
318 return SVGA3D_R32_UINT;
319 }
320 else {
321 assert(!"Bad indexWidth");
322 return SVGA3D_R32_UINT;
323 }
324 }
325
326
327 /**
328 * A helper function to validate sampler view resources to ensure any
329 * pending updates to buffers will be emitted before they are referenced
330 * at draw or dispatch time. It also rebinds the resources if needed.
331 */
332 enum pipe_error
svga_validate_sampler_resources(struct svga_context * svga,enum svga_pipe_type pipe_type)333 svga_validate_sampler_resources(struct svga_context *svga,
334 enum svga_pipe_type pipe_type)
335 {
336 enum pipe_shader_type shader, first_shader, last_shader;
337
338 assert(svga_have_vgpu10(svga));
339
340 if (pipe_type == SVGA_PIPE_GRAPHICS) {
341 first_shader = PIPE_SHADER_VERTEX;
342 last_shader = PIPE_SHADER_COMPUTE;
343 }
344 else {
345 assert(svga_have_gl43(svga));
346 first_shader = PIPE_SHADER_COMPUTE;
347 last_shader = first_shader+1;
348 }
349
350 for (shader = first_shader; shader < last_shader; shader++) {
351 unsigned count = svga->curr.num_sampler_views[shader];
352 unsigned i;
353 struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS];
354 enum pipe_error ret;
355
356 /*
357 * Reference bound sampler resources to ensure pending updates are
358 * noticed by the device.
359 */
360 for (i = 0; i < count; i++) {
361 struct svga_pipe_sampler_view *sv =
362 svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]);
363
364 if (sv) {
365 if (sv->base.texture->target == PIPE_BUFFER) {
366 surfaces[i] = svga_buffer_handle(svga, sv->base.texture,
367 PIPE_BIND_SAMPLER_VIEW);
368 }
369 else {
370 surfaces[i] = svga_texture(sv->base.texture)->handle;
371 }
372 }
373 else {
374 surfaces[i] = NULL;
375 }
376 }
377
378 if (shader == PIPE_SHADER_FRAGMENT &&
379 svga->curr.rast->templ.poly_stipple_enable) {
380 const unsigned unit =
381 svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit;
382 struct svga_pipe_sampler_view *sv =
383 svga->polygon_stipple.sampler_view;
384
385 assert(sv);
386 surfaces[unit] = svga_texture(sv->base.texture)->handle;
387 count = MAX2(count, unit+1);
388 }
389
390 /* rebind the shader resources if needed */
391 if (svga->rebind.flags.texture_samplers) {
392 for (i = 0; i < count; i++) {
393 if (surfaces[i]) {
394 ret = svga->swc->resource_rebind(svga->swc,
395 surfaces[i],
396 NULL,
397 SVGA_RELOC_READ);
398 if (ret != PIPE_OK)
399 return ret;
400 }
401 }
402 }
403 }
404 svga->rebind.flags.texture_samplers = false;
405
406 return PIPE_OK;
407 }
408
409
410 /**
411 * A helper function to validate constant buffers to ensure any
412 * pending updates to the buffers will be emitted before they are referenced
413 * at draw or dispatch time. It also rebinds the resources if needed.
414 */
415 enum pipe_error
svga_validate_constant_buffers(struct svga_context * svga,enum svga_pipe_type pipe_type)416 svga_validate_constant_buffers(struct svga_context *svga,
417 enum svga_pipe_type pipe_type)
418 {
419 enum pipe_shader_type shader, first_shader, last_shader;
420
421 assert(svga_have_vgpu10(svga));
422
423 if (pipe_type == SVGA_PIPE_GRAPHICS) {
424 first_shader = PIPE_SHADER_VERTEX;
425 last_shader = PIPE_SHADER_COMPUTE;
426 }
427 else {
428 assert(svga_have_gl43(svga));
429 first_shader = PIPE_SHADER_COMPUTE;
430 last_shader = first_shader + 1;
431 }
432
433 for (shader = first_shader; shader < last_shader; shader++) {
434
435 enum pipe_error ret;
436 struct svga_buffer *buffer;
437
438 /* Rebind the default constant buffer if needed */
439 if (svga->rebind.flags.constbufs) {
440 buffer = svga_buffer(svga->state.hw_draw.constbuf[shader][0]);
441 if (buffer) {
442 ret = svga->swc->resource_rebind(svga->swc,
443 buffer->handle,
444 NULL,
445 SVGA_RELOC_READ);
446 if (ret != PIPE_OK)
447 return ret;
448 }
449 }
450
451 struct svga_winsys_surface *handle;
452 unsigned enabled_constbufs;
453
454 /*
455 * Reference other bound constant buffers to ensure pending updates are
456 * noticed by the device.
457 */
458 enabled_constbufs = svga->state.hw_draw.enabled_constbufs[shader] & ~1u;
459 while (enabled_constbufs) {
460 unsigned i = u_bit_scan(&enabled_constbufs);
461 buffer = svga_buffer(svga->curr.constbufs[shader][i].buffer);
462
463 /* If the constant buffer has hw storage, get the buffer winsys handle.
464 * Rebind the resource if needed.
465 */
466 if (buffer && !buffer->use_swbuf)
467 handle = svga_buffer_handle(svga, &buffer->b,
468 PIPE_BIND_CONSTANT_BUFFER);
469 else
470 handle = svga->state.hw_draw.constbufoffsets[shader][i].handle;
471
472 if (svga->rebind.flags.constbufs && handle) {
473 ret = svga->swc->resource_rebind(svga->swc,
474 handle,
475 NULL,
476 SVGA_RELOC_READ);
477 if (ret != PIPE_OK)
478 return ret;
479 }
480 }
481
482 /* Reference raw constant buffers as they are not included in the
483 * hw constant buffers list.
484 */
485 unsigned enabled_rawbufs = svga->state.hw_draw.enabled_rawbufs[shader] & ~1u;
486 while (enabled_rawbufs) {
487 unsigned i = u_bit_scan(&enabled_rawbufs);
488 buffer = svga_buffer(svga->state.hw_draw.rawbufs[shader][i].buffer);
489
490 assert(buffer != NULL);
491 handle = svga_buffer_handle(svga, &buffer->b,
492 PIPE_BIND_SAMPLER_VIEW);
493
494 if (svga->rebind.flags.constbufs && handle) {
495 ret = svga->swc->resource_rebind(svga->swc,
496 handle,
497 NULL,
498 SVGA_RELOC_READ);
499 if (ret != PIPE_OK)
500 return ret;
501 }
502 }
503 }
504 svga->rebind.flags.constbufs = false;
505
506 return PIPE_OK;
507 }
508
509
510 /**
511 * A helper function to validate image view resources to ensure any
512 * pending updates to buffers will be emitted before they are referenced
513 * at draw or dispatch time. It also rebinds the resources if needed.
514 */
515 enum pipe_error
svga_validate_image_views(struct svga_context * svga,enum svga_pipe_type pipe_type)516 svga_validate_image_views(struct svga_context *svga,
517 enum svga_pipe_type pipe_type)
518 {
519 enum pipe_shader_type shader, first_shader, last_shader;
520 bool rebind = svga->rebind.flags.images;
521 enum pipe_error ret;
522
523 assert(svga_have_gl43(svga));
524
525 if (pipe_type == SVGA_PIPE_GRAPHICS) {
526 first_shader = PIPE_SHADER_VERTEX;
527 last_shader = PIPE_SHADER_COMPUTE;
528 }
529 else {
530 first_shader = PIPE_SHADER_COMPUTE;
531 last_shader = first_shader + 1;
532 }
533
534 for (shader = first_shader; shader < last_shader; shader++) {
535 ret = svga_validate_image_view_resources(svga,
536 svga->state.hw_draw.num_image_views[shader],
537 &svga->state.hw_draw.image_views[shader][0], rebind);
538
539 if (ret != PIPE_OK)
540 return ret;
541 }
542
543 svga->rebind.flags.images = false;
544
545 return PIPE_OK;
546 }
547
548
549 /**
550 * A helper function to validate shader buffer and atomic buffer resources to
551 * ensure any pending updates to buffers will be emitted before they are
552 * referenced at draw or dispatch time. It also rebinds the resources if needed.
553 */
554 enum pipe_error
svga_validate_shader_buffers(struct svga_context * svga,enum svga_pipe_type pipe_type)555 svga_validate_shader_buffers(struct svga_context *svga,
556 enum svga_pipe_type pipe_type)
557 {
558 enum pipe_shader_type shader, first_shader, last_shader;
559 bool rebind = svga->rebind.flags.shaderbufs;
560 enum pipe_error ret;
561
562 assert(svga_have_gl43(svga));
563
564 if (pipe_type == SVGA_PIPE_GRAPHICS) {
565 first_shader = PIPE_SHADER_VERTEX;
566 last_shader = PIPE_SHADER_COMPUTE;
567 }
568 else {
569 first_shader = PIPE_SHADER_COMPUTE;
570 last_shader = first_shader + 1;
571 }
572
573 for (shader = first_shader; shader < last_shader; shader++) {
574 ret = svga_validate_shader_buffer_resources(svga,
575 svga->state.hw_draw.num_shader_buffers[shader],
576 &svga->state.hw_draw.shader_buffers[shader][0], rebind);
577
578 if (ret != PIPE_OK)
579 return ret;
580 }
581
582 svga->rebind.flags.shaderbufs = false;
583
584 ret = svga_validate_shader_buffer_resources(svga,
585 svga->state.hw_draw.num_atomic_buffers,
586 svga->state.hw_draw.atomic_buffers,
587 svga->rebind.flags.atomicbufs);
588
589 if (ret != PIPE_OK)
590 return ret;
591
592 svga->rebind.flags.atomicbufs = false;
593
594 return PIPE_OK;
595 }
596
597
598 /**
599 * Was the last command put into the command buffer a drawing command?
600 * We use this to determine if we can skip emitting buffer re-bind
601 * commands when we have a sequence of drawing commands that use the
602 * same vertex/index buffers with no intervening commands.
603 *
604 * The first drawing command will bind the vertex/index buffers. If
605 * the immediately following command is also a drawing command using the
606 * same buffers, we shouldn't have to rebind them.
607 */
608 static bool
last_command_was_draw(const struct svga_context * svga)609 last_command_was_draw(const struct svga_context *svga)
610 {
611 switch (SVGA3D_GetLastCommand(svga->swc)) {
612 case SVGA_3D_CMD_DX_DRAW:
613 case SVGA_3D_CMD_DX_DRAW_INDEXED:
614 case SVGA_3D_CMD_DX_DRAW_INSTANCED:
615 case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED:
616 case SVGA_3D_CMD_DX_DRAW_AUTO:
617 case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT:
618 case SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT:
619 return true;
620 default:
621 return false;
622 }
623 }
624
625
626 /**
627 * A helper function to compare vertex buffers.
628 * They are equal if the vertex buffer attributes and the vertex buffer
629 * resources are identical.
630 */
631 static bool
vertex_buffers_equal(unsigned count,SVGA3dVertexBuffer_v2 * pVBufAttr1,struct pipe_resource ** pVBuf1,SVGA3dVertexBuffer_v2 * pVBufAttr2,struct pipe_resource ** pVBuf2)632 vertex_buffers_equal(unsigned count,
633 SVGA3dVertexBuffer_v2 *pVBufAttr1,
634 struct pipe_resource **pVBuf1,
635 SVGA3dVertexBuffer_v2 *pVBufAttr2,
636 struct pipe_resource **pVBuf2)
637 {
638 return (memcmp(pVBufAttr1, pVBufAttr2,
639 count * sizeof(*pVBufAttr1)) == 0) &&
640 (memcmp(pVBuf1, pVBuf2, count * sizeof(*pVBuf1)) == 0);
641 }
642
643
644 /*
645 * Prepare the vertex buffers for a drawing command.
646 */
647 static enum pipe_error
validate_vertex_buffers(struct svga_hwtnl * hwtnl,const struct pipe_stream_output_target * so_vertex_count)648 validate_vertex_buffers(struct svga_hwtnl *hwtnl,
649 const struct pipe_stream_output_target *so_vertex_count)
650 {
651 struct svga_context *svga = hwtnl->svga;
652 struct pipe_resource *vbuffers[SVGA3D_INPUTREG_MAX];
653 struct svga_winsys_surface *vbuffer_handles[SVGA3D_INPUTREG_MAX];
654 struct svga_winsys_surface *so_vertex_count_handle = NULL;
655 const unsigned vbuf_count = so_vertex_count ? 1 : hwtnl->cmd.vbuf_count;
656 SVGA3dVertexBuffer_v2 vbuffer_attrs[PIPE_MAX_ATTRIBS];
657 int last_vbuf = -1;
658 unsigned i;
659
660 assert(svga_have_vgpu10(svga));
661
662 /* setup vertex attribute input layout */
663 if (svga->state.hw_draw.layout_id != hwtnl->cmd.vdecl_layout_id) {
664 enum pipe_error ret =
665 SVGA3D_vgpu10_SetInputLayout(svga->swc,
666 hwtnl->cmd.vdecl_layout_id);
667 if (ret != PIPE_OK)
668 return ret;
669
670 svga->state.hw_draw.layout_id = hwtnl->cmd.vdecl_layout_id;
671 }
672
673 /* Get handle for each referenced vertex buffer, unless we're using a
674 * stream-out buffer to specify the drawing information (DrawAuto).
675 * Also set up the buffer attributes.
676 */
677 if (so_vertex_count) {
678 so_vertex_count_handle = svga_buffer_handle(svga,
679 so_vertex_count->buffer,
680 (PIPE_BIND_VERTEX_BUFFER |
681 PIPE_BIND_STREAM_OUTPUT));
682 if (!so_vertex_count_handle)
683 return PIPE_ERROR_OUT_OF_MEMORY;
684
685 /* Set IA slot0 input buffer to the SO buffer */
686 assert(vbuf_count == 1);
687 vbuffer_attrs[0].stride = svga->state.sw.need_swtnl ? hwtnl->cmd.vdecl[0].array.stride : svga->curr.velems->strides[0];
688 vbuffer_attrs[0].offset = hwtnl->cmd.vbufs[0].buffer_offset;
689 vbuffer_attrs[0].sid = 0;
690 assert(so_vertex_count->buffer != NULL);
691 vbuffer_attrs[0].sizeInBytes = svga_buffer(so_vertex_count->buffer)->size;
692 vbuffers[0] = so_vertex_count->buffer;
693 vbuffer_handles[0] = so_vertex_count_handle;
694
695 i = 1;
696 }
697 else {
698 for (i = 0; i < vbuf_count; i++) {
699 struct svga_buffer *sbuf =
700 svga_buffer(hwtnl->cmd.vbufs[i].buffer.resource);
701
702 vbuffer_attrs[i].stride = svga->state.sw.need_swtnl ? hwtnl->cmd.vdecl[i].array.stride : svga->curr.velems->strides[i];
703 vbuffer_attrs[i].offset = hwtnl->cmd.vbufs[i].buffer_offset;
704 vbuffer_attrs[i].sid = 0;
705
706 if (sbuf) {
707 vbuffer_handles[i] = svga_buffer_handle(svga, &sbuf->b,
708 PIPE_BIND_VERTEX_BUFFER);
709 assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER);
710 if (vbuffer_handles[i] == NULL)
711 return PIPE_ERROR_OUT_OF_MEMORY;
712 vbuffers[i] = &sbuf->b;
713 last_vbuf = i;
714
715 vbuffer_attrs[i].sizeInBytes = sbuf->size;
716 }
717 else {
718 vbuffers[i] = NULL;
719 vbuffer_handles[i] = NULL;
720 vbuffer_attrs[i].sizeInBytes = 0;
721 }
722 }
723 }
724
725 /* Unbind the unreferenced the vertex buffer handles */
726 for (; i < svga->state.hw_draw.num_vbuffers; i++) {
727 vbuffers[i] = NULL;
728 vbuffer_handles[i] = NULL;
729 vbuffer_attrs[i].sid = 0;
730 vbuffer_attrs[i].stride = 0;
731 vbuffer_attrs[i].offset = 0;
732 vbuffer_attrs[i].sizeInBytes = 0;
733 }
734
735 /* Get handle for each referenced vertex buffer */
736 for (i = 0; i < vbuf_count; i++) {
737 struct svga_buffer *sbuf =
738 svga_buffer(hwtnl->cmd.vbufs[i].buffer.resource);
739
740 if (sbuf) {
741 vbuffer_handles[i] = svga_buffer_handle(svga, &sbuf->b,
742 PIPE_BIND_VERTEX_BUFFER);
743 assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER);
744 if (vbuffer_handles[i] == NULL)
745 return PIPE_ERROR_OUT_OF_MEMORY;
746 vbuffers[i] = &sbuf->b;
747 last_vbuf = i;
748 }
749 else {
750 vbuffers[i] = NULL;
751 vbuffer_handles[i] = NULL;
752 }
753 }
754
755 for (; i < svga->state.hw_draw.num_vbuffers; i++) {
756 vbuffers[i] = NULL;
757 vbuffer_handles[i] = NULL;
758 }
759
760 /* setup vertex attribute input layout */
761 if (svga->state.hw_draw.layout_id != hwtnl->cmd.vdecl_layout_id) {
762 enum pipe_error ret =
763 SVGA3D_vgpu10_SetInputLayout(svga->swc,
764 hwtnl->cmd.vdecl_layout_id);
765 if (ret != PIPE_OK)
766 return ret;
767
768 svga->state.hw_draw.layout_id = hwtnl->cmd.vdecl_layout_id;
769 }
770
771 /* Get handle for the stream out buffer */
772 if (so_vertex_count) {
773 so_vertex_count_handle = svga_buffer_handle(svga,
774 so_vertex_count->buffer,
775 (PIPE_BIND_VERTEX_BUFFER |
776 PIPE_BIND_STREAM_OUTPUT));
777 if (!so_vertex_count_handle)
778 return PIPE_ERROR_OUT_OF_MEMORY;
779 }
780 else {
781 so_vertex_count_handle = NULL;
782 }
783
784 /* setup vertex buffers */
785 {
786 /* If any of the vertex buffer state has changed, issue
787 * the SetVertexBuffers command. Otherwise, we will just
788 * need to rebind the resources.
789 */
790 if (vbuf_count != svga->state.hw_draw.num_vbuffers ||
791 !vertex_buffers_equal(vbuf_count,
792 vbuffer_attrs,
793 vbuffers,
794 svga->state.hw_draw.vbuffer_attrs,
795 svga->state.hw_draw.vbuffers)) {
796
797 unsigned num_vbuffers;
798
799 /* get the max of the current bound vertex buffers count and
800 * the to-be-bound vertex buffers count, so as to unbind
801 * the unused vertex buffers.
802 */
803 num_vbuffers = MAX2(vbuf_count, svga->state.hw_draw.num_vbuffers);
804
805 if (num_vbuffers > 0) {
806 SVGA3dVertexBuffer_v2 *pbufAttrs = vbuffer_attrs;
807 struct svga_winsys_surface **pbufHandles = vbuffer_handles;
808 unsigned numVBuf = 0;
809 bool emitVBufs =
810 !svga_sws(svga)->have_index_vertex_buffer_offset_cmd ||
811 svga->rebind.flags.vertexbufs;
812
813 /* Loop through the vertex buffer lists to only emit
814 * those vertex buffers that are not already in the
815 * corresponding entries in the device's vertex buffer list.
816 */
817 for (i = 0; i < num_vbuffers; i++) {
818 bool emit =
819 vertex_buffers_equal(1,
820 &vbuffer_attrs[i],
821 &vbuffers[i],
822 &svga->state.hw_draw.vbuffer_attrs[i],
823 &svga->state.hw_draw.vbuffers[i]);
824
825 /* Check if we can use the SetVertexBuffersOffsetAndSize command */
826 emitVBufs = emitVBufs ||
827 (vbuffers[i] != svga->state.hw_draw.vbuffers[i]);
828
829 if (!emit && i == num_vbuffers-1) {
830 /* Include the last vertex buffer in the next emit
831 * if it is different.
832 */
833 emit = true;
834 numVBuf++;
835 i++;
836 }
837
838 if (emit) {
839 /* numVBuf can only be 0 if the first vertex buffer
840 * is the same as the one in the device's list.
841 * In this case, there is nothing to send yet.
842 */
843 if (numVBuf) {
844 enum pipe_error ret;
845
846 /* If all vertex buffers handle are the same as the one
847 * in the device, just use the
848 * SetVertexBuffersOffsetAndSize comand.
849 */
850 if (emitVBufs) {
851 ret = SVGA3D_vgpu10_SetVertexBuffers(svga->swc,
852 numVBuf,
853 i - numVBuf,
854 pbufAttrs, pbufHandles);
855 } else {
856 ret = SVGA3D_vgpu10_SetVertexBuffersOffsetAndSize(svga->swc,
857 numVBuf,
858 i - numVBuf,
859 pbufAttrs);
860 }
861 if (ret != PIPE_OK)
862 return ret;
863 }
864 pbufAttrs += (numVBuf + 1);
865 pbufHandles += (numVBuf + 1);
866 numVBuf = 0;
867 }
868 else
869 numVBuf++;
870 }
871
872 /* save the number of vertex buffers sent to the device, not
873 * including trailing unbound vertex buffers.
874 */
875 svga->state.hw_draw.num_vbuffers = last_vbuf + 1;
876 memcpy(svga->state.hw_draw.vbuffer_attrs, vbuffer_attrs,
877 num_vbuffers * sizeof(vbuffer_attrs[0]));
878 for (i = 0; i < num_vbuffers; i++) {
879 pipe_resource_reference(&svga->state.hw_draw.vbuffers[i],
880 vbuffers[i]);
881 }
882 }
883 }
884 else {
885 /* Even though we can avoid emitting the redundant SetVertexBuffers
886 * command, we still need to reference the vertex buffers surfaces.
887 */
888 for (i = 0; i < vbuf_count; i++) {
889 if (vbuffer_handles[i] && !last_command_was_draw(svga)) {
890 enum pipe_error ret =
891 svga->swc->resource_rebind(svga->swc, vbuffer_handles[i],
892 NULL, SVGA_RELOC_READ);
893 if (ret != PIPE_OK)
894 return ret;
895 }
896 }
897 }
898 }
899
900 svga->rebind.flags.vertexbufs = false;
901
902 return PIPE_OK;
903 }
904
905
906 /*
907 * Prepare the index buffer for a drawing command.
908 */
909 static enum pipe_error
validate_index_buffer(struct svga_hwtnl * hwtnl,const SVGA3dPrimitiveRange * range,struct pipe_resource * ib)910 validate_index_buffer(struct svga_hwtnl *hwtnl,
911 const SVGA3dPrimitiveRange *range,
912 struct pipe_resource *ib)
913 {
914 struct svga_context *svga = hwtnl->svga;
915 struct svga_winsys_surface *ib_handle =
916 svga_buffer_handle(svga, ib, PIPE_BIND_INDEX_BUFFER);
917 enum pipe_error ret;
918
919 if (!ib_handle)
920 return PIPE_ERROR_OUT_OF_MEMORY;
921
922 struct svga_buffer *sbuf = svga_buffer(ib);
923 assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_INDEX_BUFFER);
924 (void) sbuf; /* silence unused var warning */
925
926 SVGA3dSurfaceFormat indexFormat = xlate_index_format(range->indexWidth);
927
928 if (ib != svga->state.hw_draw.ib ||
929 indexFormat != svga->state.hw_draw.ib_format ||
930 range->indexArray.offset != svga->state.hw_draw.ib_offset) {
931
932 assert(indexFormat != SVGA3D_FORMAT_INVALID);
933
934 if ((ib == svga->state.hw_draw.ib) &&
935 svga_sws(hwtnl->svga)->have_index_vertex_buffer_offset_cmd &&
936 !svga->rebind.flags.indexbuf) {
937
938 ret = SVGA3D_vgpu10_SetIndexBufferOffsetAndSize(svga->swc,
939 indexFormat,
940 range->indexArray.offset,
941 sbuf->size);
942 if (ret != PIPE_OK)
943 return ret;
944 }
945 else {
946
947 ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, ib_handle,
948 indexFormat,
949 range->indexArray.offset);
950 if (ret != PIPE_OK)
951 return ret;
952 }
953
954 pipe_resource_reference(&svga->state.hw_draw.ib, ib);
955 svga->state.hw_draw.ib_format = indexFormat;
956 svga->state.hw_draw.ib_offset = range->indexArray.offset;
957 }
958 else {
959 /* Even though we can avoid emitting the redundant SetIndexBuffer
960 * command, we still need to reference the index buffer surface.
961 */
962 if (!last_command_was_draw(svga)) {
963 enum pipe_error ret = svga->swc->resource_rebind(svga->swc,
964 ib_handle,
965 NULL,
966 SVGA_RELOC_READ);
967 if (ret != PIPE_OK)
968 return ret;
969 }
970 }
971
972 svga->rebind.flags.indexbuf = false;
973
974 return PIPE_OK;
975 }
976
977
978 static enum pipe_error
draw_vgpu10(struct svga_hwtnl * hwtnl,const SVGA3dPrimitiveRange * range,unsigned vcount,unsigned min_index,unsigned max_index,struct pipe_resource * ib,unsigned start_instance,unsigned instance_count,const struct pipe_draw_indirect_info * indirect,const struct pipe_stream_output_target * so_vertex_count)979 draw_vgpu10(struct svga_hwtnl *hwtnl,
980 const SVGA3dPrimitiveRange *range,
981 unsigned vcount,
982 unsigned min_index, unsigned max_index,
983 struct pipe_resource *ib,
984 unsigned start_instance, unsigned instance_count,
985 const struct pipe_draw_indirect_info *indirect,
986 const struct pipe_stream_output_target *so_vertex_count)
987 {
988 struct svga_context *svga = hwtnl->svga;
989 struct svga_winsys_surface *indirect_handle;
990 enum pipe_error ret;
991 bool is_instanced_draw = instance_count > 1 || start_instance > 0;
992
993 assert(svga_have_vgpu10(svga));
994 assert(hwtnl->cmd.prim_count == 0);
995
996 /* We need to reemit all the current resource bindings along with the Draw
997 * command to be sure that the referenced resources are available for the
998 * Draw command, just in case the surfaces associated with the resources
999 * are paged out.
1000 */
1001 if (svga->rebind.val) {
1002 ret = svga_rebind_framebuffer_bindings(svga);
1003 if (ret != PIPE_OK)
1004 return ret;
1005
1006 ret = svga_rebind_shaders(svga);
1007 if (ret != PIPE_OK)
1008 return ret;
1009
1010 /* Rebind stream output targets */
1011 ret = svga_rebind_stream_output_targets(svga);
1012 if (ret != PIPE_OK)
1013 return ret;
1014
1015 /* No need to explicitly rebind index buffer and vertex buffers here.
1016 * Even if the same index buffer or vertex buffers are referenced for this
1017 * draw and we skip emitting the redundant set command, we will still
1018 * reference the associated resources.
1019 */
1020 }
1021
1022 ret = svga_validate_sampler_resources(svga, SVGA_PIPE_GRAPHICS);
1023 if (ret != PIPE_OK)
1024 return ret;
1025
1026 ret = svga_validate_constant_buffers(svga, SVGA_PIPE_GRAPHICS);
1027 if (ret != PIPE_OK)
1028 return ret;
1029
1030 if (svga_have_gl43(svga)) {
1031 ret = svga_validate_image_views(svga, SVGA_PIPE_GRAPHICS);
1032 if (ret != PIPE_OK)
1033 return ret;
1034
1035 ret = svga_validate_shader_buffers(svga, SVGA_PIPE_GRAPHICS);
1036 if (ret != PIPE_OK)
1037 return ret;
1038
1039 if (svga->rebind.flags.uav) {
1040 ret= svga_rebind_uav(svga);
1041 if (ret != PIPE_OK)
1042 return ret;
1043 }
1044 }
1045
1046 ret = validate_vertex_buffers(hwtnl, so_vertex_count);
1047 if (ret != PIPE_OK)
1048 return ret;
1049
1050 if (ib) {
1051 ret = validate_index_buffer(hwtnl, range, ib);
1052 if (ret != PIPE_OK)
1053 return ret;
1054 }
1055
1056 if (indirect) {
1057 indirect_handle = svga_buffer_handle(svga, indirect->buffer,
1058 PIPE_BIND_COMMAND_ARGS_BUFFER);
1059 if (!indirect_handle)
1060 return PIPE_ERROR_OUT_OF_MEMORY;
1061 }
1062 else {
1063 indirect_handle = NULL;
1064 }
1065
1066 /* Set primitive type (line, tri, etc) */
1067 if (svga->state.hw_draw.topology != range->primType) {
1068 ret = SVGA3D_vgpu10_SetTopology(svga->swc, range->primType);
1069 if (ret != PIPE_OK)
1070 return ret;
1071
1072 svga->state.hw_draw.topology = range->primType;
1073 }
1074
1075 if (ib) {
1076 /* indexed drawing */
1077 if (indirect) {
1078 ret = SVGA3D_sm5_DrawIndexedInstancedIndirect(svga->swc,
1079 indirect_handle,
1080 indirect->offset);
1081 }
1082 else if (is_instanced_draw) {
1083 ret = SVGA3D_vgpu10_DrawIndexedInstanced(svga->swc,
1084 vcount,
1085 instance_count,
1086 0, /* startIndexLocation */
1087 range->indexBias,
1088 start_instance);
1089 }
1090 else {
1091 /* non-instanced drawing */
1092 ret = SVGA3D_vgpu10_DrawIndexed(svga->swc,
1093 vcount,
1094 0, /* startIndexLocation */
1095 range->indexBias);
1096 }
1097 if (ret != PIPE_OK) {
1098 return ret;
1099 }
1100 }
1101 else {
1102 /* non-indexed drawing */
1103 if (svga->state.hw_draw.ib_format != SVGA3D_FORMAT_INVALID ||
1104 svga->state.hw_draw.ib != NULL) {
1105 /* Unbind previously bound index buffer */
1106 ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, NULL,
1107 SVGA3D_FORMAT_INVALID, 0);
1108 if (ret != PIPE_OK)
1109 return ret;
1110 pipe_resource_reference(&svga->state.hw_draw.ib, NULL);
1111 svga->state.hw_draw.ib_format = SVGA3D_FORMAT_INVALID;
1112 }
1113
1114 assert(svga->state.hw_draw.ib == NULL);
1115
1116 if (so_vertex_count) {
1117 /* Stream-output drawing */
1118 ret = SVGA3D_vgpu10_DrawAuto(svga->swc);
1119 }
1120 else if (indirect) {
1121 ret = SVGA3D_sm5_DrawInstancedIndirect(svga->swc,
1122 indirect_handle,
1123 indirect->offset);
1124 }
1125 else if (is_instanced_draw) {
1126 ret = SVGA3D_vgpu10_DrawInstanced(svga->swc,
1127 vcount,
1128 instance_count,
1129 range->indexBias,
1130 start_instance);
1131 }
1132 else {
1133 /* non-instanced */
1134 ret = SVGA3D_vgpu10_Draw(svga->swc,
1135 vcount,
1136 range->indexBias);
1137 }
1138 if (ret != PIPE_OK) {
1139 return ret;
1140 }
1141 }
1142
1143 hwtnl->cmd.prim_count = 0;
1144
1145 return PIPE_OK;
1146 }
1147
1148
1149
1150 /**
1151 * Emit any pending drawing commands to the command buffer.
1152 * When we receive VGPU9 drawing commands we accumulate them and don't
1153 * immediately emit them into the command buffer.
1154 * This function needs to be called before we change state that could
1155 * effect those pending draws.
1156 */
1157 enum pipe_error
svga_hwtnl_flush(struct svga_hwtnl * hwtnl)1158 svga_hwtnl_flush(struct svga_hwtnl *hwtnl)
1159 {
1160 enum pipe_error ret = PIPE_OK;
1161
1162 SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLFLUSH);
1163
1164 if (!svga_have_vgpu10(hwtnl->svga) && hwtnl->cmd.prim_count) {
1165 /* we only queue up primitive for VGPU9 */
1166 ret = draw_vgpu9(hwtnl);
1167 }
1168
1169 SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws);
1170 return ret;
1171 }
1172
1173
1174 void
svga_hwtnl_set_index_bias(struct svga_hwtnl * hwtnl,int index_bias)1175 svga_hwtnl_set_index_bias(struct svga_hwtnl *hwtnl, int index_bias)
1176 {
1177 hwtnl->index_bias = index_bias;
1178 }
1179
1180
1181
1182 /***********************************************************************
1183 * Internal functions:
1184 */
1185
1186 /**
1187 * For debugging only.
1188 */
1189 static void
check_draw_params(struct svga_hwtnl * hwtnl,const SVGA3dPrimitiveRange * range,unsigned min_index,unsigned max_index,struct pipe_resource * ib)1190 check_draw_params(struct svga_hwtnl *hwtnl,
1191 const SVGA3dPrimitiveRange *range,
1192 unsigned min_index, unsigned max_index,
1193 struct pipe_resource *ib)
1194 {
1195 unsigned i;
1196
1197 assert(!svga_have_vgpu10(hwtnl->svga));
1198
1199 for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
1200 unsigned j = hwtnl->cmd.vdecl_buffer_index[i];
1201 const struct pipe_vertex_buffer *vb = &hwtnl->cmd.vbufs[j];
1202 unsigned size = vb->buffer.resource ? vb->buffer.resource->width0 : 0;
1203 unsigned offset = hwtnl->cmd.vdecl[i].array.offset;
1204 unsigned stride = hwtnl->cmd.vdecl[i].array.stride;
1205 int index_bias = (int) range->indexBias + hwtnl->index_bias;
1206 unsigned width;
1207
1208 if (size == 0)
1209 continue;
1210
1211 assert(vb);
1212 assert(size);
1213 assert(offset < size);
1214 assert(min_index <= max_index);
1215 (void) width;
1216 (void) stride;
1217 (void) offset;
1218 (void) size;
1219
1220 switch (hwtnl->cmd.vdecl[i].identity.type) {
1221 case SVGA3D_DECLTYPE_FLOAT1:
1222 width = 4;
1223 break;
1224 case SVGA3D_DECLTYPE_FLOAT2:
1225 width = 4 * 2;
1226 break;
1227 case SVGA3D_DECLTYPE_FLOAT3:
1228 width = 4 * 3;
1229 break;
1230 case SVGA3D_DECLTYPE_FLOAT4:
1231 width = 4 * 4;
1232 break;
1233 case SVGA3D_DECLTYPE_D3DCOLOR:
1234 width = 4;
1235 break;
1236 case SVGA3D_DECLTYPE_UBYTE4:
1237 width = 1 * 4;
1238 break;
1239 case SVGA3D_DECLTYPE_SHORT2:
1240 width = 2 * 2;
1241 break;
1242 case SVGA3D_DECLTYPE_SHORT4:
1243 width = 2 * 4;
1244 break;
1245 case SVGA3D_DECLTYPE_UBYTE4N:
1246 width = 1 * 4;
1247 break;
1248 case SVGA3D_DECLTYPE_SHORT2N:
1249 width = 2 * 2;
1250 break;
1251 case SVGA3D_DECLTYPE_SHORT4N:
1252 width = 2 * 4;
1253 break;
1254 case SVGA3D_DECLTYPE_USHORT2N:
1255 width = 2 * 2;
1256 break;
1257 case SVGA3D_DECLTYPE_USHORT4N:
1258 width = 2 * 4;
1259 break;
1260 case SVGA3D_DECLTYPE_UDEC3:
1261 width = 4;
1262 break;
1263 case SVGA3D_DECLTYPE_DEC3N:
1264 width = 4;
1265 break;
1266 case SVGA3D_DECLTYPE_FLOAT16_2:
1267 width = 2 * 2;
1268 break;
1269 case SVGA3D_DECLTYPE_FLOAT16_4:
1270 width = 2 * 4;
1271 break;
1272 default:
1273 assert(0);
1274 width = 0;
1275 break;
1276 }
1277
1278 if (index_bias >= 0) {
1279 assert(offset + index_bias * stride + width <= size);
1280 }
1281
1282 /*
1283 * min_index/max_index are merely conservative guesses, so we can't
1284 * make buffer overflow detection based on their values.
1285 */
1286 }
1287
1288 assert(range->indexWidth == range->indexArray.stride);
1289
1290 if (ib) {
1291 ASSERTED unsigned size = ib->width0;
1292 ASSERTED unsigned offset = range->indexArray.offset;
1293 ASSERTED unsigned stride = range->indexArray.stride;
1294 ASSERTED unsigned count;
1295
1296 assert(size);
1297 assert(offset < size);
1298 assert(stride);
1299
1300 switch (range->primType) {
1301 case SVGA3D_PRIMITIVE_POINTLIST:
1302 count = range->primitiveCount;
1303 break;
1304 case SVGA3D_PRIMITIVE_LINELIST:
1305 count = range->primitiveCount * 2;
1306 break;
1307 case SVGA3D_PRIMITIVE_LINESTRIP:
1308 count = range->primitiveCount + 1;
1309 break;
1310 case SVGA3D_PRIMITIVE_TRIANGLELIST:
1311 count = range->primitiveCount * 3;
1312 break;
1313 case SVGA3D_PRIMITIVE_TRIANGLESTRIP:
1314 count = range->primitiveCount + 2;
1315 break;
1316 case SVGA3D_PRIMITIVE_TRIANGLEFAN:
1317 count = range->primitiveCount + 2;
1318 break;
1319 default:
1320 assert(0);
1321 count = 0;
1322 break;
1323 }
1324
1325 assert(offset + count * stride <= size);
1326 }
1327 }
1328
1329
1330 /**
1331 * All drawing filters down into this function, either directly
1332 * on the hardware path or after doing software vertex processing.
1333 * \param indirect if non-null, get the vertex count, first vertex, etc.
1334 * from a buffer.
1335 * \param so_vertex_count if non-null, get the vertex count from a
1336 * stream-output target.
1337 */
1338 enum pipe_error
svga_hwtnl_prim(struct svga_hwtnl * hwtnl,const SVGA3dPrimitiveRange * range,unsigned vcount,unsigned min_index,unsigned max_index,struct pipe_resource * ib,unsigned start_instance,unsigned instance_count,const struct pipe_draw_indirect_info * indirect,const struct pipe_stream_output_target * so_vertex_count)1339 svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
1340 const SVGA3dPrimitiveRange *range,
1341 unsigned vcount,
1342 unsigned min_index, unsigned max_index,
1343 struct pipe_resource *ib,
1344 unsigned start_instance, unsigned instance_count,
1345 const struct pipe_draw_indirect_info *indirect,
1346 const struct pipe_stream_output_target *so_vertex_count)
1347 {
1348 enum pipe_error ret = PIPE_OK;
1349
1350 SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLPRIM);
1351
1352 if (svga_have_vgpu10(hwtnl->svga)) {
1353 /* draw immediately */
1354 SVGA_RETRY(hwtnl->svga, draw_vgpu10(hwtnl, range, vcount, min_index,
1355 max_index, ib, start_instance,
1356 instance_count, indirect,
1357 so_vertex_count));
1358 }
1359 else {
1360 /* batch up drawing commands */
1361 assert(indirect == NULL);
1362 #if MESA_DEBUG
1363 check_draw_params(hwtnl, range, min_index, max_index, ib);
1364 assert(start_instance == 0);
1365 assert(instance_count <= 1);
1366 #else
1367 (void) check_draw_params;
1368 #endif
1369
1370 if (hwtnl->cmd.prim_count + 1 >= QSZ) {
1371 ret = svga_hwtnl_flush(hwtnl);
1372 if (ret != PIPE_OK)
1373 goto done;
1374 }
1375
1376 /* min/max indices are relative to bias */
1377 hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index;
1378 hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index;
1379
1380 hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;
1381 hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias;
1382
1383 pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
1384 hwtnl->cmd.prim_count++;
1385 }
1386
1387 done:
1388 SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws);
1389 return ret;
1390 }
1391
1392
1393 /**
1394 * Return TRUE if there are pending primitives.
1395 */
1396 bool
svga_hwtnl_has_pending_prim(struct svga_hwtnl * hwtnl)1397 svga_hwtnl_has_pending_prim(struct svga_hwtnl *hwtnl)
1398 {
1399 return hwtnl->cmd.prim_count > 0;
1400 }
1401