• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**********************************************************
2  * Copyright 2022 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 #include "pipe/p_defines.h"
27 #include "util/u_bitmask.h"
28 #include "util/format/u_format.h"
29 #include "util/u_inlines.h"
30 #include "util/u_math.h"
31 #include "util/u_memory.h"
32 #include "tgsi/tgsi_parse.h"
33 
34 #include "svga_context.h"
35 #include "svga_cmd.h"
36 #include "svga_debug.h"
37 #include "svga_resource_buffer.h"
38 #include "svga_resource_texture.h"
39 #include "svga_surface.h"
40 #include "svga_sampler_view.h"
41 #include "svga_format.h"
42 
43 
44 /**
45  * Create a uav object for the specified shader image view
46  */
47 SVGA3dUAViewId
svga_create_uav_image(struct svga_context * svga,const struct pipe_image_view * image)48 svga_create_uav_image(struct svga_context *svga,
49                       const struct pipe_image_view *image)
50 {
51    struct svga_screen *ss = svga_screen(svga->pipe.screen);
52    SVGA3dSurfaceFormat svga_format;
53    SVGA3dUAViewDesc desc;
54    SVGA3dUAViewId uaViewId;
55 
56    assert(image);
57 
58    /* Make sure the translated svga format supports uav */
59    svga_format = svga_translate_format(ss, image->format,
60                                        PIPE_BIND_SHADER_IMAGE);
61    if (svga_format == SVGA3D_FORMAT_INVALID)
62       return SVGA3D_INVALID_ID;
63 
64    struct pipe_resource *res = image->resource;
65    struct svga_winsys_surface *surf;
66    unsigned resourceDim;
67 
68    /* resolve target to resource dimension */
69    resourceDim = svga_resource_type(res->target);
70 
71    memset(&desc, 0, sizeof(desc));
72 
73    if (resourceDim == SVGA3D_RESOURCE_BUFFER) {
74       unsigned block_width, block_height, bytes_per_block;
75 
76       svga_format_size(svga_format, &block_width, &block_height,
77                        &bytes_per_block);
78       surf = svga_buffer_handle(svga, res, PIPE_BIND_SHADER_IMAGE);
79       desc.buffer.firstElement = image->u.buf.offset / bytes_per_block;
80       desc.buffer.numElements = image->u.buf.size / bytes_per_block;
81 
82       /* mark this buffer as being used in uav */
83       struct svga_buffer *sbuf = svga_buffer(res);
84       sbuf->uav = TRUE;
85    }
86    else if (resourceDim == SVGA3D_RESOURCE_TEXTURE1D ||
87             resourceDim == SVGA3D_RESOURCE_TEXTURE2D) {
88 
89       struct svga_texture *tex = svga_texture(res);
90       surf = tex->handle;
91       desc.tex.mipSlice = image->u.tex.level;
92       desc.tex.firstArraySlice = image->u.tex.first_layer;
93       desc.tex.arraySize = image->u.tex.last_layer - image->u.tex.first_layer + 1;
94    }
95    else {
96       assert(resourceDim == SVGA3D_RESOURCE_TEXTURE3D);
97 
98       struct svga_texture *tex = svga_texture(res);
99       surf = tex->handle;
100       desc.tex3D.mipSlice = image->u.tex.level;
101       desc.tex3D.firstW = image->u.tex.first_layer;
102       desc.tex3D.wSize = image->u.tex.last_layer - image->u.tex.first_layer + 1;
103    }
104 
105    uaViewId = svga_create_uav(svga, &desc, svga_format, resourceDim, surf);
106    if (uaViewId == SVGA3D_INVALID_ID)
107       return uaViewId;
108 
109    SVGA_DBG(DEBUG_IMAGE, "%s: resource=0x%x dim=%d format=%d uaViewId=%d\n",
110             __FUNCTION__, res, resourceDim, svga_format, uaViewId);
111 
112    return uaViewId;
113 }
114 
115 
116 /**
117  * Set shader images
118  */
119 static void
svga_set_shader_images(struct pipe_context * pipe,enum pipe_shader_type shader,unsigned start,unsigned num,unsigned unbind_num_trailing_slots,const struct pipe_image_view * images)120 svga_set_shader_images(struct pipe_context *pipe,
121                        enum pipe_shader_type shader,
122                        unsigned start,
123                        unsigned num,
124                        unsigned unbind_num_trailing_slots,
125                        const struct pipe_image_view *images)
126 {
127    struct svga_context *svga = svga_context(pipe);
128    const struct pipe_image_view *img = images;
129 
130    assert(svga_have_gl43(svga));
131 
132    assert(start + num <= SVGA_MAX_IMAGES);
133 
134    if (images) {
135       for (unsigned i = start; i < start + num; i++, img++) {
136          struct svga_image_view *cur_image_view = &svga->curr.image_views[shader][i];
137 
138          if (img) {
139             cur_image_view->desc = *img;
140             if (img->resource == NULL) {
141                /* Use a dummy resource if the image view is created with a NULL resource */
142                if (svga->dummy_resource == NULL) {
143                   struct svga_screen *ss = svga_screen(svga->pipe.screen);
144                   struct pipe_resource templ;
145                   struct pipe_resource *res;
146                   templ.target = PIPE_BUFFER;
147                   templ.format = PIPE_FORMAT_R8_UNORM;
148                   templ.bind = PIPE_BIND_SHADER_BUFFER;
149                   templ.width0 = 64;
150                   templ.height0 = 1;
151                   templ.depth0 = 1;
152                   templ.array_size = 1;
153                   res = ss->screen.resource_create(&ss->screen, &templ);
154                   pipe_resource_reference(&svga->dummy_resource, res);
155                }
156                pipe_resource_reference(&cur_image_view->resource,
157                                        svga->dummy_resource);
158             }
159             else {
160                pipe_resource_reference(&cur_image_view->resource,
161                                        img->resource);
162             }
163          }
164          else {
165             pipe_resource_reference(&cur_image_view->resource, NULL);
166          }
167          cur_image_view->uav_index = -1;
168       }
169    }
170 
171    /* unbind trailing slots */
172    for (unsigned j = 0, i = start + num; j < unbind_num_trailing_slots;
173         i++, j++) {
174       struct svga_image_view *cur_image_view = &svga->curr.image_views[shader][i];
175       cur_image_view->uav_index = -1;
176       pipe_resource_reference(&cur_image_view->resource, NULL);
177    }
178 
179    /* number of bound image views */
180    svga->curr.num_image_views[shader] = start + num;
181 
182 #ifdef DEBUG
183    SVGA_DBG(DEBUG_UAV, "%s: num_image_views=%d start=%d num=%d unbind_num_trailing_slots=%d\n",
184             __FUNCTION__, svga->curr.num_image_views[shader], start, num,
185             unbind_num_trailing_slots);
186 
187    for (unsigned i = start; i < start + num; i++) {
188       struct svga_image_view *cur_image_view = &svga->curr.image_views[shader][i];
189       struct pipe_image_view *img = &cur_image_view->desc;
190       if (img->resource) {
191          if (img->resource->target == PIPE_BUFFER) {
192             SVGA_DBG(DEBUG_UAV, "   buffer res=0x%x format=%d offset=%d size=%d\n",
193                      img->resource, img->format,
194                      img->u.buf.offset, img->u.buf.size);
195          }
196          else {
197             SVGA_DBG(DEBUG_UAV,
198                "   texture res=0x%x format=%d first_layer=%d last_layer=%d level=%d\n",
199                      img->resource, img->format, img->u.tex.first_layer,
200                      img->u.tex.last_layer, img->u.tex.level);
201          }
202       }
203       else {
204          SVGA_DBG(DEBUG_UAV, "   res=NULL\n");
205       }
206    }
207 
208    SVGA_DBG(DEBUG_UAV, "\n");
209 #endif
210 
211    /* purge any unused uav objects */
212    svga_destroy_uav(svga);
213 
214    svga->dirty |= SVGA_NEW_IMAGE_VIEW;
215 }
216 
217 
218 /**
219  *  Initialize shader images gallium interface
220  */
221 void
svga_init_shader_image_functions(struct svga_context * svga)222 svga_init_shader_image_functions(struct svga_context *svga)
223 {
224    if (svga_have_gl43(svga)) {
225       svga->pipe.set_shader_images = svga_set_shader_images;
226    }
227 
228    /* Initialize shader image views */
229    for (unsigned shader = 0; shader < PIPE_SHADER_TYPES; ++shader) {
230       struct svga_image_view *hw_image_views =
231          &svga->state.hw_draw.image_views[shader][0];
232       struct svga_image_view *cur_image_views =
233          &svga->curr.image_views[shader][0];
234 
235       for (unsigned i = 0; i < ARRAY_SIZE(svga->curr.image_views[shader]);
236            i++, hw_image_views++, cur_image_views++) {
237          hw_image_views->resource = NULL;
238          cur_image_views->resource = NULL;
239       }
240    }
241    memset(svga->state.hw_draw.num_image_views, 0,
242           sizeof(svga->state.hw_draw.num_image_views));
243 }
244 
245 
246 /**
247  * Cleanup shader image state
248  */
249 void
svga_cleanup_shader_image_state(struct svga_context * svga)250 svga_cleanup_shader_image_state(struct svga_context *svga)
251 {
252    if (!svga_have_gl43(svga))
253       return;
254 
255    svga_destroy_uav(svga);
256 }
257 
258 
259 /**
260  * Validate shader image view resources to ensure any pending changes to
261  * texture buffers are emitted before they are referenced in image views.
262  * The helper function also rebinds the image view resources if the rebind flag
263  * is specified.
264  */
265 enum pipe_error
svga_validate_image_view_resources(struct svga_context * svga,unsigned count,struct svga_image_view * images,bool rebind)266 svga_validate_image_view_resources(struct svga_context *svga,
267                                    unsigned count,
268                                    struct svga_image_view *images,
269                                    bool rebind)
270 {
271    assert(svga_have_gl43(svga));
272 
273    struct svga_winsys_surface *surf;
274    enum pipe_error ret;
275    unsigned i;
276 
277    for (i = 0; i < count; i++) {
278       struct pipe_resource *res = images[i].resource;
279       if (res) {
280          assert(res == images[i].desc.resource);
281          if (res->target == PIPE_BUFFER) {
282             struct svga_buffer *sbuf = svga_buffer(res);
283 
284             surf = svga_buffer_handle(svga, res, PIPE_BIND_SHADER_IMAGE);
285             /* Mark buffer surface as RENDERED */
286             svga_set_buffer_rendered_to(sbuf->bufsurf);
287          } else {
288             struct svga_texture *tex = svga_texture(res);
289 
290             surf = tex->handle;
291             /* Mark texture as RENDERED */
292             svga_set_texture_rendered_to(tex);
293          }
294 
295          assert(surf);
296          if (rebind) {
297             ret = svga->swc->resource_rebind(svga->swc, surf, NULL,
298                                              SVGA_RELOC_READ|SVGA_RELOC_WRITE);
299             if (ret != PIPE_OK)
300                return ret;
301          }
302       }
303    }
304 
305    return PIPE_OK;
306 }
307