1/* 2 * Copyright © 2021 Intel Corporation 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 "iris_batch.h" 25#include "iris_context.h" 26#include "iris_utrace.h" 27 28#include "util/u_trace_gallium.h" 29 30#include "ds/intel_driver_ds.h" 31 32#ifdef MAJOR_IN_MKDEV 33#include <sys/mkdev.h> 34#endif 35#ifdef MAJOR_IN_SYSMACROS 36#include <sys/sysmacros.h> 37#endif 38#include <sys/types.h> 39#include <sys/stat.h> 40#include <unistd.h> 41 42static void 43iris_utrace_record_ts(struct u_trace *trace, void *cs, 44 void *timestamps, unsigned idx, 45 bool end_of_pipe) 46{ 47 struct iris_batch *batch = container_of(trace, struct iris_batch, trace); 48 struct iris_resource *res = (void *) timestamps; 49 struct iris_bo *bo = res->bo; 50 51 iris_use_pinned_bo(batch, bo, true, IRIS_DOMAIN_NONE); 52 53 if (end_of_pipe) { 54 iris_emit_pipe_control_write(batch, "query: pipelined snapshot write", 55 PIPE_CONTROL_WRITE_TIMESTAMP, 56 bo, idx * sizeof(uint64_t), 0ull); 57 } else { 58 batch->screen->vtbl.store_register_mem64(batch, 59 0x2358, 60 bo, idx * sizeof(uint64_t), 61 false); 62 } 63} 64 65static uint64_t 66iris_utrace_read_ts(struct u_trace_context *utctx, 67 void *timestamps, unsigned idx, void *flush_data) 68{ 69 struct iris_context *ice = 70 container_of(utctx, struct iris_context, ds.trace_context); 71 struct pipe_context *ctx = &ice->ctx; 72 struct iris_screen *screen = (struct iris_screen *)ctx->screen; 73 struct iris_resource *res = (void *) timestamps; 74 struct iris_bo *bo = res->bo; 75 76 if (idx == 0) 77 iris_bo_wait_rendering(bo); 78 79 uint64_t *ts = iris_bo_map(NULL, bo, MAP_READ); 80 81 /* Don't translate the no-timestamp marker: */ 82 if (ts[idx] == U_TRACE_NO_TIMESTAMP) 83 return U_TRACE_NO_TIMESTAMP; 84 85 return intel_device_info_timebase_scale(&screen->devinfo, ts[idx]); 86} 87 88static void 89iris_utrace_delete_flush_data(struct u_trace_context *utctx, 90 void *flush_data) 91{ 92 free(flush_data); 93} 94 95void iris_utrace_flush(struct iris_batch *batch, uint64_t submission_id) 96{ 97 struct intel_ds_flush_data *flush_data = malloc(sizeof(*flush_data)); 98 intel_ds_flush_data_init(flush_data, batch->ds, submission_id); 99 u_trace_flush(&batch->trace, flush_data, false); 100} 101 102void iris_utrace_init(struct iris_context *ice) 103{ 104 struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen; 105 106 struct stat st; 107 uint32_t minor; 108 109 if (fstat(screen->fd, &st) == 0) 110 minor = minor(st.st_rdev); 111 else 112 minor = 0; 113 114 /* We could be dealing with /dev/dri/card0 or /dev/dri/renderD128 so to get 115 * a GPU ID we % 128 the minor number. 116 */ 117 intel_ds_device_init(&ice->ds, &screen->devinfo, screen->fd, minor % 128, 118 INTEL_DS_API_OPENGL); 119 u_trace_pipe_context_init(&ice->ds.trace_context, &ice->ctx, 120 iris_utrace_record_ts, 121 iris_utrace_read_ts, 122 iris_utrace_delete_flush_data); 123 124 for (int i = 0; i < IRIS_BATCH_COUNT; i++) { 125 ice->batches[i].ds = 126 intel_ds_device_add_queue(&ice->ds, "%s", 127 iris_batch_name_to_string(i)); 128 } 129} 130 131void iris_utrace_fini(struct iris_context *ice) 132{ 133 intel_ds_device_fini(&ice->ds); 134} 135 136enum intel_ds_stall_flag 137iris_utrace_pipe_flush_bit_to_ds_stall_flag(uint32_t flags) 138{ 139 static const struct { 140 uint32_t iris; 141 enum intel_ds_stall_flag ds; 142 } iris_to_ds_flags[] = { 143 { .iris = PIPE_CONTROL_DEPTH_CACHE_FLUSH, .ds = INTEL_DS_DEPTH_CACHE_FLUSH_BIT, }, 144 { .iris = PIPE_CONTROL_DATA_CACHE_FLUSH, .ds = INTEL_DS_DATA_CACHE_FLUSH_BIT, }, 145 { .iris = PIPE_CONTROL_TILE_CACHE_FLUSH, .ds = INTEL_DS_TILE_CACHE_FLUSH_BIT, }, 146 { .iris = PIPE_CONTROL_RENDER_TARGET_FLUSH, .ds = INTEL_DS_RENDER_TARGET_CACHE_FLUSH_BIT, }, 147 { .iris = PIPE_CONTROL_STATE_CACHE_INVALIDATE, .ds = INTEL_DS_STATE_CACHE_INVALIDATE_BIT, }, 148 { .iris = PIPE_CONTROL_CONST_CACHE_INVALIDATE, .ds = INTEL_DS_CONST_CACHE_INVALIDATE_BIT, }, 149 { .iris = PIPE_CONTROL_VF_CACHE_INVALIDATE, .ds = INTEL_DS_VF_CACHE_INVALIDATE_BIT, }, 150 { .iris = PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE, .ds = INTEL_DS_TEXTURE_CACHE_INVALIDATE_BIT, }, 151 { .iris = PIPE_CONTROL_INSTRUCTION_INVALIDATE, .ds = INTEL_DS_INST_CACHE_INVALIDATE_BIT, }, 152 { .iris = PIPE_CONTROL_DEPTH_STALL, .ds = INTEL_DS_DEPTH_STALL_BIT, }, 153 { .iris = PIPE_CONTROL_CS_STALL, .ds = INTEL_DS_CS_STALL_BIT, }, 154 { .iris = PIPE_CONTROL_FLUSH_HDC, .ds = INTEL_DS_HDC_PIPELINE_FLUSH_BIT, }, 155 { .iris = PIPE_CONTROL_STALL_AT_SCOREBOARD, .ds = INTEL_DS_STALL_AT_SCOREBOARD_BIT, }, 156 }; 157 158 enum intel_ds_stall_flag ret = 0; 159 for (uint32_t i = 0; i < ARRAY_SIZE(iris_to_ds_flags); i++) { 160 if (iris_to_ds_flags[i].iris & flags) 161 ret |= iris_to_ds_flags[i].ds; 162 } 163 164 assert(ret != 0); 165 166 return ret; 167} 168