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