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 */ 47SVGA3dUAViewId 48svga_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 */ 119static void 120svga_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 */ 221void 222svga_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 */ 249void 250svga_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 */ 265enum pipe_error 266svga_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