• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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