1bf215546Sopenharmony_ci/********************************************************** 2bf215546Sopenharmony_ci * Copyright 2022 VMware, Inc. All rights reserved. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person 5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation 6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without 7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy, 8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies 9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is 10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be 13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci **********************************************************/ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "pipe/p_defines.h" 27bf215546Sopenharmony_ci#include "util/u_bitmask.h" 28bf215546Sopenharmony_ci#include "util/format/u_format.h" 29bf215546Sopenharmony_ci#include "util/u_inlines.h" 30bf215546Sopenharmony_ci#include "util/u_math.h" 31bf215546Sopenharmony_ci#include "util/u_memory.h" 32bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "svga_context.h" 35bf215546Sopenharmony_ci#include "svga_cmd.h" 36bf215546Sopenharmony_ci#include "svga_debug.h" 37bf215546Sopenharmony_ci#include "svga_resource_buffer.h" 38bf215546Sopenharmony_ci#include "svga_resource_texture.h" 39bf215546Sopenharmony_ci#include "svga_surface.h" 40bf215546Sopenharmony_ci#include "svga_sampler_view.h" 41bf215546Sopenharmony_ci#include "svga_format.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci/** 45bf215546Sopenharmony_ci * Create a uav object for the specified shader image view 46bf215546Sopenharmony_ci */ 47bf215546Sopenharmony_ciSVGA3dUAViewId 48bf215546Sopenharmony_cisvga_create_uav_image(struct svga_context *svga, 49bf215546Sopenharmony_ci const struct pipe_image_view *image) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci struct svga_screen *ss = svga_screen(svga->pipe.screen); 52bf215546Sopenharmony_ci SVGA3dSurfaceFormat svga_format; 53bf215546Sopenharmony_ci SVGA3dUAViewDesc desc; 54bf215546Sopenharmony_ci SVGA3dUAViewId uaViewId; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci assert(image); 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci /* Make sure the translated svga format supports uav */ 59bf215546Sopenharmony_ci svga_format = svga_translate_format(ss, image->format, 60bf215546Sopenharmony_ci PIPE_BIND_SHADER_IMAGE); 61bf215546Sopenharmony_ci if (svga_format == SVGA3D_FORMAT_INVALID) 62bf215546Sopenharmony_ci return SVGA3D_INVALID_ID; 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci struct pipe_resource *res = image->resource; 65bf215546Sopenharmony_ci struct svga_winsys_surface *surf; 66bf215546Sopenharmony_ci unsigned resourceDim; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci /* resolve target to resource dimension */ 69bf215546Sopenharmony_ci resourceDim = svga_resource_type(res->target); 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci memset(&desc, 0, sizeof(desc)); 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci if (resourceDim == SVGA3D_RESOURCE_BUFFER) { 74bf215546Sopenharmony_ci unsigned block_width, block_height, bytes_per_block; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci svga_format_size(svga_format, &block_width, &block_height, 77bf215546Sopenharmony_ci &bytes_per_block); 78bf215546Sopenharmony_ci surf = svga_buffer_handle(svga, res, PIPE_BIND_SHADER_IMAGE); 79bf215546Sopenharmony_ci desc.buffer.firstElement = image->u.buf.offset / bytes_per_block; 80bf215546Sopenharmony_ci desc.buffer.numElements = image->u.buf.size / bytes_per_block; 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci /* mark this buffer as being used in uav */ 83bf215546Sopenharmony_ci struct svga_buffer *sbuf = svga_buffer(res); 84bf215546Sopenharmony_ci sbuf->uav = TRUE; 85bf215546Sopenharmony_ci } 86bf215546Sopenharmony_ci else if (resourceDim == SVGA3D_RESOURCE_TEXTURE1D || 87bf215546Sopenharmony_ci resourceDim == SVGA3D_RESOURCE_TEXTURE2D) { 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(res); 90bf215546Sopenharmony_ci surf = tex->handle; 91bf215546Sopenharmony_ci desc.tex.mipSlice = image->u.tex.level; 92bf215546Sopenharmony_ci desc.tex.firstArraySlice = image->u.tex.first_layer; 93bf215546Sopenharmony_ci desc.tex.arraySize = image->u.tex.last_layer - image->u.tex.first_layer + 1; 94bf215546Sopenharmony_ci } 95bf215546Sopenharmony_ci else { 96bf215546Sopenharmony_ci assert(resourceDim == SVGA3D_RESOURCE_TEXTURE3D); 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(res); 99bf215546Sopenharmony_ci surf = tex->handle; 100bf215546Sopenharmony_ci desc.tex3D.mipSlice = image->u.tex.level; 101bf215546Sopenharmony_ci desc.tex3D.firstW = image->u.tex.first_layer; 102bf215546Sopenharmony_ci desc.tex3D.wSize = image->u.tex.last_layer - image->u.tex.first_layer + 1; 103bf215546Sopenharmony_ci } 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci uaViewId = svga_create_uav(svga, &desc, svga_format, resourceDim, surf); 106bf215546Sopenharmony_ci if (uaViewId == SVGA3D_INVALID_ID) 107bf215546Sopenharmony_ci return uaViewId; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci SVGA_DBG(DEBUG_IMAGE, "%s: resource=0x%x dim=%d format=%d uaViewId=%d\n", 110bf215546Sopenharmony_ci __FUNCTION__, res, resourceDim, svga_format, uaViewId); 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci return uaViewId; 113bf215546Sopenharmony_ci} 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci/** 117bf215546Sopenharmony_ci * Set shader images 118bf215546Sopenharmony_ci */ 119bf215546Sopenharmony_cistatic void 120bf215546Sopenharmony_cisvga_set_shader_images(struct pipe_context *pipe, 121bf215546Sopenharmony_ci enum pipe_shader_type shader, 122bf215546Sopenharmony_ci unsigned start, 123bf215546Sopenharmony_ci unsigned num, 124bf215546Sopenharmony_ci unsigned unbind_num_trailing_slots, 125bf215546Sopenharmony_ci const struct pipe_image_view *images) 126bf215546Sopenharmony_ci{ 127bf215546Sopenharmony_ci struct svga_context *svga = svga_context(pipe); 128bf215546Sopenharmony_ci const struct pipe_image_view *img = images; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci assert(svga_have_gl43(svga)); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci assert(start + num <= SVGA_MAX_IMAGES); 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci if (images) { 135bf215546Sopenharmony_ci for (unsigned i = start; i < start + num; i++, img++) { 136bf215546Sopenharmony_ci struct svga_image_view *cur_image_view = &svga->curr.image_views[shader][i]; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci if (img) { 139bf215546Sopenharmony_ci cur_image_view->desc = *img; 140bf215546Sopenharmony_ci if (img->resource == NULL) { 141bf215546Sopenharmony_ci /* Use a dummy resource if the image view is created with a NULL resource */ 142bf215546Sopenharmony_ci if (svga->dummy_resource == NULL) { 143bf215546Sopenharmony_ci struct svga_screen *ss = svga_screen(svga->pipe.screen); 144bf215546Sopenharmony_ci struct pipe_resource templ; 145bf215546Sopenharmony_ci struct pipe_resource *res; 146bf215546Sopenharmony_ci templ.target = PIPE_BUFFER; 147bf215546Sopenharmony_ci templ.format = PIPE_FORMAT_R8_UNORM; 148bf215546Sopenharmony_ci templ.bind = PIPE_BIND_SHADER_BUFFER; 149bf215546Sopenharmony_ci templ.width0 = 64; 150bf215546Sopenharmony_ci templ.height0 = 1; 151bf215546Sopenharmony_ci templ.depth0 = 1; 152bf215546Sopenharmony_ci templ.array_size = 1; 153bf215546Sopenharmony_ci res = ss->screen.resource_create(&ss->screen, &templ); 154bf215546Sopenharmony_ci pipe_resource_reference(&svga->dummy_resource, res); 155bf215546Sopenharmony_ci } 156bf215546Sopenharmony_ci pipe_resource_reference(&cur_image_view->resource, 157bf215546Sopenharmony_ci svga->dummy_resource); 158bf215546Sopenharmony_ci } 159bf215546Sopenharmony_ci else { 160bf215546Sopenharmony_ci pipe_resource_reference(&cur_image_view->resource, 161bf215546Sopenharmony_ci img->resource); 162bf215546Sopenharmony_ci } 163bf215546Sopenharmony_ci } 164bf215546Sopenharmony_ci else { 165bf215546Sopenharmony_ci pipe_resource_reference(&cur_image_view->resource, NULL); 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci cur_image_view->uav_index = -1; 168bf215546Sopenharmony_ci } 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci /* unbind trailing slots */ 172bf215546Sopenharmony_ci for (unsigned j = 0, i = start + num; j < unbind_num_trailing_slots; 173bf215546Sopenharmony_ci i++, j++) { 174bf215546Sopenharmony_ci struct svga_image_view *cur_image_view = &svga->curr.image_views[shader][i]; 175bf215546Sopenharmony_ci cur_image_view->uav_index = -1; 176bf215546Sopenharmony_ci pipe_resource_reference(&cur_image_view->resource, NULL); 177bf215546Sopenharmony_ci } 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci /* number of bound image views */ 180bf215546Sopenharmony_ci svga->curr.num_image_views[shader] = start + num; 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci#ifdef DEBUG 183bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "%s: num_image_views=%d start=%d num=%d unbind_num_trailing_slots=%d\n", 184bf215546Sopenharmony_ci __FUNCTION__, svga->curr.num_image_views[shader], start, num, 185bf215546Sopenharmony_ci unbind_num_trailing_slots); 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci for (unsigned i = start; i < start + num; i++) { 188bf215546Sopenharmony_ci struct svga_image_view *cur_image_view = &svga->curr.image_views[shader][i]; 189bf215546Sopenharmony_ci struct pipe_image_view *img = &cur_image_view->desc; 190bf215546Sopenharmony_ci if (img->resource) { 191bf215546Sopenharmony_ci if (img->resource->target == PIPE_BUFFER) { 192bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, " buffer res=0x%x format=%d offset=%d size=%d\n", 193bf215546Sopenharmony_ci img->resource, img->format, 194bf215546Sopenharmony_ci img->u.buf.offset, img->u.buf.size); 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci else { 197bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, 198bf215546Sopenharmony_ci " texture res=0x%x format=%d first_layer=%d last_layer=%d level=%d\n", 199bf215546Sopenharmony_ci img->resource, img->format, img->u.tex.first_layer, 200bf215546Sopenharmony_ci img->u.tex.last_layer, img->u.tex.level); 201bf215546Sopenharmony_ci } 202bf215546Sopenharmony_ci } 203bf215546Sopenharmony_ci else { 204bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, " res=NULL\n"); 205bf215546Sopenharmony_ci } 206bf215546Sopenharmony_ci } 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "\n"); 209bf215546Sopenharmony_ci#endif 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci /* purge any unused uav objects */ 212bf215546Sopenharmony_ci svga_destroy_uav(svga); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci svga->dirty |= SVGA_NEW_IMAGE_VIEW; 215bf215546Sopenharmony_ci} 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci/** 219bf215546Sopenharmony_ci * Initialize shader images gallium interface 220bf215546Sopenharmony_ci */ 221bf215546Sopenharmony_civoid 222bf215546Sopenharmony_cisvga_init_shader_image_functions(struct svga_context *svga) 223bf215546Sopenharmony_ci{ 224bf215546Sopenharmony_ci if (svga_have_gl43(svga)) { 225bf215546Sopenharmony_ci svga->pipe.set_shader_images = svga_set_shader_images; 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci /* Initialize shader image views */ 229bf215546Sopenharmony_ci for (unsigned shader = 0; shader < PIPE_SHADER_TYPES; ++shader) { 230bf215546Sopenharmony_ci struct svga_image_view *hw_image_views = 231bf215546Sopenharmony_ci &svga->state.hw_draw.image_views[shader][0]; 232bf215546Sopenharmony_ci struct svga_image_view *cur_image_views = 233bf215546Sopenharmony_ci &svga->curr.image_views[shader][0]; 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(svga->curr.image_views[shader]); 236bf215546Sopenharmony_ci i++, hw_image_views++, cur_image_views++) { 237bf215546Sopenharmony_ci hw_image_views->resource = NULL; 238bf215546Sopenharmony_ci cur_image_views->resource = NULL; 239bf215546Sopenharmony_ci } 240bf215546Sopenharmony_ci } 241bf215546Sopenharmony_ci memset(svga->state.hw_draw.num_image_views, 0, 242bf215546Sopenharmony_ci sizeof(svga->state.hw_draw.num_image_views)); 243bf215546Sopenharmony_ci} 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci/** 247bf215546Sopenharmony_ci * Cleanup shader image state 248bf215546Sopenharmony_ci */ 249bf215546Sopenharmony_civoid 250bf215546Sopenharmony_cisvga_cleanup_shader_image_state(struct svga_context *svga) 251bf215546Sopenharmony_ci{ 252bf215546Sopenharmony_ci if (!svga_have_gl43(svga)) 253bf215546Sopenharmony_ci return; 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci svga_destroy_uav(svga); 256bf215546Sopenharmony_ci} 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci/** 260bf215546Sopenharmony_ci * Validate shader image view resources to ensure any pending changes to 261bf215546Sopenharmony_ci * texture buffers are emitted before they are referenced in image views. 262bf215546Sopenharmony_ci * The helper function also rebinds the image view resources if the rebind flag 263bf215546Sopenharmony_ci * is specified. 264bf215546Sopenharmony_ci */ 265bf215546Sopenharmony_cienum pipe_error 266bf215546Sopenharmony_cisvga_validate_image_view_resources(struct svga_context *svga, 267bf215546Sopenharmony_ci unsigned count, 268bf215546Sopenharmony_ci struct svga_image_view *images, 269bf215546Sopenharmony_ci bool rebind) 270bf215546Sopenharmony_ci{ 271bf215546Sopenharmony_ci assert(svga_have_gl43(svga)); 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci struct svga_winsys_surface *surf; 274bf215546Sopenharmony_ci enum pipe_error ret; 275bf215546Sopenharmony_ci unsigned i; 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 278bf215546Sopenharmony_ci struct pipe_resource *res = images[i].resource; 279bf215546Sopenharmony_ci if (res) { 280bf215546Sopenharmony_ci assert(res == images[i].desc.resource); 281bf215546Sopenharmony_ci if (res->target == PIPE_BUFFER) { 282bf215546Sopenharmony_ci struct svga_buffer *sbuf = svga_buffer(res); 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci surf = svga_buffer_handle(svga, res, PIPE_BIND_SHADER_IMAGE); 285bf215546Sopenharmony_ci /* Mark buffer surface as RENDERED */ 286bf215546Sopenharmony_ci svga_set_buffer_rendered_to(sbuf->bufsurf); 287bf215546Sopenharmony_ci } else { 288bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(res); 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci surf = tex->handle; 291bf215546Sopenharmony_ci /* Mark texture as RENDERED */ 292bf215546Sopenharmony_ci svga_set_texture_rendered_to(tex); 293bf215546Sopenharmony_ci } 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci assert(surf); 296bf215546Sopenharmony_ci if (rebind) { 297bf215546Sopenharmony_ci ret = svga->swc->resource_rebind(svga->swc, surf, NULL, 298bf215546Sopenharmony_ci SVGA_RELOC_READ|SVGA_RELOC_WRITE); 299bf215546Sopenharmony_ci if (ret != PIPE_OK) 300bf215546Sopenharmony_ci return ret; 301bf215546Sopenharmony_ci } 302bf215546Sopenharmony_ci } 303bf215546Sopenharmony_ci } 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci return PIPE_OK; 306bf215546Sopenharmony_ci} 307