1/**************************************************************************** 2 * Copyright (C) 2015 Intel Corporation. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 ***************************************************************************/ 23 24#include "swr_context.h" 25#include "swr_memory.h" 26#include "swr_screen.h" 27#include "swr_resource.h" 28#include "swr_scratch.h" 29#include "swr_query.h" 30#include "swr_fence.h" 31 32#include "util/u_memory.h" 33#include "util/u_inlines.h" 34#include "util/u_format.h" 35#include "util/u_atomic.h" 36 37extern "C" { 38#include "util/u_transfer.h" 39#include "util/u_surface.h" 40} 41 42#include "api.h" 43#include "backend.h" 44 45static struct pipe_surface * 46swr_create_surface(struct pipe_context *pipe, 47 struct pipe_resource *pt, 48 const struct pipe_surface *surf_tmpl) 49{ 50 struct pipe_surface *ps; 51 52 ps = CALLOC_STRUCT(pipe_surface); 53 if (ps) { 54 pipe_reference_init(&ps->reference, 1); 55 pipe_resource_reference(&ps->texture, pt); 56 ps->context = pipe; 57 ps->format = surf_tmpl->format; 58 if (pt->target != PIPE_BUFFER) { 59 assert(surf_tmpl->u.tex.level <= pt->last_level); 60 ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); 61 ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); 62 ps->u.tex.level = surf_tmpl->u.tex.level; 63 ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; 64 ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; 65 } else { 66 /* setting width as number of elements should get us correct 67 * renderbuffer width */ 68 ps->width = surf_tmpl->u.buf.last_element 69 - surf_tmpl->u.buf.first_element + 1; 70 ps->height = pt->height0; 71 ps->u.buf.first_element = surf_tmpl->u.buf.first_element; 72 ps->u.buf.last_element = surf_tmpl->u.buf.last_element; 73 assert(ps->u.buf.first_element <= ps->u.buf.last_element); 74 assert(ps->u.buf.last_element < ps->width); 75 } 76 } 77 return ps; 78} 79 80static void 81swr_surface_destroy(struct pipe_context *pipe, struct pipe_surface *surf) 82{ 83 assert(surf->texture); 84 struct pipe_resource *resource = surf->texture; 85 86 /* If the resource has been drawn to, store tiles. */ 87 swr_store_dirty_resource(pipe, resource, SWR_TILE_RESOLVED); 88 89 pipe_resource_reference(&resource, NULL); 90 FREE(surf); 91} 92 93 94static void * 95swr_transfer_map(struct pipe_context *pipe, 96 struct pipe_resource *resource, 97 unsigned level, 98 unsigned usage, 99 const struct pipe_box *box, 100 struct pipe_transfer **transfer) 101{ 102 struct swr_screen *screen = swr_screen(pipe->screen); 103 struct swr_resource *spr = swr_resource(resource); 104 struct pipe_transfer *pt; 105 enum pipe_format format = resource->format; 106 107 assert(resource); 108 assert(level <= resource->last_level); 109 110 /* If mapping an attached rendertarget, store tiles to surface and set 111 * postStoreTileState to SWR_TILE_INVALID so tiles get reloaded on next use 112 * and nothing needs to be done at unmap. */ 113 swr_store_dirty_resource(pipe, resource, SWR_TILE_INVALID); 114 115 if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { 116 /* If resource is in use, finish fence before mapping. 117 * Unless requested not to block, then if not done return NULL map */ 118 if (usage & PIPE_TRANSFER_DONTBLOCK) { 119 if (swr_is_fence_pending(screen->flush_fence)) 120 return NULL; 121 } else { 122 if (spr->status) { 123 /* But, if there's no fence pending, submit one. 124 * XXX: Remove once draw timestamps are finished. */ 125 if (!swr_is_fence_pending(screen->flush_fence)) 126 swr_fence_submit(swr_context(pipe), screen->flush_fence); 127 128 swr_fence_finish(pipe->screen, NULL, screen->flush_fence, 0); 129 swr_resource_unused(resource); 130 } 131 } 132 } 133 134 pt = CALLOC_STRUCT(pipe_transfer); 135 if (!pt) 136 return NULL; 137 pipe_resource_reference(&pt->resource, resource); 138 pt->usage = (pipe_transfer_usage)usage; 139 pt->level = level; 140 pt->box = *box; 141 pt->stride = spr->swr.pitch; 142 pt->layer_stride = spr->swr.qpitch * spr->swr.pitch; 143 144 /* if we're mapping the depth/stencil, copy in stencil for the section 145 * being read in 146 */ 147 if (usage & PIPE_TRANSFER_READ && spr->has_depth && spr->has_stencil) { 148 size_t zbase, sbase; 149 for (int z = box->z; z < box->z + box->depth; z++) { 150 zbase = (z * spr->swr.qpitch + box->y) * spr->swr.pitch + 151 spr->mip_offsets[level]; 152 sbase = (z * spr->secondary.qpitch + box->y) * spr->secondary.pitch + 153 spr->secondary_mip_offsets[level]; 154 for (int y = box->y; y < box->y + box->height; y++) { 155 if (spr->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT) { 156 for (int x = box->x; x < box->x + box->width; x++) 157 spr->swr.pBaseAddress[zbase + 4 * x + 3] = 158 spr->secondary.pBaseAddress[sbase + x]; 159 } else if (spr->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) { 160 for (int x = box->x; x < box->x + box->width; x++) 161 spr->swr.pBaseAddress[zbase + 8 * x + 4] = 162 spr->secondary.pBaseAddress[sbase + x]; 163 } 164 zbase += spr->swr.pitch; 165 sbase += spr->secondary.pitch; 166 } 167 } 168 } 169 170 unsigned offset = box->z * pt->layer_stride + 171 util_format_get_nblocksy(format, box->y) * pt->stride + 172 util_format_get_stride(format, box->x); 173 174 *transfer = pt; 175 176 return spr->swr.pBaseAddress + offset + spr->mip_offsets[level]; 177} 178 179static void 180swr_transfer_flush_region(struct pipe_context *pipe, 181 struct pipe_transfer *transfer, 182 const struct pipe_box *flush_box) 183{ 184 assert(transfer->resource); 185 assert(transfer->usage & PIPE_TRANSFER_WRITE); 186 187 struct swr_resource *spr = swr_resource(transfer->resource); 188 if (!spr->has_depth || !spr->has_stencil) 189 return; 190 191 size_t zbase, sbase; 192 struct pipe_box box = *flush_box; 193 box.x += transfer->box.x; 194 box.y += transfer->box.y; 195 box.z += transfer->box.z; 196 for (int z = box.z; z < box.z + box.depth; z++) { 197 zbase = (z * spr->swr.qpitch + box.y) * spr->swr.pitch + 198 spr->mip_offsets[transfer->level]; 199 sbase = (z * spr->secondary.qpitch + box.y) * spr->secondary.pitch + 200 spr->secondary_mip_offsets[transfer->level]; 201 for (int y = box.y; y < box.y + box.height; y++) { 202 if (spr->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT) { 203 for (int x = box.x; x < box.x + box.width; x++) 204 spr->secondary.pBaseAddress[sbase + x] = 205 spr->swr.pBaseAddress[zbase + 4 * x + 3]; 206 } else if (spr->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) { 207 for (int x = box.x; x < box.x + box.width; x++) 208 spr->secondary.pBaseAddress[sbase + x] = 209 spr->swr.pBaseAddress[zbase + 8 * x + 4]; 210 } 211 zbase += spr->swr.pitch; 212 sbase += spr->secondary.pitch; 213 } 214 } 215} 216 217static void 218swr_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) 219{ 220 assert(transfer->resource); 221 222 struct swr_resource *spr = swr_resource(transfer->resource); 223 /* if we're mapping the depth/stencil, copy in stencil for the section 224 * being written out 225 */ 226 if (transfer->usage & PIPE_TRANSFER_WRITE && 227 !(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT) && 228 spr->has_depth && spr->has_stencil) { 229 struct pipe_box box; 230 u_box_3d(0, 0, 0, transfer->box.width, transfer->box.height, 231 transfer->box.depth, &box); 232 swr_transfer_flush_region(pipe, transfer, &box); 233 } 234 235 pipe_resource_reference(&transfer->resource, NULL); 236 FREE(transfer); 237} 238 239 240static void 241swr_resource_copy(struct pipe_context *pipe, 242 struct pipe_resource *dst, 243 unsigned dst_level, 244 unsigned dstx, 245 unsigned dsty, 246 unsigned dstz, 247 struct pipe_resource *src, 248 unsigned src_level, 249 const struct pipe_box *src_box) 250{ 251 struct swr_screen *screen = swr_screen(pipe->screen); 252 253 /* If either the src or dst is a renderTarget, store tiles before copy */ 254 swr_store_dirty_resource(pipe, src, SWR_TILE_RESOLVED); 255 swr_store_dirty_resource(pipe, dst, SWR_TILE_RESOLVED); 256 257 swr_fence_finish(pipe->screen, NULL, screen->flush_fence, 0); 258 swr_resource_unused(src); 259 swr_resource_unused(dst); 260 261 if ((dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) 262 || (dst->target != PIPE_BUFFER && src->target != PIPE_BUFFER)) { 263 util_resource_copy_region( 264 pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); 265 return; 266 } 267 268 debug_printf("unhandled swr_resource_copy\n"); 269} 270 271 272static void 273swr_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) 274{ 275 struct swr_context *ctx = swr_context(pipe); 276 struct pipe_blit_info info = *blit_info; 277 278 if (blit_info->render_condition_enable && !swr_check_render_cond(pipe)) 279 return; 280 281 if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 282 && !util_format_is_depth_or_stencil(info.src.resource->format) 283 && !util_format_is_pure_integer(info.src.resource->format)) { 284 debug_printf("swr: color resolve unimplemented\n"); 285 return; 286 } 287 288 if (util_try_blit_via_copy_region(pipe, &info)) { 289 return; /* done */ 290 } 291 292 if (info.mask & PIPE_MASK_S) { 293 debug_printf("swr: cannot blit stencil, skipping\n"); 294 info.mask &= ~PIPE_MASK_S; 295 } 296 297 if (!util_blitter_is_blit_supported(ctx->blitter, &info)) { 298 debug_printf("swr: blit unsupported %s -> %s\n", 299 util_format_short_name(info.src.resource->format), 300 util_format_short_name(info.dst.resource->format)); 301 return; 302 } 303 304 if (ctx->active_queries) { 305 SwrEnableStatsFE(ctx->swrContext, FALSE); 306 SwrEnableStatsBE(ctx->swrContext, FALSE); 307 } 308 309 util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertex_buffer); 310 util_blitter_save_vertex_elements(ctx->blitter, (void *)ctx->velems); 311 util_blitter_save_vertex_shader(ctx->blitter, (void *)ctx->vs); 312 /*util_blitter_save_geometry_shader(ctx->blitter, (void*)ctx->gs);*/ 313 util_blitter_save_so_targets( 314 ctx->blitter, 315 ctx->num_so_targets, 316 (struct pipe_stream_output_target **)ctx->so_targets); 317 util_blitter_save_rasterizer(ctx->blitter, (void *)ctx->rasterizer); 318 util_blitter_save_viewport(ctx->blitter, &ctx->viewport); 319 util_blitter_save_scissor(ctx->blitter, &ctx->scissor); 320 util_blitter_save_fragment_shader(ctx->blitter, ctx->fs); 321 util_blitter_save_blend(ctx->blitter, (void *)ctx->blend); 322 util_blitter_save_depth_stencil_alpha(ctx->blitter, 323 (void *)ctx->depth_stencil); 324 util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref); 325 util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask); 326 util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer); 327 util_blitter_save_fragment_sampler_states( 328 ctx->blitter, 329 ctx->num_samplers[PIPE_SHADER_FRAGMENT], 330 (void **)ctx->samplers[PIPE_SHADER_FRAGMENT]); 331 util_blitter_save_fragment_sampler_views( 332 ctx->blitter, 333 ctx->num_sampler_views[PIPE_SHADER_FRAGMENT], 334 ctx->sampler_views[PIPE_SHADER_FRAGMENT]); 335 util_blitter_save_render_condition(ctx->blitter, 336 ctx->render_cond_query, 337 ctx->render_cond_cond, 338 ctx->render_cond_mode); 339 340 util_blitter_blit(ctx->blitter, &info); 341 342 if (ctx->active_queries) { 343 SwrEnableStatsFE(ctx->swrContext, TRUE); 344 SwrEnableStatsBE(ctx->swrContext, TRUE); 345 } 346} 347 348 349static void 350swr_destroy(struct pipe_context *pipe) 351{ 352 struct swr_context *ctx = swr_context(pipe); 353 struct swr_screen *screen = swr_screen(pipe->screen); 354 355 if (ctx->blitter) 356 util_blitter_destroy(ctx->blitter); 357 358 for (unsigned i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { 359 pipe_surface_reference(&ctx->framebuffer.cbufs[i], NULL); 360 } 361 362 pipe_surface_reference(&ctx->framebuffer.zsbuf, NULL); 363 364 for (unsigned i = 0; i < ARRAY_SIZE(ctx->sampler_views[0]); i++) { 365 pipe_sampler_view_reference(&ctx->sampler_views[PIPE_SHADER_FRAGMENT][i], NULL); 366 } 367 368 for (unsigned i = 0; i < ARRAY_SIZE(ctx->sampler_views[0]); i++) { 369 pipe_sampler_view_reference(&ctx->sampler_views[PIPE_SHADER_VERTEX][i], NULL); 370 } 371 372 /* Idle core after destroying buffer resources, but before deleting 373 * context. Destroying resources has potentially called StoreTiles.*/ 374 SwrWaitForIdle(ctx->swrContext); 375 376 if (ctx->swrContext) 377 SwrDestroyContext(ctx->swrContext); 378 379 delete ctx->blendJIT; 380 381 swr_destroy_scratch_buffers(ctx); 382 383 /* Only update screen->pipe if current context is being destroyed */ 384 assert(screen); 385 if (screen->pipe == pipe) 386 screen->pipe = NULL; 387 388 FREE(ctx); 389} 390 391 392static void 393swr_render_condition(struct pipe_context *pipe, 394 struct pipe_query *query, 395 boolean condition, 396 uint mode) 397{ 398 struct swr_context *ctx = swr_context(pipe); 399 400 ctx->render_cond_query = query; 401 ctx->render_cond_mode = mode; 402 ctx->render_cond_cond = condition; 403} 404 405static void 406swr_UpdateStats(HANDLE hPrivateContext, const SWR_STATS *pStats) 407{ 408 swr_draw_context *pDC = (swr_draw_context*)hPrivateContext; 409 410 if (!pDC) 411 return; 412 413 struct swr_query_result *pqr = (struct swr_query_result *)pDC->pStats; 414 415 SWR_STATS *pSwrStats = &pqr->core; 416 417 pSwrStats->DepthPassCount += pStats->DepthPassCount; 418 pSwrStats->PsInvocations += pStats->PsInvocations; 419 pSwrStats->CsInvocations += pStats->CsInvocations; 420} 421 422static void 423swr_UpdateStatsFE(HANDLE hPrivateContext, const SWR_STATS_FE *pStats) 424{ 425 swr_draw_context *pDC = (swr_draw_context*)hPrivateContext; 426 427 if (!pDC) 428 return; 429 430 struct swr_query_result *pqr = (struct swr_query_result *)pDC->pStats; 431 432 SWR_STATS_FE *pSwrStats = &pqr->coreFE; 433 p_atomic_add(&pSwrStats->IaVertices, pStats->IaVertices); 434 p_atomic_add(&pSwrStats->IaPrimitives, pStats->IaPrimitives); 435 p_atomic_add(&pSwrStats->VsInvocations, pStats->VsInvocations); 436 p_atomic_add(&pSwrStats->HsInvocations, pStats->HsInvocations); 437 p_atomic_add(&pSwrStats->DsInvocations, pStats->DsInvocations); 438 p_atomic_add(&pSwrStats->GsInvocations, pStats->GsInvocations); 439 p_atomic_add(&pSwrStats->CInvocations, pStats->CInvocations); 440 p_atomic_add(&pSwrStats->CPrimitives, pStats->CPrimitives); 441 p_atomic_add(&pSwrStats->GsPrimitives, pStats->GsPrimitives); 442 443 for (unsigned i = 0; i < 4; i++) { 444 p_atomic_add(&pSwrStats->SoPrimStorageNeeded[i], 445 pStats->SoPrimStorageNeeded[i]); 446 p_atomic_add(&pSwrStats->SoNumPrimsWritten[i], 447 pStats->SoNumPrimsWritten[i]); 448 } 449} 450 451struct pipe_context * 452swr_create_context(struct pipe_screen *p_screen, void *priv, unsigned flags) 453{ 454 struct swr_context *ctx = CALLOC_STRUCT(swr_context); 455 ctx->blendJIT = 456 new std::unordered_map<BLEND_COMPILE_STATE, PFN_BLEND_JIT_FUNC>; 457 458 SWR_CREATECONTEXT_INFO createInfo; 459 memset(&createInfo, 0, sizeof(createInfo)); 460 createInfo.privateStateSize = sizeof(swr_draw_context); 461 createInfo.pfnLoadTile = swr_LoadHotTile; 462 createInfo.pfnStoreTile = swr_StoreHotTile; 463 createInfo.pfnClearTile = swr_StoreHotTileClear; 464 createInfo.pfnUpdateStats = swr_UpdateStats; 465 createInfo.pfnUpdateStatsFE = swr_UpdateStatsFE; 466 ctx->swrContext = SwrCreateContext(&createInfo); 467 468 /* Init Load/Store/ClearTiles Tables */ 469 swr_InitMemoryModule(); 470 471 InitBackendFuncTables(); 472 473 if (ctx->swrContext == NULL) 474 goto fail; 475 476 ctx->pipe.screen = p_screen; 477 ctx->pipe.destroy = swr_destroy; 478 ctx->pipe.priv = priv; 479 ctx->pipe.create_surface = swr_create_surface; 480 ctx->pipe.surface_destroy = swr_surface_destroy; 481 ctx->pipe.transfer_map = swr_transfer_map; 482 ctx->pipe.transfer_unmap = swr_transfer_unmap; 483 ctx->pipe.transfer_flush_region = swr_transfer_flush_region; 484 485 ctx->pipe.buffer_subdata = u_default_buffer_subdata; 486 ctx->pipe.texture_subdata = u_default_texture_subdata; 487 488 ctx->pipe.resource_copy_region = swr_resource_copy; 489 ctx->pipe.render_condition = swr_render_condition; 490 491 swr_state_init(&ctx->pipe); 492 swr_clear_init(&ctx->pipe); 493 swr_draw_init(&ctx->pipe); 494 swr_query_init(&ctx->pipe); 495 496 ctx->pipe.blit = swr_blit; 497 ctx->blitter = util_blitter_create(&ctx->pipe); 498 if (!ctx->blitter) 499 goto fail; 500 501 swr_init_scratch_buffers(ctx); 502 503 return &ctx->pipe; 504 505fail: 506 /* Should really validate the init steps and fail gracefully */ 507 swr_destroy(&ctx->pipe); 508 return NULL; 509} 510