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