1 /*
2 * Copyright 2013 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25
26 /**
27 * VGPU10 sampler and sampler view functions.
28 */
29
30
31 #include "pipe/p_defines.h"
32 #include "util/u_bitmask.h"
33 #include "util/format/u_format.h"
34 #include "util/u_inlines.h"
35 #include "util/u_math.h"
36 #include "util/u_memory.h"
37
38 #include "svga_cmd.h"
39 #include "svga_context.h"
40 #include "svga_format.h"
41 #include "svga_resource_buffer.h"
42 #include "svga_resource_texture.h"
43 #include "svga_sampler_view.h"
44 #include "svga_shader.h"
45 #include "svga_state.h"
46 #include "svga_surface.h"
47 #include "svga3d_surfacedefs.h"
48
49 /** Get resource handle for a texture or buffer */
50 static inline struct svga_winsys_surface *
svga_resource_handle(struct pipe_resource * res)51 svga_resource_handle(struct pipe_resource *res)
52 {
53 if (res->target == PIPE_BUFFER) {
54 return svga_buffer(res)->handle;
55 }
56 else {
57 return svga_texture(res)->handle;
58 }
59 }
60
61
62 /**
63 * This helper function returns TRUE if the specified resource collides with
64 * any of the resources bound to any of the currently bound sampler views.
65 */
66 bool
svga_check_sampler_view_resource_collision(const struct svga_context * svga,const struct svga_winsys_surface * res,enum pipe_shader_type shader)67 svga_check_sampler_view_resource_collision(const struct svga_context *svga,
68 const struct svga_winsys_surface *res,
69 enum pipe_shader_type shader)
70 {
71 struct pipe_screen *screen = svga->pipe.screen;
72 unsigned i;
73
74 if (svga_screen(screen)->debug.no_surface_view) {
75 return false;
76 }
77
78 if (!svga_curr_shader_use_samplers(svga, shader))
79 return false;
80
81 for (i = 0; i < svga->curr.num_sampler_views[shader]; i++) {
82 struct svga_pipe_sampler_view *sv =
83 svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]);
84
85 if (sv && res == svga_resource_handle(sv->base.texture)) {
86 return true;
87 }
88 }
89
90 return false;
91 }
92
93
94 /**
95 * Check if there are any resources that are both bound to a render target
96 * and bound as a shader resource for the given type of shader.
97 */
98 bool
svga_check_sampler_framebuffer_resource_collision(struct svga_context * svga,enum pipe_shader_type shader)99 svga_check_sampler_framebuffer_resource_collision(struct svga_context *svga,
100 enum pipe_shader_type shader)
101 {
102 struct svga_surface *surf;
103 unsigned i;
104
105 for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
106 surf = svga_surface(svga->curr.framebuffer.cbufs[i]);
107 if (surf &&
108 svga_check_sampler_view_resource_collision(svga, surf->handle,
109 shader)) {
110 return true;
111 }
112 }
113
114 surf = svga_surface(svga->curr.framebuffer.zsbuf);
115 if (surf &&
116 svga_check_sampler_view_resource_collision(svga, surf->handle, shader)) {
117 return true;
118 }
119
120 return false;
121 }
122
123
124 /**
125 * Create a DX ShaderResourceSamplerView for the given pipe_sampler_view,
126 * if needed.
127 */
128 enum pipe_error
svga_validate_pipe_sampler_view(struct svga_context * svga,struct svga_pipe_sampler_view * sv)129 svga_validate_pipe_sampler_view(struct svga_context *svga,
130 struct svga_pipe_sampler_view *sv)
131 {
132 enum pipe_error ret = PIPE_OK;
133
134 if (sv->id == SVGA3D_INVALID_ID) {
135 struct svga_screen *ss = svga_screen(svga->pipe.screen);
136 struct pipe_resource *texture = sv->base.texture;
137 struct svga_winsys_surface *surface;
138 SVGA3dSurfaceFormat format;
139 SVGA3dResourceType resourceDim;
140 SVGA3dShaderResourceViewDesc viewDesc;
141 enum pipe_format viewFormat = sv->base.format;
142 enum pipe_texture_target target = sv->base.target;
143
144 /* vgpu10 cannot create a BGRX view for a BGRA resource, so force it to
145 * create a BGRA view (and vice versa).
146 */
147 if (viewFormat == PIPE_FORMAT_B8G8R8X8_UNORM &&
148 svga_texture_device_format_has_alpha(texture)) {
149 viewFormat = PIPE_FORMAT_B8G8R8A8_UNORM;
150 }
151 else if (viewFormat == PIPE_FORMAT_B8G8R8A8_UNORM &&
152 !svga_texture_device_format_has_alpha(texture)) {
153 viewFormat = PIPE_FORMAT_B8G8R8X8_UNORM;
154 }
155
156 if (target == PIPE_BUFFER) {
157 unsigned pf_flags;
158 assert(texture->target == PIPE_BUFFER);
159 svga_translate_texture_buffer_view_format(viewFormat,
160 &format,
161 &pf_flags);
162 surface = svga_buffer_handle(svga, texture, PIPE_BIND_SAMPLER_VIEW);
163 }
164 else {
165 format = svga_translate_format(ss, viewFormat,
166 PIPE_BIND_SAMPLER_VIEW);
167
168 /* Convert the format to a sampler-friendly format, if needed */
169 format = svga_sampler_format(format);
170
171 surface = svga_texture(texture)->handle;
172 }
173
174 assert(format != SVGA3D_FORMAT_INVALID);
175
176 if (target == PIPE_BUFFER) {
177 unsigned elem_size = util_format_get_blocksize(sv->base.format);
178
179 viewDesc.buffer.firstElement = sv->base.u.buf.offset / elem_size;
180 viewDesc.buffer.numElements = sv->base.u.buf.size / elem_size;
181 }
182 else {
183 viewDesc.tex.mostDetailedMip = sv->base.u.tex.first_level;
184 viewDesc.tex.firstArraySlice = sv->base.u.tex.first_layer;
185 viewDesc.tex.mipLevels = (sv->base.u.tex.last_level -
186 sv->base.u.tex.first_level + 1);
187 }
188
189 /* arraySize in viewDesc specifies the number of array slices in a
190 * texture array. For 3D texture, last_layer in
191 * pipe_sampler_view specifies the last slice of the texture
192 * which is different from the last slice in a texture array,
193 * hence we need to set arraySize to 1 explicitly.
194 */
195 viewDesc.tex.arraySize =
196 (target == PIPE_TEXTURE_3D || target == PIPE_BUFFER) ? 1 :
197 (sv->base.u.tex.last_layer - sv->base.u.tex.first_layer + 1);
198
199 switch (target) {
200 case PIPE_BUFFER:
201 resourceDim = SVGA3D_RESOURCE_BUFFER;
202 break;
203 case PIPE_TEXTURE_1D:
204 case PIPE_TEXTURE_1D_ARRAY:
205 resourceDim = SVGA3D_RESOURCE_TEXTURE1D;
206 break;
207 case PIPE_TEXTURE_RECT:
208 case PIPE_TEXTURE_2D:
209 case PIPE_TEXTURE_2D_ARRAY:
210 resourceDim = SVGA3D_RESOURCE_TEXTURE2D;
211 break;
212 case PIPE_TEXTURE_3D:
213 resourceDim = SVGA3D_RESOURCE_TEXTURE3D;
214 break;
215 case PIPE_TEXTURE_CUBE:
216 case PIPE_TEXTURE_CUBE_ARRAY:
217 resourceDim = SVGA3D_RESOURCE_TEXTURECUBE;
218 break;
219
220 default:
221 assert(!"Unexpected texture type");
222 resourceDim = SVGA3D_RESOURCE_TEXTURE2D;
223 }
224
225 sv->id = util_bitmask_add(svga->sampler_view_id_bm);
226
227 ret = SVGA3D_vgpu10_DefineShaderResourceView(svga->swc,
228 sv->id,
229 surface,
230 format,
231 resourceDim,
232 &viewDesc);
233 if (ret != PIPE_OK) {
234 util_bitmask_clear(svga->sampler_view_id_bm, sv->id);
235 sv->id = SVGA3D_INVALID_ID;
236 }
237 }
238
239 return ret;
240 }
241
242
243 static enum pipe_error
update_sampler_resources(struct svga_context * svga,uint64_t dirty)244 update_sampler_resources(struct svga_context *svga, uint64_t dirty)
245 {
246 enum pipe_error ret = PIPE_OK;
247 enum pipe_shader_type shader;
248
249 assert(svga_have_vgpu10(svga));
250
251 for (shader = PIPE_SHADER_VERTEX; shader < PIPE_SHADER_COMPUTE; shader++) {
252 SVGA3dShaderResourceViewId ids[PIPE_MAX_SAMPLERS];
253 struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS];
254 struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
255 unsigned count;
256 unsigned nviews;
257 unsigned i;
258
259 count = svga->curr.num_sampler_views[shader];
260 for (i = 0; i < count; i++) {
261 struct svga_pipe_sampler_view *sv =
262 svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]);
263
264 if (sv) {
265 surfaces[i] = svga_resource_handle(sv->base.texture);
266
267 ret = svga_validate_pipe_sampler_view(svga, sv);
268 if (ret != PIPE_OK)
269 return ret;
270
271 assert(sv->id != SVGA3D_INVALID_ID);
272 ids[i] = sv->id;
273 sampler_views[i] = &sv->base;
274 }
275 else {
276 surfaces[i] = NULL;
277 ids[i] = SVGA3D_INVALID_ID;
278 sampler_views[i] = NULL;
279 }
280 }
281
282 for (; i < svga->state.hw_draw.num_sampler_views[shader]; i++) {
283 ids[i] = SVGA3D_INVALID_ID;
284 surfaces[i] = NULL;
285 sampler_views[i] = NULL;
286 }
287
288 /* Number of ShaderResources that need to be modified. This includes
289 * the one that need to be unbound.
290 */
291 nviews = MAX2(svga->state.hw_draw.num_sampler_views[shader], count);
292 if (nviews > 0) {
293 if (count != svga->state.hw_draw.num_sampler_views[shader] ||
294 memcmp(sampler_views, svga->state.hw_draw.sampler_views[shader],
295 count * sizeof(sampler_views[0])) != 0) {
296 SVGA3dShaderResourceViewId *pIds = ids;
297 struct svga_winsys_surface **pSurf = surfaces;
298 unsigned numSR = 0;
299
300 /* Loop through the sampler view list to only emit
301 * the sampler views that are not already in the
302 * corresponding entries in the device's
303 * shader resource list.
304 */
305 for (i = 0; i < nviews; i++) {
306 bool emit;
307
308 emit = sampler_views[i] ==
309 svga->state.hw_draw.sampler_views[shader][i];
310
311 if (!emit && i == nviews-1) {
312 /* Include the last sampler view in the next emit
313 * if it is different.
314 */
315 emit = true;
316 numSR++;
317 i++;
318 }
319
320 if (emit) {
321 /* numSR can only be 0 if the first entry of the list
322 * is the same as the one in the device list.
323 * In this case, * there is nothing to send yet.
324 */
325 if (numSR) {
326 ret = SVGA3D_vgpu10_SetShaderResources(
327 svga->swc,
328 svga_shader_type(shader),
329 i - numSR, /* startView */
330 numSR,
331 pIds,
332 pSurf);
333
334 if (ret != PIPE_OK)
335 return ret;
336 }
337 pIds += (numSR + 1);
338 pSurf += (numSR + 1);
339 numSR = 0;
340 }
341 else
342 numSR++;
343 }
344
345 /* Save referenced sampler views in the hw draw state. */
346 svga->state.hw_draw.num_sampler_views[shader] = count;
347 for (i = 0; i < nviews; i++) {
348 pipe_sampler_view_reference(
349 &svga->state.hw_draw.sampler_views[shader][i],
350 sampler_views[i]);
351 }
352 }
353 }
354 }
355
356 /* Handle polygon stipple sampler view */
357 if (svga->curr.rast->templ.poly_stipple_enable) {
358 const unsigned unit =
359 svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit;
360 struct svga_pipe_sampler_view *sv = svga->polygon_stipple.sampler_view;
361 struct svga_winsys_surface *surface;
362
363 assert(sv);
364 if (!sv) {
365 return PIPE_OK; /* probably out of memory */
366 }
367
368 ret = svga_validate_pipe_sampler_view(svga, sv);
369 if (ret != PIPE_OK)
370 return ret;
371
372 surface = svga_resource_handle(sv->base.texture);
373 ret = SVGA3D_vgpu10_SetShaderResources(
374 svga->swc,
375 svga_shader_type(PIPE_SHADER_FRAGMENT),
376 unit, /* startView */
377 1,
378 &sv->id,
379 &surface);
380 }
381 return ret;
382 }
383
384
385 struct svga_tracked_state svga_hw_sampler_bindings = {
386 "shader resources emit",
387 SVGA_NEW_STIPPLE |
388 SVGA_NEW_TEXTURE_BINDING,
389 update_sampler_resources
390 };
391
392
393
394 static enum pipe_error
update_samplers(struct svga_context * svga,uint64_t dirty)395 update_samplers(struct svga_context *svga, uint64_t dirty )
396 {
397 enum pipe_error ret = PIPE_OK;
398 enum pipe_shader_type shader;
399
400 assert(svga_have_vgpu10(svga));
401
402 for (shader = PIPE_SHADER_VERTEX; shader < PIPE_SHADER_COMPUTE; shader++) {
403 const unsigned count = svga->curr.num_samplers[shader];
404 SVGA3dSamplerId ids[PIPE_MAX_SAMPLERS*2];
405 unsigned i;
406 unsigned nsamplers = 0;
407 bool sampler_state_mapping =
408 svga_use_sampler_state_mapping(svga, count);
409
410 for (i = 0; i < count; i++) {
411 bool fs_shadow = false;
412 const struct svga_sampler_state *sampler = svga->curr.sampler[shader][i];
413
414 /* _NEW_FS */
415 if (shader == PIPE_SHADER_FRAGMENT) {
416 struct svga_fs_variant *fs =
417 svga_fs_variant(svga->state.hw_draw.fs);
418
419 if (fs && (fs->fs_shadow_compare_units & (1 << i))) {
420
421 /* Use the alternate sampler state with the compare
422 * bit disabled when comparison is done in the shader and
423 * sampler state mapping is not enabled.
424 */
425 fs_shadow = true;
426 }
427 }
428
429 if (!sampler_state_mapping) {
430 if (sampler) {
431 SVGA3dSamplerId id = sampler->id[fs_shadow];
432 assert(id != SVGA3D_INVALID_ID);
433 ids[i] = id;
434 }
435 else {
436 ids[i] = SVGA3D_INVALID_ID;
437 }
438 nsamplers++;
439 }
440 else {
441 if (sampler) {
442 SVGA3dSamplerId id = sampler->id[0];
443 assert(id != SVGA3D_INVALID_ID);
444
445 /* Check if the sampler id is already on the ids list */
446 unsigned k;
447 for (k = 0; k < nsamplers; k++) {
448 if (ids[k] == id)
449 break;
450 }
451
452 /* add the id to the list if it is not already on the list */
453 if (k == nsamplers) {
454 ids[nsamplers++] = id;
455
456 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
457 /*
458 * add the alternate sampler state as well as the shader
459 * might use this alternate sampler state which has comparison
460 * disabled when the comparison is done in the shader.
461 */
462 ids[nsamplers++] = sampler->id[1];
463 }
464 }
465 }
466 }
467 }
468
469 for (i = nsamplers; i < svga->state.hw_draw.num_samplers[shader]; i++) {
470 ids[i] = SVGA3D_INVALID_ID;
471 }
472
473 unsigned nsamplerIds =
474 MAX2(nsamplers, svga->state.hw_draw.num_samplers[shader]);
475
476 if (nsamplerIds > 0) {
477
478 if (nsamplers > SVGA3D_DX_MAX_SAMPLERS) {
479 debug_warn_once("Too many sampler states");
480 nsamplers = SVGA3D_DX_MAX_SAMPLERS;
481 }
482
483 if (nsamplers != svga->state.hw_draw.num_samplers[shader] ||
484 memcmp(ids, svga->state.hw_draw.samplers[shader],
485 nsamplerIds * sizeof(ids[0])) != 0) {
486
487 /* HW state is really changing */
488 ret = SVGA3D_vgpu10_SetSamplers(svga->swc,
489 nsamplerIds,
490 0, /* start */
491 svga_shader_type(shader), /* type */
492 ids);
493 if (ret != PIPE_OK)
494 return ret;
495 memcpy(svga->state.hw_draw.samplers[shader], ids,
496 nsamplerIds * sizeof(ids[0]));
497 svga->state.hw_draw.num_samplers[shader] = nsamplers;
498 }
499 }
500 }
501
502 /* Handle polygon stipple sampler texture */
503 if (svga->curr.rast->templ.poly_stipple_enable) {
504 const unsigned unit =
505 svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_state_index;
506 struct svga_sampler_state *sampler = svga->polygon_stipple.sampler;
507
508 assert(sampler);
509 if (!sampler) {
510 return PIPE_OK; /* probably out of memory */
511 }
512
513 if (svga->state.hw_draw.samplers[PIPE_SHADER_FRAGMENT][unit]
514 != sampler->id[0]) {
515 ret = SVGA3D_vgpu10_SetSamplers(svga->swc,
516 1, /* count */
517 unit, /* start */
518 SVGA3D_SHADERTYPE_PS,
519 &sampler->id[0]);
520 if (ret != PIPE_OK)
521 return ret;
522
523 /* save the polygon stipple sampler in the hw draw state */
524 svga->state.hw_draw.samplers[PIPE_SHADER_FRAGMENT][unit] =
525 sampler->id[0];
526 }
527 svga->state.hw_draw.num_samplers[PIPE_SHADER_FRAGMENT]++;
528 }
529
530 return ret;
531 }
532
533
534 struct svga_tracked_state svga_hw_sampler = {
535 "texture sampler emit",
536 (SVGA_NEW_FS |
537 SVGA_NEW_SAMPLER |
538 SVGA_NEW_STIPPLE),
539 update_samplers
540 };
541
542
543 static enum pipe_error
update_cs_sampler_resources(struct svga_context * svga,uint64_t dirty)544 update_cs_sampler_resources(struct svga_context *svga, uint64_t dirty)
545 {
546 enum pipe_error ret = PIPE_OK;
547 enum pipe_shader_type shader = PIPE_SHADER_COMPUTE;
548
549 assert(svga_have_sm5(svga));
550
551 SVGA3dShaderResourceViewId ids[PIPE_MAX_SAMPLERS];
552 struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS];
553 struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
554 unsigned count;
555 unsigned nviews;
556 unsigned i;
557 struct svga_compute_shader *cs = svga->curr.cs;
558
559 count = svga->curr.num_sampler_views[shader];
560 if (!cs || !cs->base.info.uses_samplers)
561 count = 0;
562
563 for (i = 0; i < count; i++) {
564 struct svga_pipe_sampler_view *sv =
565 svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]);
566
567 if (sv) {
568 surfaces[i] = svga_resource_handle(sv->base.texture);
569
570 ret = svga_validate_pipe_sampler_view(svga, sv);
571 if (ret != PIPE_OK)
572 return ret;
573
574 assert(sv->id != SVGA3D_INVALID_ID);
575 ids[i] = sv->id;
576 sampler_views[i] = &sv->base;
577 }
578 else {
579 surfaces[i] = NULL;
580 ids[i] = SVGA3D_INVALID_ID;
581 sampler_views[i] = NULL;
582 }
583 }
584
585 for (; i < svga->state.hw_draw.num_sampler_views[shader]; i++) {
586 ids[i] = SVGA3D_INVALID_ID;
587 surfaces[i] = NULL;
588 sampler_views[i] = NULL;
589 }
590
591 /* Number of ShaderResources that need to be modified. This includes
592 * the one that need to be unbound.
593 */
594 nviews = MAX2(svga->state.hw_draw.num_sampler_views[shader], count);
595 if (nviews > 0) {
596 if (count != svga->state.hw_draw.num_sampler_views[shader] ||
597 memcmp(sampler_views, svga->state.hw_draw.sampler_views[shader],
598 count * sizeof(sampler_views[0])) != 0) {
599 SVGA3dShaderResourceViewId *pIds = ids;
600 struct svga_winsys_surface **pSurf = surfaces;
601 unsigned numSR = 0;
602
603 /* Loop through the sampler view list to only emit the sampler views
604 * that are not already in the corresponding entries in the device's
605 * shader resource list.
606 */
607 for (i = 0; i < nviews; i++) {
608 bool emit;
609
610 emit = sampler_views[i] ==
611 svga->state.hw_draw.sampler_views[shader][i];
612
613 if (!emit && i == nviews - 1) {
614 /* Include the last sampler view in the next emit
615 * if it is different.
616 */
617 emit = true;
618 numSR++;
619 i++;
620 }
621
622 if (emit) {
623 /* numSR can only be 0 if the first entry of the list
624 * is the same as the one in the device list.
625 * In this case, * there is nothing to send yet.
626 */
627 if (numSR) {
628 ret = SVGA3D_vgpu10_SetShaderResources(svga->swc,
629 svga_shader_type(shader),
630 i - numSR, /* startView */
631 numSR,
632 pIds,
633 pSurf);
634
635 if (ret != PIPE_OK)
636 return ret;
637 }
638 pIds += (numSR + 1);
639 pSurf += (numSR + 1);
640 numSR = 0;
641 }
642 else
643 numSR++;
644 }
645
646 /* Save referenced sampler views in the hw draw state. */
647 svga->state.hw_draw.num_sampler_views[shader] = count;
648 for (i = 0; i < nviews; i++) {
649 pipe_sampler_view_reference(
650 &svga->state.hw_draw.sampler_views[shader][i],
651 sampler_views[i]);
652 }
653 }
654 }
655 return ret;
656 }
657
658
659 struct svga_tracked_state svga_hw_cs_sampler_bindings = {
660 "cs shader resources emit",
661 SVGA_NEW_TEXTURE_BINDING,
662 update_cs_sampler_resources
663 };
664
665 static enum pipe_error
update_cs_samplers(struct svga_context * svga,uint64_t dirty)666 update_cs_samplers(struct svga_context *svga, uint64_t dirty )
667 {
668 enum pipe_error ret = PIPE_OK;
669 enum pipe_shader_type shader = PIPE_SHADER_COMPUTE;
670
671 assert(svga_have_sm5(svga));
672
673 const unsigned count = svga->curr.num_samplers[shader];
674 SVGA3dSamplerId ids[PIPE_MAX_SAMPLERS];
675 unsigned i;
676 unsigned nsamplers;
677
678 for (i = 0; i < count; i++) {
679 if (svga->curr.sampler[shader][i]) {
680 ids[i] = svga->curr.sampler[shader][i]->id[0];
681 assert(ids[i] != SVGA3D_INVALID_ID);
682 }
683 else {
684 ids[i] = SVGA3D_INVALID_ID;
685 }
686 }
687
688 for (; i < svga->state.hw_draw.num_samplers[shader]; i++) {
689 ids[i] = SVGA3D_INVALID_ID;
690 }
691
692 nsamplers = MAX2(svga->state.hw_draw.num_samplers[shader], count);
693 if (nsamplers > 0) {
694 if (count != svga->state.hw_draw.num_samplers[shader] ||
695 memcmp(ids, svga->state.hw_draw.samplers[shader],
696 count * sizeof(ids[0])) != 0) {
697 /* HW state is really changing */
698 ret = SVGA3D_vgpu10_SetSamplers(svga->swc,
699 nsamplers,
700 0, /* start */
701 svga_shader_type(shader), /* type */
702 ids);
703 if (ret != PIPE_OK)
704 return ret;
705
706 memcpy(svga->state.hw_draw.samplers[shader], ids,
707 nsamplers * sizeof(ids[0]));
708 svga->state.hw_draw.num_samplers[shader] = count;
709 }
710 }
711
712 return ret;
713 }
714
715
716 struct svga_tracked_state svga_hw_cs_sampler = {
717 "texture cs sampler emit",
718 (SVGA_NEW_CS |
719 SVGA_NEW_SAMPLER),
720 update_cs_samplers
721 };
722