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