Path: blob/21.2-virgl/src/gallium/drivers/iris/iris_context.c
4565 views
/*1* Copyright © 2017 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included11* in all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS14* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER17* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING18* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER19* DEALINGS IN THE SOFTWARE.20*/2122#include <stdio.h>23#include <time.h>24#include "pipe/p_defines.h"25#include "pipe/p_state.h"26#include "util/debug.h"27#include "util/ralloc.h"28#include "util/u_inlines.h"29#include "util/format/u_format.h"30#include "util/u_upload_mgr.h"31#include "drm-uapi/i915_drm.h"32#include "iris_context.h"33#include "iris_resource.h"34#include "iris_screen.h"35#include "common/intel_defines.h"36#include "common/intel_sample_positions.h"3738/**39* The pipe->set_debug_callback() driver hook.40*/41static void42iris_set_debug_callback(struct pipe_context *ctx,43const struct pipe_debug_callback *cb)44{45struct iris_context *ice = (struct iris_context *)ctx;4647if (cb)48ice->dbg = *cb;49else50memset(&ice->dbg, 0, sizeof(ice->dbg));51}5253/**54* Called from the batch module when it detects a GPU hang.55*56* In this case, we've lost our GEM context, and can't rely on any existing57* state on the GPU. We must mark everything dirty and wipe away any saved58* assumptions about the last known state of the GPU.59*/60void61iris_lost_context_state(struct iris_batch *batch)62{63struct iris_context *ice = batch->ice;6465if (batch->name == IRIS_BATCH_RENDER) {66batch->screen->vtbl.init_render_context(batch);67} else if (batch->name == IRIS_BATCH_COMPUTE) {68batch->screen->vtbl.init_compute_context(batch);69} else {70unreachable("unhandled batch reset");71}7273ice->state.dirty = ~0ull;74ice->state.stage_dirty = ~0ull;75ice->state.current_hash_scale = 0;76memset(&ice->shaders.urb, 0, sizeof(ice->shaders.urb));77memset(ice->state.last_block, 0, sizeof(ice->state.last_block));78memset(ice->state.last_grid, 0, sizeof(ice->state.last_grid));79batch->last_surface_base_address = ~0ull;80batch->last_aux_map_state = 0;81batch->screen->vtbl.lost_genx_state(ice, batch);82}8384static enum pipe_reset_status85iris_get_device_reset_status(struct pipe_context *ctx)86{87struct iris_context *ice = (struct iris_context *)ctx;8889enum pipe_reset_status worst_reset = PIPE_NO_RESET;9091/* Check the reset status of each batch's hardware context, and take the92* worst status (if one was guilty, proclaim guilt).93*/94for (int i = 0; i < IRIS_BATCH_COUNT; i++) {95/* This will also recreate the hardware contexts as necessary, so any96* future queries will show no resets. We only want to report once.97*/98enum pipe_reset_status batch_reset =99iris_batch_check_for_reset(&ice->batches[i]);100101if (batch_reset == PIPE_NO_RESET)102continue;103104if (worst_reset == PIPE_NO_RESET) {105worst_reset = batch_reset;106} else {107/* GUILTY < INNOCENT < UNKNOWN */108worst_reset = MIN2(worst_reset, batch_reset);109}110}111112if (worst_reset != PIPE_NO_RESET && ice->reset.reset)113ice->reset.reset(ice->reset.data, worst_reset);114115return worst_reset;116}117118static void119iris_set_device_reset_callback(struct pipe_context *ctx,120const struct pipe_device_reset_callback *cb)121{122struct iris_context *ice = (struct iris_context *)ctx;123124if (cb)125ice->reset = *cb;126else127memset(&ice->reset, 0, sizeof(ice->reset));128}129130static void131iris_get_sample_position(struct pipe_context *ctx,132unsigned sample_count,133unsigned sample_index,134float *out_value)135{136union {137struct {138float x[16];139float y[16];140} a;141struct {142float _0XOffset, _1XOffset, _2XOffset, _3XOffset,143_4XOffset, _5XOffset, _6XOffset, _7XOffset,144_8XOffset, _9XOffset, _10XOffset, _11XOffset,145_12XOffset, _13XOffset, _14XOffset, _15XOffset;146float _0YOffset, _1YOffset, _2YOffset, _3YOffset,147_4YOffset, _5YOffset, _6YOffset, _7YOffset,148_8YOffset, _9YOffset, _10YOffset, _11YOffset,149_12YOffset, _13YOffset, _14YOffset, _15YOffset;150} v;151} u;152switch (sample_count) {153case 1: INTEL_SAMPLE_POS_1X(u.v._); break;154case 2: INTEL_SAMPLE_POS_2X(u.v._); break;155case 4: INTEL_SAMPLE_POS_4X(u.v._); break;156case 8: INTEL_SAMPLE_POS_8X(u.v._); break;157case 16: INTEL_SAMPLE_POS_16X(u.v._); break;158default: unreachable("invalid sample count");159}160161out_value[0] = u.a.x[sample_index];162out_value[1] = u.a.y[sample_index];163}164165static bool166create_dirty_dmabuf_set(struct iris_context *ice)167{168assert(ice->dirty_dmabufs == NULL);169170ice->dirty_dmabufs = _mesa_pointer_set_create(ice);171return ice->dirty_dmabufs != NULL;172}173174void175iris_mark_dirty_dmabuf(struct iris_context *ice,176struct pipe_resource *res)177{178if (!_mesa_set_search(ice->dirty_dmabufs, res)) {179_mesa_set_add(ice->dirty_dmabufs, res);180pipe_reference(NULL, &res->reference);181}182}183184static void185clear_dirty_dmabuf_set(struct iris_context *ice)186{187set_foreach(ice->dirty_dmabufs, entry) {188struct pipe_resource *res = (struct pipe_resource *)entry->key;189if (pipe_reference(&res->reference, NULL))190res->screen->resource_destroy(res->screen, res);191}192193_mesa_set_clear(ice->dirty_dmabufs, NULL);194}195196void197iris_flush_dirty_dmabufs(struct iris_context *ice)198{199set_foreach(ice->dirty_dmabufs, entry) {200struct pipe_resource *res = (struct pipe_resource *)entry->key;201ice->ctx.flush_resource(&ice->ctx, res);202}203204clear_dirty_dmabuf_set(ice);205}206207208/**209* Destroy a context, freeing any associated memory.210*/211static void212iris_destroy_context(struct pipe_context *ctx)213{214struct iris_context *ice = (struct iris_context *)ctx;215struct iris_screen *screen = (struct iris_screen *)ctx->screen;216217if (ctx->stream_uploader)218u_upload_destroy(ctx->stream_uploader);219if (ctx->const_uploader)220u_upload_destroy(ctx->const_uploader);221222clear_dirty_dmabuf_set(ice);223224screen->vtbl.destroy_state(ice);225226for (unsigned i = 0; i < ARRAY_SIZE(ice->shaders.scratch_surfs); i++)227pipe_resource_reference(&ice->shaders.scratch_surfs[i].res, NULL);228229iris_destroy_program_cache(ice);230iris_destroy_border_color_pool(ice);231if (screen->measure.config)232iris_destroy_ctx_measure(ice);233234u_upload_destroy(ice->state.surface_uploader);235u_upload_destroy(ice->state.bindless_uploader);236u_upload_destroy(ice->state.dynamic_uploader);237u_upload_destroy(ice->query_buffer_uploader);238239iris_batch_free(&ice->batches[IRIS_BATCH_RENDER]);240iris_batch_free(&ice->batches[IRIS_BATCH_COMPUTE]);241iris_destroy_binder(&ice->state.binder);242243slab_destroy_child(&ice->transfer_pool);244slab_destroy_child(&ice->transfer_pool_unsync);245246ralloc_free(ice);247}248249#define genX_call(devinfo, func, ...) \250switch ((devinfo)->verx10) { \251case 125: \252gfx125_##func(__VA_ARGS__); \253break; \254case 120: \255gfx12_##func(__VA_ARGS__); \256break; \257case 110: \258gfx11_##func(__VA_ARGS__); \259break; \260case 90: \261gfx9_##func(__VA_ARGS__); \262break; \263case 80: \264gfx8_##func(__VA_ARGS__); \265break; \266default: \267unreachable("Unknown hardware generation"); \268}269270/**271* Create a context.272*273* This is where each context begins.274*/275struct pipe_context *276iris_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags)277{278struct iris_screen *screen = (struct iris_screen*)pscreen;279const struct intel_device_info *devinfo = &screen->devinfo;280struct iris_context *ice = rzalloc(NULL, struct iris_context);281282if (!ice)283return NULL;284285struct pipe_context *ctx = &ice->ctx;286287ctx->screen = pscreen;288ctx->priv = priv;289290ctx->stream_uploader = u_upload_create_default(ctx);291if (!ctx->stream_uploader) {292free(ctx);293return NULL;294}295ctx->const_uploader = u_upload_create(ctx, 1024 * 1024,296PIPE_BIND_CONSTANT_BUFFER,297PIPE_USAGE_IMMUTABLE,298IRIS_RESOURCE_FLAG_DEVICE_MEM);299if (!ctx->const_uploader) {300u_upload_destroy(ctx->stream_uploader);301free(ctx);302return NULL;303}304305if (!create_dirty_dmabuf_set(ice)) {306ralloc_free(ice);307return NULL;308}309310ctx->destroy = iris_destroy_context;311ctx->set_debug_callback = iris_set_debug_callback;312ctx->set_device_reset_callback = iris_set_device_reset_callback;313ctx->get_device_reset_status = iris_get_device_reset_status;314ctx->get_sample_position = iris_get_sample_position;315316iris_init_context_fence_functions(ctx);317iris_init_blit_functions(ctx);318iris_init_clear_functions(ctx);319iris_init_program_functions(ctx);320iris_init_resource_functions(ctx);321iris_init_flush_functions(ctx);322iris_init_perfquery_functions(ctx);323324iris_init_program_cache(ice);325iris_init_border_color_pool(ice);326iris_init_binder(ice);327328slab_create_child(&ice->transfer_pool, &screen->transfer_pool);329slab_create_child(&ice->transfer_pool_unsync, &screen->transfer_pool);330331ice->state.surface_uploader =332u_upload_create(ctx, 64 * 1024, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE,333IRIS_RESOURCE_FLAG_SURFACE_MEMZONE |334IRIS_RESOURCE_FLAG_DEVICE_MEM);335ice->state.bindless_uploader =336u_upload_create(ctx, 64 * 1024, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE,337IRIS_RESOURCE_FLAG_BINDLESS_MEMZONE |338IRIS_RESOURCE_FLAG_DEVICE_MEM);339ice->state.dynamic_uploader =340u_upload_create(ctx, 64 * 1024, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE,341IRIS_RESOURCE_FLAG_DYNAMIC_MEMZONE |342IRIS_RESOURCE_FLAG_DEVICE_MEM);343344ice->query_buffer_uploader =345u_upload_create(ctx, 16 * 1024, PIPE_BIND_CUSTOM, PIPE_USAGE_STAGING,3460);347348genX_call(devinfo, init_state, ice);349genX_call(devinfo, init_blorp, ice);350genX_call(devinfo, init_query, ice);351352int priority = 0;353if (flags & PIPE_CONTEXT_HIGH_PRIORITY)354priority = INTEL_CONTEXT_HIGH_PRIORITY;355if (flags & PIPE_CONTEXT_LOW_PRIORITY)356priority = INTEL_CONTEXT_LOW_PRIORITY;357358if (INTEL_DEBUG & DEBUG_BATCH)359ice->state.sizes = _mesa_hash_table_u64_create(ice);360361for (int i = 0; i < IRIS_BATCH_COUNT; i++) {362iris_init_batch(ice, (enum iris_batch_name) i, priority);363}364365screen->vtbl.init_render_context(&ice->batches[IRIS_BATCH_RENDER]);366screen->vtbl.init_compute_context(&ice->batches[IRIS_BATCH_COMPUTE]);367368if (!(flags & PIPE_CONTEXT_PREFER_THREADED))369return ctx;370371/* Clover doesn't support u_threaded_context */372if (flags & PIPE_CONTEXT_COMPUTE_ONLY)373return ctx;374375return threaded_context_create(ctx, &screen->transfer_pool,376iris_replace_buffer_storage,377NULL, /* TODO: asynchronous flushes? */378NULL,379false,380&ice->thrctx);381}382383384