19f464c52Smaya/* 29f464c52Smaya * Copyright © 2017 Intel Corporation 39f464c52Smaya * 49f464c52Smaya * Permission is hereby granted, free of charge, to any person obtaining a 59f464c52Smaya * copy of this software and associated documentation files (the "Software"), 69f464c52Smaya * to deal in the Software without restriction, including without limitation 79f464c52Smaya * the rights to use, copy, modify, merge, publish, distribute, sublicense, 89f464c52Smaya * and/or sell copies of the Software, and to permit persons to whom the 99f464c52Smaya * Software is furnished to do so, subject to the following conditions: 109f464c52Smaya * 119f464c52Smaya * The above copyright notice and this permission notice shall be included 129f464c52Smaya * in all copies or substantial portions of the Software. 139f464c52Smaya * 149f464c52Smaya * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 159f464c52Smaya * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 169f464c52Smaya * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 179f464c52Smaya * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 189f464c52Smaya * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 199f464c52Smaya * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 209f464c52Smaya * DEALINGS IN THE SOFTWARE. 219f464c52Smaya */ 229f464c52Smaya 239f464c52Smaya#include <stdio.h> 249f464c52Smaya#include <time.h> 259f464c52Smaya#include "pipe/p_defines.h" 269f464c52Smaya#include "pipe/p_state.h" 277ec681f3Smrg#include "util/debug.h" 289f464c52Smaya#include "util/ralloc.h" 299f464c52Smaya#include "util/u_inlines.h" 307ec681f3Smrg#include "util/format/u_format.h" 319f464c52Smaya#include "util/u_upload_mgr.h" 329f464c52Smaya#include "drm-uapi/i915_drm.h" 339f464c52Smaya#include "iris_context.h" 349f464c52Smaya#include "iris_resource.h" 359f464c52Smaya#include "iris_screen.h" 367ec681f3Smrg#include "common/intel_defines.h" 377ec681f3Smrg#include "common/intel_sample_positions.h" 389f464c52Smaya 399f464c52Smaya/** 407ec681f3Smrg * The pipe->set_debug_callback() driver hook. 419f464c52Smaya */ 427ec681f3Smrgstatic void 437ec681f3Smrgiris_set_debug_callback(struct pipe_context *ctx, 447ec681f3Smrg const struct pipe_debug_callback *cb) 459f464c52Smaya{ 467ec681f3Smrg struct iris_context *ice = (struct iris_context *)ctx; 477ec681f3Smrg struct iris_screen *screen = (struct iris_screen *)ctx->screen; 489f464c52Smaya 497ec681f3Smrg util_queue_finish(&screen->shader_compiler_queue); 509f464c52Smaya 517ec681f3Smrg if (cb) 527ec681f3Smrg ice->dbg = *cb; 537ec681f3Smrg else 547ec681f3Smrg memset(&ice->dbg, 0, sizeof(ice->dbg)); 559f464c52Smaya} 569f464c52Smaya 579f464c52Smaya/** 587ec681f3Smrg * Called from the batch module when it detects a GPU hang. 597ec681f3Smrg * 607ec681f3Smrg * In this case, we've lost our GEM context, and can't rely on any existing 617ec681f3Smrg * state on the GPU. We must mark everything dirty and wipe away any saved 627ec681f3Smrg * assumptions about the last known state of the GPU. 639f464c52Smaya */ 647ec681f3Smrgvoid 657ec681f3Smrgiris_lost_context_state(struct iris_batch *batch) 667ec681f3Smrg{ 677ec681f3Smrg struct iris_context *ice = batch->ice; 687ec681f3Smrg 697ec681f3Smrg if (batch->name == IRIS_BATCH_RENDER) { 707ec681f3Smrg batch->screen->vtbl.init_render_context(batch); 717ec681f3Smrg } else if (batch->name == IRIS_BATCH_COMPUTE) { 727ec681f3Smrg batch->screen->vtbl.init_compute_context(batch); 737ec681f3Smrg } else { 747ec681f3Smrg unreachable("unhandled batch reset"); 757ec681f3Smrg } 767ec681f3Smrg 777ec681f3Smrg ice->state.dirty = ~0ull; 787ec681f3Smrg ice->state.stage_dirty = ~0ull; 797ec681f3Smrg ice->state.current_hash_scale = 0; 807ec681f3Smrg memset(&ice->shaders.urb, 0, sizeof(ice->shaders.urb)); 817ec681f3Smrg memset(ice->state.last_block, 0, sizeof(ice->state.last_block)); 827ec681f3Smrg memset(ice->state.last_grid, 0, sizeof(ice->state.last_grid)); 837ec681f3Smrg batch->last_surface_base_address = ~0ull; 847ec681f3Smrg batch->last_aux_map_state = 0; 857ec681f3Smrg batch->screen->vtbl.lost_genx_state(ice, batch); 867ec681f3Smrg} 877ec681f3Smrg 887ec681f3Smrgstatic enum pipe_reset_status 897ec681f3Smrgiris_get_device_reset_status(struct pipe_context *ctx) 907ec681f3Smrg{ 917ec681f3Smrg struct iris_context *ice = (struct iris_context *)ctx; 927ec681f3Smrg 937ec681f3Smrg enum pipe_reset_status worst_reset = PIPE_NO_RESET; 947ec681f3Smrg 957ec681f3Smrg /* Check the reset status of each batch's hardware context, and take the 967ec681f3Smrg * worst status (if one was guilty, proclaim guilt). 977ec681f3Smrg */ 987ec681f3Smrg for (int i = 0; i < IRIS_BATCH_COUNT; i++) { 997ec681f3Smrg /* This will also recreate the hardware contexts as necessary, so any 1007ec681f3Smrg * future queries will show no resets. We only want to report once. 1017ec681f3Smrg */ 1027ec681f3Smrg enum pipe_reset_status batch_reset = 1037ec681f3Smrg iris_batch_check_for_reset(&ice->batches[i]); 1047ec681f3Smrg 1057ec681f3Smrg if (batch_reset == PIPE_NO_RESET) 1067ec681f3Smrg continue; 1077ec681f3Smrg 1087ec681f3Smrg if (worst_reset == PIPE_NO_RESET) { 1097ec681f3Smrg worst_reset = batch_reset; 1107ec681f3Smrg } else { 1117ec681f3Smrg /* GUILTY < INNOCENT < UNKNOWN */ 1127ec681f3Smrg worst_reset = MIN2(worst_reset, batch_reset); 1137ec681f3Smrg } 1147ec681f3Smrg } 1157ec681f3Smrg 1167ec681f3Smrg if (worst_reset != PIPE_NO_RESET && ice->reset.reset) 1177ec681f3Smrg ice->reset.reset(ice->reset.data, worst_reset); 1187ec681f3Smrg 1197ec681f3Smrg return worst_reset; 1207ec681f3Smrg} 1217ec681f3Smrg 1229f464c52Smayastatic void 1237ec681f3Smrgiris_set_device_reset_callback(struct pipe_context *ctx, 1247ec681f3Smrg const struct pipe_device_reset_callback *cb) 1259f464c52Smaya{ 1269f464c52Smaya struct iris_context *ice = (struct iris_context *)ctx; 1279f464c52Smaya 1289f464c52Smaya if (cb) 1297ec681f3Smrg ice->reset = *cb; 1309f464c52Smaya else 1317ec681f3Smrg memset(&ice->reset, 0, sizeof(ice->reset)); 1329f464c52Smaya} 1339f464c52Smaya 1349f464c52Smayastatic void 1359f464c52Smayairis_get_sample_position(struct pipe_context *ctx, 1369f464c52Smaya unsigned sample_count, 1379f464c52Smaya unsigned sample_index, 1389f464c52Smaya float *out_value) 1399f464c52Smaya{ 1409f464c52Smaya union { 1419f464c52Smaya struct { 1429f464c52Smaya float x[16]; 1439f464c52Smaya float y[16]; 1449f464c52Smaya } a; 1459f464c52Smaya struct { 1469f464c52Smaya float _0XOffset, _1XOffset, _2XOffset, _3XOffset, 1479f464c52Smaya _4XOffset, _5XOffset, _6XOffset, _7XOffset, 1489f464c52Smaya _8XOffset, _9XOffset, _10XOffset, _11XOffset, 1499f464c52Smaya _12XOffset, _13XOffset, _14XOffset, _15XOffset; 1509f464c52Smaya float _0YOffset, _1YOffset, _2YOffset, _3YOffset, 1519f464c52Smaya _4YOffset, _5YOffset, _6YOffset, _7YOffset, 1529f464c52Smaya _8YOffset, _9YOffset, _10YOffset, _11YOffset, 1539f464c52Smaya _12YOffset, _13YOffset, _14YOffset, _15YOffset; 1549f464c52Smaya } v; 1559f464c52Smaya } u; 1569f464c52Smaya switch (sample_count) { 1577ec681f3Smrg case 1: INTEL_SAMPLE_POS_1X(u.v._); break; 1587ec681f3Smrg case 2: INTEL_SAMPLE_POS_2X(u.v._); break; 1597ec681f3Smrg case 4: INTEL_SAMPLE_POS_4X(u.v._); break; 1607ec681f3Smrg case 8: INTEL_SAMPLE_POS_8X(u.v._); break; 1617ec681f3Smrg case 16: INTEL_SAMPLE_POS_16X(u.v._); break; 1629f464c52Smaya default: unreachable("invalid sample count"); 1639f464c52Smaya } 1649f464c52Smaya 1659f464c52Smaya out_value[0] = u.a.x[sample_index]; 1669f464c52Smaya out_value[1] = u.a.y[sample_index]; 1679f464c52Smaya} 1689f464c52Smaya 1697ec681f3Smrgstatic bool 1707ec681f3Smrgcreate_dirty_dmabuf_set(struct iris_context *ice) 1717ec681f3Smrg{ 1727ec681f3Smrg assert(ice->dirty_dmabufs == NULL); 1737ec681f3Smrg 1747ec681f3Smrg ice->dirty_dmabufs = _mesa_pointer_set_create(ice); 1757ec681f3Smrg return ice->dirty_dmabufs != NULL; 1767ec681f3Smrg} 1777ec681f3Smrg 1787ec681f3Smrgvoid 1797ec681f3Smrgiris_mark_dirty_dmabuf(struct iris_context *ice, 1807ec681f3Smrg struct pipe_resource *res) 1817ec681f3Smrg{ 1827ec681f3Smrg if (!_mesa_set_search(ice->dirty_dmabufs, res)) { 1837ec681f3Smrg _mesa_set_add(ice->dirty_dmabufs, res); 1847ec681f3Smrg pipe_reference(NULL, &res->reference); 1857ec681f3Smrg } 1867ec681f3Smrg} 1877ec681f3Smrg 1887ec681f3Smrgstatic void 1897ec681f3Smrgclear_dirty_dmabuf_set(struct iris_context *ice) 1907ec681f3Smrg{ 1917ec681f3Smrg set_foreach(ice->dirty_dmabufs, entry) { 1927ec681f3Smrg struct pipe_resource *res = (struct pipe_resource *)entry->key; 1937ec681f3Smrg if (pipe_reference(&res->reference, NULL)) 1947ec681f3Smrg res->screen->resource_destroy(res->screen, res); 1957ec681f3Smrg } 1967ec681f3Smrg 1977ec681f3Smrg _mesa_set_clear(ice->dirty_dmabufs, NULL); 1987ec681f3Smrg} 1997ec681f3Smrg 2007ec681f3Smrgvoid 2017ec681f3Smrgiris_flush_dirty_dmabufs(struct iris_context *ice) 2027ec681f3Smrg{ 2037ec681f3Smrg set_foreach(ice->dirty_dmabufs, entry) { 2047ec681f3Smrg struct pipe_resource *res = (struct pipe_resource *)entry->key; 2057ec681f3Smrg ice->ctx.flush_resource(&ice->ctx, res); 2067ec681f3Smrg } 2077ec681f3Smrg 2087ec681f3Smrg clear_dirty_dmabuf_set(ice); 2097ec681f3Smrg} 2107ec681f3Smrg 2117ec681f3Smrg 2129f464c52Smaya/** 2139f464c52Smaya * Destroy a context, freeing any associated memory. 2149f464c52Smaya */ 2157ec681f3Smrgvoid 2169f464c52Smayairis_destroy_context(struct pipe_context *ctx) 2179f464c52Smaya{ 2189f464c52Smaya struct iris_context *ice = (struct iris_context *)ctx; 2197ec681f3Smrg struct iris_screen *screen = (struct iris_screen *)ctx->screen; 2209f464c52Smaya 2219f464c52Smaya if (ctx->stream_uploader) 2229f464c52Smaya u_upload_destroy(ctx->stream_uploader); 2237ec681f3Smrg if (ctx->const_uploader) 2247ec681f3Smrg u_upload_destroy(ctx->const_uploader); 2257ec681f3Smrg 2267ec681f3Smrg clear_dirty_dmabuf_set(ice); 2277ec681f3Smrg 2287ec681f3Smrg screen->vtbl.destroy_state(ice); 2297ec681f3Smrg 2307ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(ice->shaders.scratch_surfs); i++) 2317ec681f3Smrg pipe_resource_reference(&ice->shaders.scratch_surfs[i].res, NULL); 2329f464c52Smaya 2339f464c52Smaya iris_destroy_program_cache(ice); 2349f464c52Smaya iris_destroy_border_color_pool(ice); 2357ec681f3Smrg if (screen->measure.config) 2367ec681f3Smrg iris_destroy_ctx_measure(ice); 2377ec681f3Smrg 2389f464c52Smaya u_upload_destroy(ice->state.surface_uploader); 2397ec681f3Smrg u_upload_destroy(ice->state.bindless_uploader); 2409f464c52Smaya u_upload_destroy(ice->state.dynamic_uploader); 2419f464c52Smaya u_upload_destroy(ice->query_buffer_uploader); 2429f464c52Smaya 2439f464c52Smaya iris_batch_free(&ice->batches[IRIS_BATCH_RENDER]); 2449f464c52Smaya iris_batch_free(&ice->batches[IRIS_BATCH_COMPUTE]); 2459f464c52Smaya iris_destroy_binder(&ice->state.binder); 2469f464c52Smaya 2477ec681f3Smrg slab_destroy_child(&ice->transfer_pool); 2487ec681f3Smrg slab_destroy_child(&ice->transfer_pool_unsync); 2497ec681f3Smrg 2509f464c52Smaya ralloc_free(ice); 2519f464c52Smaya} 2529f464c52Smaya 2539f464c52Smaya#define genX_call(devinfo, func, ...) \ 2547ec681f3Smrg switch ((devinfo)->verx10) { \ 2557ec681f3Smrg case 125: \ 2567ec681f3Smrg gfx125_##func(__VA_ARGS__); \ 2579f464c52Smaya break; \ 2587ec681f3Smrg case 120: \ 2597ec681f3Smrg gfx12_##func(__VA_ARGS__); \ 2609f464c52Smaya break; \ 2617ec681f3Smrg case 110: \ 2627ec681f3Smrg gfx11_##func(__VA_ARGS__); \ 2639f464c52Smaya break; \ 2647ec681f3Smrg case 90: \ 2657ec681f3Smrg gfx9_##func(__VA_ARGS__); \ 2667ec681f3Smrg break; \ 2677ec681f3Smrg case 80: \ 2687ec681f3Smrg gfx8_##func(__VA_ARGS__); \ 2699f464c52Smaya break; \ 2709f464c52Smaya default: \ 2719f464c52Smaya unreachable("Unknown hardware generation"); \ 2729f464c52Smaya } 2739f464c52Smaya 2749f464c52Smaya/** 2759f464c52Smaya * Create a context. 2769f464c52Smaya * 2779f464c52Smaya * This is where each context begins. 2789f464c52Smaya */ 2799f464c52Smayastruct pipe_context * 2809f464c52Smayairis_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags) 2819f464c52Smaya{ 2829f464c52Smaya struct iris_screen *screen = (struct iris_screen*)pscreen; 2837ec681f3Smrg const struct intel_device_info *devinfo = &screen->devinfo; 2849f464c52Smaya struct iris_context *ice = rzalloc(NULL, struct iris_context); 2859f464c52Smaya 2869f464c52Smaya if (!ice) 2879f464c52Smaya return NULL; 2889f464c52Smaya 2899f464c52Smaya struct pipe_context *ctx = &ice->ctx; 2909f464c52Smaya 2919f464c52Smaya ctx->screen = pscreen; 2929f464c52Smaya ctx->priv = priv; 2939f464c52Smaya 2949f464c52Smaya ctx->stream_uploader = u_upload_create_default(ctx); 2959f464c52Smaya if (!ctx->stream_uploader) { 2969f464c52Smaya free(ctx); 2979f464c52Smaya return NULL; 2989f464c52Smaya } 2997ec681f3Smrg ctx->const_uploader = u_upload_create(ctx, 1024 * 1024, 3007ec681f3Smrg PIPE_BIND_CONSTANT_BUFFER, 3017ec681f3Smrg PIPE_USAGE_IMMUTABLE, 3027ec681f3Smrg IRIS_RESOURCE_FLAG_DEVICE_MEM); 3037ec681f3Smrg if (!ctx->const_uploader) { 3047ec681f3Smrg u_upload_destroy(ctx->stream_uploader); 3057ec681f3Smrg free(ctx); 3067ec681f3Smrg return NULL; 3077ec681f3Smrg } 3087ec681f3Smrg 3097ec681f3Smrg if (!create_dirty_dmabuf_set(ice)) { 3107ec681f3Smrg ralloc_free(ice); 3117ec681f3Smrg return NULL; 3127ec681f3Smrg } 3139f464c52Smaya 3149f464c52Smaya ctx->destroy = iris_destroy_context; 3159f464c52Smaya ctx->set_debug_callback = iris_set_debug_callback; 3167ec681f3Smrg ctx->set_device_reset_callback = iris_set_device_reset_callback; 3177ec681f3Smrg ctx->get_device_reset_status = iris_get_device_reset_status; 3189f464c52Smaya ctx->get_sample_position = iris_get_sample_position; 3199f464c52Smaya 3209f464c52Smaya iris_init_context_fence_functions(ctx); 3219f464c52Smaya iris_init_blit_functions(ctx); 3229f464c52Smaya iris_init_clear_functions(ctx); 3239f464c52Smaya iris_init_program_functions(ctx); 3249f464c52Smaya iris_init_resource_functions(ctx); 3259f464c52Smaya iris_init_flush_functions(ctx); 3267ec681f3Smrg iris_init_perfquery_functions(ctx); 3279f464c52Smaya 3289f464c52Smaya iris_init_program_cache(ice); 3299f464c52Smaya iris_init_border_color_pool(ice); 3309f464c52Smaya iris_init_binder(ice); 3319f464c52Smaya 3329f464c52Smaya slab_create_child(&ice->transfer_pool, &screen->transfer_pool); 3337ec681f3Smrg slab_create_child(&ice->transfer_pool_unsync, &screen->transfer_pool); 3349f464c52Smaya 3359f464c52Smaya ice->state.surface_uploader = 3367ec681f3Smrg u_upload_create(ctx, 64 * 1024, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, 3377ec681f3Smrg IRIS_RESOURCE_FLAG_SURFACE_MEMZONE | 3387ec681f3Smrg IRIS_RESOURCE_FLAG_DEVICE_MEM); 3397ec681f3Smrg ice->state.bindless_uploader = 3407ec681f3Smrg u_upload_create(ctx, 64 * 1024, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, 3417ec681f3Smrg IRIS_RESOURCE_FLAG_BINDLESS_MEMZONE | 3427ec681f3Smrg IRIS_RESOURCE_FLAG_DEVICE_MEM); 3439f464c52Smaya ice->state.dynamic_uploader = 3447ec681f3Smrg u_upload_create(ctx, 64 * 1024, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, 3457ec681f3Smrg IRIS_RESOURCE_FLAG_DYNAMIC_MEMZONE | 3467ec681f3Smrg IRIS_RESOURCE_FLAG_DEVICE_MEM); 3479f464c52Smaya 3489f464c52Smaya ice->query_buffer_uploader = 3497ec681f3Smrg u_upload_create(ctx, 16 * 1024, PIPE_BIND_CUSTOM, PIPE_USAGE_STAGING, 3509f464c52Smaya 0); 3519f464c52Smaya 3529f464c52Smaya genX_call(devinfo, init_state, ice); 3539f464c52Smaya genX_call(devinfo, init_blorp, ice); 3547ec681f3Smrg genX_call(devinfo, init_query, ice); 3559f464c52Smaya 3569f464c52Smaya int priority = 0; 3579f464c52Smaya if (flags & PIPE_CONTEXT_HIGH_PRIORITY) 3587ec681f3Smrg priority = INTEL_CONTEXT_HIGH_PRIORITY; 3599f464c52Smaya if (flags & PIPE_CONTEXT_LOW_PRIORITY) 3607ec681f3Smrg priority = INTEL_CONTEXT_LOW_PRIORITY; 3617ec681f3Smrg 3627ec681f3Smrg if (INTEL_DEBUG(DEBUG_BATCH)) 3637ec681f3Smrg ice->state.sizes = _mesa_hash_table_u64_create(ice); 3649f464c52Smaya 3659f464c52Smaya for (int i = 0; i < IRIS_BATCH_COUNT; i++) { 3667ec681f3Smrg iris_init_batch(ice, (enum iris_batch_name) i, priority); 3679f464c52Smaya } 3689f464c52Smaya 3697ec681f3Smrg screen->vtbl.init_render_context(&ice->batches[IRIS_BATCH_RENDER]); 3707ec681f3Smrg screen->vtbl.init_compute_context(&ice->batches[IRIS_BATCH_COMPUTE]); 3717ec681f3Smrg 3727ec681f3Smrg if (!(flags & PIPE_CONTEXT_PREFER_THREADED)) 3737ec681f3Smrg return ctx; 3747ec681f3Smrg 3757ec681f3Smrg /* Clover doesn't support u_threaded_context */ 3767ec681f3Smrg if (flags & PIPE_CONTEXT_COMPUTE_ONLY) 3777ec681f3Smrg return ctx; 3789f464c52Smaya 3797ec681f3Smrg return threaded_context_create(ctx, &screen->transfer_pool, 3807ec681f3Smrg iris_replace_buffer_storage, 3817ec681f3Smrg NULL, /* TODO: asynchronous flushes? */ 3827ec681f3Smrg &ice->thrctx); 3839f464c52Smaya} 384