1 /********************************************************** 2 * Copyright 2008-2009 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 "svga_cmd.h" 27 28 #include "pipe/p_state.h" 29 #include "pipe/p_defines.h" 30 #include "util/u_inlines.h" 31 #include "os/os_thread.h" 32 #include "util/u_math.h" 33 #include "util/u_memory.h" 34 #include "util/u_resource.h" 35 36 #include "svga_context.h" 37 #include "svga_screen.h" 38 #include "svga_resource_buffer.h" 39 #include "svga_resource_buffer_upload.h" 40 #include "svga_winsys.h" 41 #include "svga_debug.h" 42 43 44 /** 45 * Vertex and index buffers need hardware backing. Constant buffers 46 * do not. No other types of buffers currently supported. 47 */ 48 static inline boolean 49 svga_buffer_needs_hw_storage(unsigned usage) 50 { 51 return (usage & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER | 52 PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_STREAM_OUTPUT)) != 0; 53 } 54 55 56 /** 57 * Create a buffer transfer. 58 * 59 * Unlike texture DMAs (which are written immediately to the command buffer and 60 * therefore inherently serialized with other context operations), for buffers 61 * we try to coalesce multiple range mappings (i.e, multiple calls to this 62 * function) into a single DMA command, for better efficiency in command 63 * processing. This means we need to exercise extra care here to ensure that 64 * the end result is exactly the same as if one DMA was used for every mapped 65 * range. 66 */ 67 static void * 68 svga_buffer_transfer_map(struct pipe_context *pipe, 69 struct pipe_resource *resource, 70 unsigned level, 71 unsigned usage, 72 const struct pipe_box *box, 73 struct pipe_transfer **ptransfer) 74 { 75 struct svga_context *svga = svga_context(pipe); 76 struct svga_screen *ss = svga_screen(pipe->screen); 77 struct svga_buffer *sbuf = svga_buffer(resource); 78 struct pipe_transfer *transfer; 79 uint8_t *map = NULL; 80 int64_t begin = svga_get_time(svga); 81 82 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_BUFFERTRANSFERMAP); 83 84 assert(box->y == 0); 85 assert(box->z == 0); 86 assert(box->height == 1); 87 assert(box->depth == 1); 88 89 transfer = MALLOC_STRUCT(pipe_transfer); 90 if (!transfer) { 91 goto done; 92 } 93 94 transfer->resource = resource; 95 transfer->level = level; 96 transfer->usage = usage; 97 transfer->box = *box; 98 transfer->stride = 0; 99 transfer->layer_stride = 0; 100 101 if (usage & PIPE_TRANSFER_WRITE) { 102 /* If we write to the buffer for any reason, free any saved translated 103 * vertices. 104 */ 105 pipe_resource_reference(&sbuf->translated_indices.buffer, NULL); 106 } 107 108 if ((usage & PIPE_TRANSFER_READ) && sbuf->dirty) { 109 enum pipe_error ret; 110 111 /* Host-side buffers can only be dirtied with vgpu10 features 112 * (streamout and buffer copy). 113 */ 114 assert(svga_have_vgpu10(svga)); 115 116 if (!sbuf->user) { 117 (void) svga_buffer_handle(svga, resource); 118 } 119 120 if (sbuf->dma.pending > 0) { 121 svga_buffer_upload_flush(svga, sbuf); 122 svga_context_finish(svga); 123 } 124 125 assert(sbuf->handle); 126 127 ret = SVGA3D_vgpu10_ReadbackSubResource(svga->swc, sbuf->handle, 0); 128 if (ret != PIPE_OK) { 129 svga_context_flush(svga, NULL); 130 ret = SVGA3D_vgpu10_ReadbackSubResource(svga->swc, sbuf->handle, 0); 131 assert(ret == PIPE_OK); 132 } 133 134 svga->hud.num_readbacks++; 135 136 svga_context_finish(svga); 137 138 sbuf->dirty = FALSE; 139 } 140 141 if (usage & PIPE_TRANSFER_WRITE) { 142 if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { 143 /* 144 * Flush any pending primitives, finish writing any pending DMA 145 * commands, and tell the host to discard the buffer contents on 146 * the next DMA operation. 147 */ 148 149 svga_hwtnl_flush_buffer(svga, resource); 150 151 if (sbuf->dma.pending) { 152 svga_buffer_upload_flush(svga, sbuf); 153 154 /* 155 * Instead of flushing the context command buffer, simply discard 156 * the current hwbuf, and start a new one. 157 * With GB objects, the map operation takes care of this 158 * if passed the PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE flag, 159 * and the old backing store is busy. 160 */ 161 162 if (!svga_have_gb_objects(svga)) 163 svga_buffer_destroy_hw_storage(ss, sbuf); 164 } 165 166 sbuf->map.num_ranges = 0; 167 sbuf->dma.flags.discard = TRUE; 168 } 169 170 if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) { 171 if (!sbuf->map.num_ranges) { 172 /* 173 * No pending ranges to upload so far, so we can tell the host to 174 * not synchronize on the next DMA command. 175 */ 176 177 sbuf->dma.flags.unsynchronized = TRUE; 178 } 179 } else { 180 /* 181 * Synchronizing, so flush any pending primitives, finish writing any 182 * pending DMA command, and ensure the next DMA will be done in order. 183 */ 184 185 svga_hwtnl_flush_buffer(svga, resource); 186 187 if (sbuf->dma.pending) { 188 svga_buffer_upload_flush(svga, sbuf); 189 190 if (svga_buffer_has_hw_storage(sbuf)) { 191 /* 192 * We have a pending DMA upload from a hardware buffer, therefore 193 * we need to ensure that the host finishes processing that DMA 194 * command before the state tracker can start overwriting the 195 * hardware buffer. 196 * 197 * XXX: This could be avoided by tying the hardware buffer to 198 * the transfer (just as done with textures), which would allow 199 * overlapping DMAs commands to be queued on the same context 200 * buffer. However, due to the likelihood of software vertex 201 * processing, it is more convenient to hold on to the hardware 202 * buffer, allowing to quickly access the contents from the CPU 203 * without having to do a DMA download from the host. 204 */ 205 206 if (usage & PIPE_TRANSFER_DONTBLOCK) { 207 /* 208 * Flushing the command buffer here will most likely cause 209 * the map of the hwbuf below to block, so preemptively 210 * return NULL here if DONTBLOCK is set to prevent unnecessary 211 * command buffer flushes. 212 */ 213 214 FREE(transfer); 215 goto done; 216 } 217 218 svga_context_flush(svga, NULL); 219 } 220 } 221 222 sbuf->dma.flags.unsynchronized = FALSE; 223 } 224 } 225 226 if (!sbuf->swbuf && !svga_buffer_has_hw_storage(sbuf)) { 227 if (svga_buffer_create_hw_storage(ss, sbuf) != PIPE_OK) { 228 /* 229 * We can't create a hardware buffer big enough, so create a malloc 230 * buffer instead. 231 */ 232 if (0) { 233 debug_printf("%s: failed to allocate %u KB of DMA, " 234 "splitting DMA transfers\n", 235 __FUNCTION__, 236 (sbuf->b.b.width0 + 1023)/1024); 237 } 238 239 sbuf->swbuf = align_malloc(sbuf->b.b.width0, 16); 240 if (!sbuf->swbuf) { 241 FREE(transfer); 242 goto done; 243 } 244 } 245 } 246 247 if (sbuf->swbuf) { 248 /* User/malloc buffer */ 249 map = sbuf->swbuf; 250 } 251 else if (svga_buffer_has_hw_storage(sbuf)) { 252 boolean retry; 253 254 map = svga_buffer_hw_storage_map(svga, sbuf, transfer->usage, &retry); 255 if (map == NULL && retry) { 256 /* 257 * At this point, svga_buffer_get_transfer() has already 258 * hit the DISCARD_WHOLE_RESOURCE path and flushed HWTNL 259 * for this buffer. 260 */ 261 svga_context_flush(svga, NULL); 262 map = svga_buffer_hw_storage_map(svga, sbuf, transfer->usage, &retry); 263 } 264 } 265 else { 266 map = NULL; 267 } 268 269 if (map) { 270 ++sbuf->map.count; 271 map += transfer->box.x; 272 *ptransfer = transfer; 273 } else { 274 FREE(transfer); 275 } 276 277 svga->hud.map_buffer_time += (svga_get_time(svga) - begin); 278 279 done: 280 SVGA_STATS_TIME_POP(svga_sws(svga)); 281 return map; 282 } 283 284 285 static void 286 svga_buffer_transfer_flush_region( struct pipe_context *pipe, 287 struct pipe_transfer *transfer, 288 const struct pipe_box *box) 289 { 290 struct svga_screen *ss = svga_screen(pipe->screen); 291 struct svga_buffer *sbuf = svga_buffer(transfer->resource); 292 293 unsigned offset = transfer->box.x + box->x; 294 unsigned length = box->width; 295 296 assert(transfer->usage & PIPE_TRANSFER_WRITE); 297 assert(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT); 298 299 pipe_mutex_lock(ss->swc_mutex); 300 svga_buffer_add_range(sbuf, offset, offset + length); 301 pipe_mutex_unlock(ss->swc_mutex); 302 } 303 304 305 static void 306 svga_buffer_transfer_unmap( struct pipe_context *pipe, 307 struct pipe_transfer *transfer ) 308 { 309 struct svga_screen *ss = svga_screen(pipe->screen); 310 struct svga_context *svga = svga_context(pipe); 311 struct svga_buffer *sbuf = svga_buffer(transfer->resource); 312 313 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_BUFFERTRANSFERUNMAP); 314 315 pipe_mutex_lock(ss->swc_mutex); 316 317 assert(sbuf->map.count); 318 if (sbuf->map.count) { 319 --sbuf->map.count; 320 } 321 322 if (svga_buffer_has_hw_storage(sbuf)) { 323 svga_buffer_hw_storage_unmap(svga, sbuf); 324 } 325 326 if (transfer->usage & PIPE_TRANSFER_WRITE) { 327 if (!(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) { 328 /* 329 * Mapped range not flushed explicitly, so flush the whole buffer, 330 * and tell the host to discard the contents when processing the DMA 331 * command. 332 */ 333 334 SVGA_DBG(DEBUG_DMA, "flushing the whole buffer\n"); 335 336 sbuf->dma.flags.discard = TRUE; 337 338 svga_buffer_add_range(sbuf, 0, sbuf->b.b.width0); 339 } 340 } 341 342 pipe_mutex_unlock(ss->swc_mutex); 343 FREE(transfer); 344 SVGA_STATS_TIME_POP(svga_sws(svga)); 345 } 346 347 348 static void 349 svga_buffer_destroy( struct pipe_screen *screen, 350 struct pipe_resource *buf ) 351 { 352 struct svga_screen *ss = svga_screen(screen); 353 struct svga_buffer *sbuf = svga_buffer( buf ); 354 355 assert(!p_atomic_read(&buf->reference.count)); 356 357 assert(!sbuf->dma.pending); 358 359 if (sbuf->handle) 360 svga_buffer_destroy_host_surface(ss, sbuf); 361 362 if (sbuf->uploaded.buffer) 363 pipe_resource_reference(&sbuf->uploaded.buffer, NULL); 364 365 if (sbuf->hwbuf) 366 svga_buffer_destroy_hw_storage(ss, sbuf); 367 368 if (sbuf->swbuf && !sbuf->user) 369 align_free(sbuf->swbuf); 370 371 pipe_resource_reference(&sbuf->translated_indices.buffer, NULL); 372 373 ss->hud.total_resource_bytes -= sbuf->size; 374 assert(ss->hud.num_resources > 0); 375 if (ss->hud.num_resources > 0) 376 ss->hud.num_resources--; 377 378 FREE(sbuf); 379 } 380 381 382 struct u_resource_vtbl svga_buffer_vtbl = 383 { 384 u_default_resource_get_handle, /* get_handle */ 385 svga_buffer_destroy, /* resource_destroy */ 386 svga_buffer_transfer_map, /* transfer_map */ 387 svga_buffer_transfer_flush_region, /* transfer_flush_region */ 388 svga_buffer_transfer_unmap, /* transfer_unmap */ 389 }; 390 391 392 393 struct pipe_resource * 394 svga_buffer_create(struct pipe_screen *screen, 395 const struct pipe_resource *template) 396 { 397 struct svga_screen *ss = svga_screen(screen); 398 struct svga_buffer *sbuf; 399 400 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATEBUFFER); 401 402 sbuf = CALLOC_STRUCT(svga_buffer); 403 if (!sbuf) 404 goto error1; 405 406 sbuf->b.b = *template; 407 sbuf->b.vtbl = &svga_buffer_vtbl; 408 pipe_reference_init(&sbuf->b.b.reference, 1); 409 sbuf->b.b.screen = screen; 410 sbuf->bind_flags = template->bind; 411 412 if (template->bind & PIPE_BIND_CONSTANT_BUFFER) { 413 /* Constant buffers can only have the PIPE_BIND_CONSTANT_BUFFER 414 * flag set. 415 */ 416 if (ss->sws->have_vgpu10) { 417 sbuf->bind_flags = PIPE_BIND_CONSTANT_BUFFER; 418 419 /* Constant buffer size needs to be in multiples of 16. */ 420 sbuf->b.b.width0 = align(sbuf->b.b.width0, 16); 421 } 422 } 423 424 if (svga_buffer_needs_hw_storage(template->bind)) { 425 426 /* If the buffer will be used for vertex/index/stream data, set all 427 * the flags so that the buffer will be accepted for all those uses. 428 * Note that the PIPE_BIND_ flags we get from the state tracker are 429 * just a hint about how the buffer may be used. And OpenGL buffer 430 * object may be used for many different things. 431 */ 432 if (!(template->bind & PIPE_BIND_CONSTANT_BUFFER)) { 433 /* Not a constant buffer. The buffer may be used for vertex data, 434 * indexes or stream-out. 435 */ 436 sbuf->bind_flags |= (PIPE_BIND_VERTEX_BUFFER | 437 PIPE_BIND_INDEX_BUFFER); 438 if (ss->sws->have_vgpu10) 439 sbuf->bind_flags |= PIPE_BIND_STREAM_OUTPUT; 440 } 441 442 if (svga_buffer_create_host_surface(ss, sbuf) != PIPE_OK) 443 goto error2; 444 } 445 else { 446 sbuf->swbuf = align_malloc(sbuf->b.b.width0, 64); 447 if (!sbuf->swbuf) 448 goto error2; 449 } 450 451 debug_reference(&sbuf->b.b.reference, 452 (debug_reference_descriptor)debug_describe_resource, 0); 453 454 sbuf->size = util_resource_size(&sbuf->b.b); 455 ss->hud.total_resource_bytes += sbuf->size; 456 457 ss->hud.num_resources++; 458 SVGA_STATS_TIME_POP(ss->sws); 459 460 return &sbuf->b.b; 461 462 error2: 463 FREE(sbuf); 464 error1: 465 SVGA_STATS_TIME_POP(ss->sws); 466 return NULL; 467 } 468 469 470 struct pipe_resource * 471 svga_user_buffer_create(struct pipe_screen *screen, 472 void *ptr, 473 unsigned bytes, 474 unsigned bind) 475 { 476 struct svga_buffer *sbuf; 477 struct svga_screen *ss = svga_screen(screen); 478 479 sbuf = CALLOC_STRUCT(svga_buffer); 480 if (!sbuf) 481 goto no_sbuf; 482 483 pipe_reference_init(&sbuf->b.b.reference, 1); 484 sbuf->b.vtbl = &svga_buffer_vtbl; 485 sbuf->b.b.screen = screen; 486 sbuf->b.b.format = PIPE_FORMAT_R8_UNORM; /* ?? */ 487 sbuf->b.b.usage = PIPE_USAGE_IMMUTABLE; 488 sbuf->b.b.bind = bind; 489 sbuf->b.b.width0 = bytes; 490 sbuf->b.b.height0 = 1; 491 sbuf->b.b.depth0 = 1; 492 sbuf->b.b.array_size = 1; 493 494 sbuf->bind_flags = bind; 495 sbuf->swbuf = ptr; 496 sbuf->user = TRUE; 497 498 debug_reference(&sbuf->b.b.reference, 499 (debug_reference_descriptor)debug_describe_resource, 0); 500 501 ss->hud.num_resources++; 502 503 return &sbuf->b.b; 504 505 no_sbuf: 506 return NULL; 507 } 508 509 510 511