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