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 buffer 46bf215546Sopenharmony_ci */ 47bf215546Sopenharmony_ciSVGA3dUAViewId 48bf215546Sopenharmony_cisvga_create_uav_buffer(struct svga_context *svga, 49bf215546Sopenharmony_ci const struct pipe_shader_buffer *buf, 50bf215546Sopenharmony_ci SVGA3dSurfaceFormat format, 51bf215546Sopenharmony_ci SVGA3dUABufferFlags bufFlag) 52bf215546Sopenharmony_ci{ 53bf215546Sopenharmony_ci SVGA3dUAViewDesc desc; 54bf215546Sopenharmony_ci unsigned uaViewId; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci assert(buf); 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci /* If there is not one defined, create one. */ 59bf215546Sopenharmony_ci memset(&desc, 0, sizeof(desc)); 60bf215546Sopenharmony_ci desc.buffer.firstElement = buf->buffer_offset / sizeof(uint32); 61bf215546Sopenharmony_ci desc.buffer.numElements = buf->buffer_size / sizeof(uint32); 62bf215546Sopenharmony_ci desc.buffer.flags = bufFlag; 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci uaViewId = svga_create_uav(svga, &desc, format, 65bf215546Sopenharmony_ci SVGA3D_RESOURCE_BUFFER, 66bf215546Sopenharmony_ci svga_buffer_handle(svga, buf->buffer, 67bf215546Sopenharmony_ci PIPE_BIND_SHADER_BUFFER)); 68bf215546Sopenharmony_ci if (uaViewId == SVGA3D_INVALID_ID) 69bf215546Sopenharmony_ci return uaViewId; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "%s: resource=0x%x uaViewId=%d\n", 72bf215546Sopenharmony_ci __FUNCTION__, buf->buffer, uaViewId); 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci /* Mark this buffer as a uav bound buffer */ 75bf215546Sopenharmony_ci struct svga_buffer *sbuf = svga_buffer(buf->buffer); 76bf215546Sopenharmony_ci sbuf->uav = TRUE; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci return uaViewId; 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci/** 83bf215546Sopenharmony_ci * Set shader buffers. 84bf215546Sopenharmony_ci */ 85bf215546Sopenharmony_cistatic void 86bf215546Sopenharmony_cisvga_set_shader_buffers(struct pipe_context *pipe, 87bf215546Sopenharmony_ci enum pipe_shader_type shader, 88bf215546Sopenharmony_ci unsigned start, unsigned num, 89bf215546Sopenharmony_ci const struct pipe_shader_buffer *buffers, 90bf215546Sopenharmony_ci unsigned writeable_bitmask) 91bf215546Sopenharmony_ci{ 92bf215546Sopenharmony_ci struct svga_context *svga = svga_context(pipe); 93bf215546Sopenharmony_ci const struct pipe_shader_buffer *buf; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci assert(svga_have_gl43(svga)); 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci assert(start + num <= SVGA_MAX_SHADER_BUFFERS); 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci#ifdef DEBUG 100bf215546Sopenharmony_ci const struct pipe_shader_buffer *b = buffers; 101bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "%s: shader=%d start=%d num=%d ", 102bf215546Sopenharmony_ci __FUNCTION__, shader, start, num); 103bf215546Sopenharmony_ci if (buffers) { 104bf215546Sopenharmony_ci for (unsigned i = 0; i < num; i++, b++) { 105bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, " 0x%x ", b); 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci } 108bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "\n"); 109bf215546Sopenharmony_ci#endif 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci buf = buffers; 112bf215546Sopenharmony_ci if (buffers) { 113bf215546Sopenharmony_ci int last_buffer = -1; 114bf215546Sopenharmony_ci for (unsigned i = start; i < start + num; i++, buf++) { 115bf215546Sopenharmony_ci struct svga_shader_buffer *cbuf = &svga->curr.shader_buffers[shader][i]; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (buf && buf->buffer) { 118bf215546Sopenharmony_ci cbuf->desc = *buf; 119bf215546Sopenharmony_ci pipe_resource_reference(&cbuf->resource, buf->buffer); 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci /* Mark the last bound shader buffer */ 122bf215546Sopenharmony_ci last_buffer = i; 123bf215546Sopenharmony_ci } 124bf215546Sopenharmony_ci else { 125bf215546Sopenharmony_ci cbuf->desc.buffer = NULL; 126bf215546Sopenharmony_ci pipe_resource_reference(&cbuf->resource, NULL); 127bf215546Sopenharmony_ci } 128bf215546Sopenharmony_ci cbuf->uav_index = -1; 129bf215546Sopenharmony_ci } 130bf215546Sopenharmony_ci svga->curr.num_shader_buffers[shader] = 131bf215546Sopenharmony_ci MAX2(svga->curr.num_shader_buffers[shader], last_buffer + 1); 132bf215546Sopenharmony_ci } 133bf215546Sopenharmony_ci else { 134bf215546Sopenharmony_ci for (unsigned i = start; i < start + num; i++) { 135bf215546Sopenharmony_ci struct svga_shader_buffer *cbuf = &svga->curr.shader_buffers[shader][i]; 136bf215546Sopenharmony_ci cbuf->desc.buffer = NULL; 137bf215546Sopenharmony_ci cbuf->uav_index = -1; 138bf215546Sopenharmony_ci pipe_resource_reference(&cbuf->resource, NULL); 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci if ((start + num) >= svga->curr.num_shader_buffers[shader]) 141bf215546Sopenharmony_ci svga->curr.num_shader_buffers[shader] = start; 142bf215546Sopenharmony_ci } 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci#ifdef DEBUG 145bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, 146bf215546Sopenharmony_ci "%s: current num_shader_buffers=%d start=%d num=%d buffers=", 147bf215546Sopenharmony_ci __FUNCTION__, svga->curr.num_shader_buffers[shader], 148bf215546Sopenharmony_ci start, num); 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci for (unsigned i = start; i < start + num; i++) { 151bf215546Sopenharmony_ci struct svga_shader_buffer *cbuf = &svga->curr.shader_buffers[shader][i]; 152bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, " 0x%x ", cbuf->desc.buffer); 153bf215546Sopenharmony_ci } 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "\n"); 156bf215546Sopenharmony_ci#endif 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci /* purge any unused uav objects */ 159bf215546Sopenharmony_ci svga_destroy_uav(svga); 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci svga->dirty |= SVGA_NEW_SHADER_BUFFER; 162bf215546Sopenharmony_ci} 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci/** 166bf215546Sopenharmony_ci * Set HW atomic buffers. 167bf215546Sopenharmony_ci */ 168bf215546Sopenharmony_cistatic void 169bf215546Sopenharmony_cisvga_set_hw_atomic_buffers(struct pipe_context *pipe, 170bf215546Sopenharmony_ci unsigned start, unsigned num, 171bf215546Sopenharmony_ci const struct pipe_shader_buffer *buffers) 172bf215546Sopenharmony_ci{ 173bf215546Sopenharmony_ci struct svga_context *svga = svga_context(pipe); 174bf215546Sopenharmony_ci const struct pipe_shader_buffer *buf = buffers; 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci assert(svga_have_gl43(svga)); 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci assert(start + num <= SVGA_MAX_ATOMIC_BUFFERS); 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci#ifdef DEBUG 181bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "%s: start=%d num=%d \n", __FUNCTION__, start, num); 182bf215546Sopenharmony_ci#endif 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci buf = buffers; 185bf215546Sopenharmony_ci if (buffers) { 186bf215546Sopenharmony_ci int last_buffer = -1; 187bf215546Sopenharmony_ci for (unsigned i = start; i < start + num; i++, buf++) { 188bf215546Sopenharmony_ci struct svga_shader_buffer *cbuf = &svga->curr.atomic_buffers[i]; 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci if (buf && buf->buffer) { 191bf215546Sopenharmony_ci cbuf->desc = *buf; 192bf215546Sopenharmony_ci pipe_resource_reference(&cbuf->resource, buf->buffer); 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci last_buffer = i; 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci /* Mark the buffer as uav buffer so that a readback will 197bf215546Sopenharmony_ci * be done at each read transfer. We can't rely on the 198bf215546Sopenharmony_ci * dirty bit because it is reset after each read, but 199bf215546Sopenharmony_ci * the uav buffer can be updated at each draw. 200bf215546Sopenharmony_ci */ 201bf215546Sopenharmony_ci struct svga_buffer *sbuf = svga_buffer(cbuf->desc.buffer); 202bf215546Sopenharmony_ci sbuf->uav = TRUE; 203bf215546Sopenharmony_ci } 204bf215546Sopenharmony_ci else { 205bf215546Sopenharmony_ci cbuf->desc.buffer = NULL; 206bf215546Sopenharmony_ci pipe_resource_reference(&cbuf->resource, NULL); 207bf215546Sopenharmony_ci } 208bf215546Sopenharmony_ci cbuf->uav_index = -1; 209bf215546Sopenharmony_ci } 210bf215546Sopenharmony_ci svga->curr.num_atomic_buffers = MAX2(svga->curr.num_atomic_buffers, 211bf215546Sopenharmony_ci last_buffer + 1); 212bf215546Sopenharmony_ci } 213bf215546Sopenharmony_ci else { 214bf215546Sopenharmony_ci for (unsigned i = start; i < start + num; i++) { 215bf215546Sopenharmony_ci struct svga_shader_buffer *cbuf = &svga->curr.atomic_buffers[i]; 216bf215546Sopenharmony_ci cbuf->desc.buffer = NULL; 217bf215546Sopenharmony_ci cbuf->uav_index = -1; 218bf215546Sopenharmony_ci pipe_resource_reference(&cbuf->resource, NULL); 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci if ((start + num) >= svga->curr.num_atomic_buffers) 221bf215546Sopenharmony_ci svga->curr.num_atomic_buffers = start; 222bf215546Sopenharmony_ci } 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci#ifdef DEBUG 225bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "%s: current num_atomic_buffers=%d start=%d num=%d ", 226bf215546Sopenharmony_ci __FUNCTION__, svga->curr.num_atomic_buffers, 227bf215546Sopenharmony_ci start, num); 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci for (unsigned i = start; i < start + num; i++) { 230bf215546Sopenharmony_ci struct svga_shader_buffer *cbuf = &svga->curr.atomic_buffers[i]; 231bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, " 0x%x ", cbuf->desc.buffer); 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "\n"); 235bf215546Sopenharmony_ci#endif 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci /* purge any unused uav objects */ 238bf215546Sopenharmony_ci svga_destroy_uav(svga); 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci svga->dirty |= SVGA_NEW_SHADER_BUFFER; 241bf215546Sopenharmony_ci} 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci/** 245bf215546Sopenharmony_ci * Initialize shader images gallium interface 246bf215546Sopenharmony_ci */ 247bf215546Sopenharmony_civoid 248bf215546Sopenharmony_cisvga_init_shader_buffer_functions(struct svga_context *svga) 249bf215546Sopenharmony_ci{ 250bf215546Sopenharmony_ci if (!svga_have_gl43(svga)) 251bf215546Sopenharmony_ci return; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci svga->pipe.set_shader_buffers = svga_set_shader_buffers; 254bf215546Sopenharmony_ci svga->pipe.set_hw_atomic_buffers = svga_set_hw_atomic_buffers; 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci /* Initialize shader buffers */ 257bf215546Sopenharmony_ci for (unsigned shader = 0; shader < PIPE_SHADER_TYPES; ++shader) { 258bf215546Sopenharmony_ci struct svga_shader_buffer *hw_buf = 259bf215546Sopenharmony_ci &svga->state.hw_draw.shader_buffers[shader][0]; 260bf215546Sopenharmony_ci struct svga_shader_buffer *cur_buf = 261bf215546Sopenharmony_ci &svga->curr.shader_buffers[shader][0]; 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci /* Initialize uaViewId to SVGA3D_INVALID_ID for current shader buffers 264bf215546Sopenharmony_ci * and shader buffers in hw state to avoid unintentional unbinding of 265bf215546Sopenharmony_ci * shader buffers with uaViewId 0. 266bf215546Sopenharmony_ci */ 267bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(svga->curr.shader_buffers[shader]); 268bf215546Sopenharmony_ci i++, hw_buf++, cur_buf++) { 269bf215546Sopenharmony_ci hw_buf->resource = NULL; 270bf215546Sopenharmony_ci hw_buf->uav_index = -1; 271bf215546Sopenharmony_ci cur_buf->desc.buffer = NULL; 272bf215546Sopenharmony_ci cur_buf->resource = NULL; 273bf215546Sopenharmony_ci cur_buf->uav_index = -1; 274bf215546Sopenharmony_ci } 275bf215546Sopenharmony_ci } 276bf215546Sopenharmony_ci memset(svga->state.hw_draw.num_shader_buffers, 0, 277bf215546Sopenharmony_ci sizeof(svga->state.hw_draw.num_shader_buffers)); 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci /* Initialize atomic buffers */ 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci /* Initialize uaViewId to SVGA3D_INVALID_ID for current atomic buffers 282bf215546Sopenharmony_ci * and atomic buffers in hw state to avoid unintentional unbinding of 283bf215546Sopenharmony_ci * shader buffer with uaViewId 0. 284bf215546Sopenharmony_ci */ 285bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(svga->state.hw_draw.atomic_buffers); i++) { 286bf215546Sopenharmony_ci svga->curr.atomic_buffers[i].resource = NULL; 287bf215546Sopenharmony_ci svga->curr.atomic_buffers[i].uav_index = -1; 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci svga->state.hw_draw.num_atomic_buffers = 0; 290bf215546Sopenharmony_ci} 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci/** 294bf215546Sopenharmony_ci * Cleanup shader image state 295bf215546Sopenharmony_ci */ 296bf215546Sopenharmony_civoid 297bf215546Sopenharmony_cisvga_cleanup_shader_buffer_state(struct svga_context *svga) 298bf215546Sopenharmony_ci{ 299bf215546Sopenharmony_ci if (!svga_have_gl43(svga)) 300bf215546Sopenharmony_ci return; 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci svga_destroy_uav(svga); 303bf215546Sopenharmony_ci} 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci/** 307bf215546Sopenharmony_ci * Validate shader buffer resources to ensure any pending changes to the 308bf215546Sopenharmony_ci * buffers are emitted before they are referenced. 309bf215546Sopenharmony_ci * The helper function also rebinds the buffer resources if the rebind flag 310bf215546Sopenharmony_ci * is specified. 311bf215546Sopenharmony_ci */ 312bf215546Sopenharmony_cienum pipe_error 313bf215546Sopenharmony_cisvga_validate_shader_buffer_resources(struct svga_context *svga, 314bf215546Sopenharmony_ci unsigned count, 315bf215546Sopenharmony_ci struct svga_shader_buffer *bufs, 316bf215546Sopenharmony_ci bool rebind) 317bf215546Sopenharmony_ci{ 318bf215546Sopenharmony_ci assert(svga_have_gl43(svga)); 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci struct svga_winsys_surface *surf; 321bf215546Sopenharmony_ci enum pipe_error ret; 322bf215546Sopenharmony_ci unsigned i; 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 325bf215546Sopenharmony_ci if (bufs[i].resource) { 326bf215546Sopenharmony_ci assert(bufs[i].resource == bufs[i].desc.buffer); 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci struct svga_buffer *sbuf = svga_buffer(bufs[i].resource); 329bf215546Sopenharmony_ci surf = svga_buffer_handle(svga, bufs[i].desc.buffer, 330bf215546Sopenharmony_ci PIPE_BIND_SHADER_BUFFER); 331bf215546Sopenharmony_ci assert(surf); 332bf215546Sopenharmony_ci if (rebind) { 333bf215546Sopenharmony_ci ret = svga->swc->resource_rebind(svga->swc, surf, NULL, 334bf215546Sopenharmony_ci SVGA_RELOC_READ|SVGA_RELOC_WRITE); 335bf215546Sopenharmony_ci if (ret != PIPE_OK) 336bf215546Sopenharmony_ci return ret; 337bf215546Sopenharmony_ci } 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci /* Mark buffer as RENDERED */ 340bf215546Sopenharmony_ci svga_set_buffer_rendered_to(sbuf->bufsurf); 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci return PIPE_OK; 345bf215546Sopenharmony_ci} 346