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