1 /************************************************************************** 2 * 3 * Copyright 2015 Advanced Micro Devices, Inc. 4 * Copyright 2008 VMware, Inc. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * on the rights to use, copy, modify, merge, publish, distribute, sub 11 * license, and/or sell copies of the Software, and to permit persons to whom 12 * the Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the next 15 * paragraph) shall be included in all copies or substantial portions of the 16 * Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24 * USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 #ifndef DD_H_ 29 #define DD_H_ 30 31 #include "pipe/p_context.h" 32 #include "pipe/p_state.h" 33 #include "pipe/p_screen.h" 34 #include "dd_util.h" 35 #include "os/os_thread.h" 36 #include "util/list.h" 37 #include "util/u_log.h" 38 #include "util/u_queue.h" 39 40 struct dd_context; 41 42 enum dd_dump_mode { 43 DD_DUMP_ONLY_HANGS, 44 DD_DUMP_ALL_CALLS, 45 DD_DUMP_APITRACE_CALL, 46 }; 47 48 struct dd_screen 49 { 50 struct pipe_screen base; 51 struct pipe_screen *screen; 52 unsigned timeout_ms; 53 enum dd_dump_mode dump_mode; 54 bool flush_always; 55 bool transfers; 56 bool verbose; 57 unsigned skip_count; 58 unsigned apitrace_dump_call; 59 }; 60 61 enum call_type 62 { 63 CALL_DRAW_VBO, 64 CALL_LAUNCH_GRID, 65 CALL_RESOURCE_COPY_REGION, 66 CALL_BLIT, 67 CALL_FLUSH_RESOURCE, 68 CALL_CLEAR, 69 CALL_CLEAR_BUFFER, 70 CALL_CLEAR_TEXTURE, 71 CALL_CLEAR_RENDER_TARGET, 72 CALL_CLEAR_DEPTH_STENCIL, 73 CALL_GENERATE_MIPMAP, 74 CALL_GET_QUERY_RESULT_RESOURCE, 75 CALL_TRANSFER_MAP, 76 CALL_TRANSFER_FLUSH_REGION, 77 CALL_TRANSFER_UNMAP, 78 CALL_BUFFER_SUBDATA, 79 CALL_TEXTURE_SUBDATA, 80 }; 81 82 struct call_resource_copy_region 83 { 84 struct pipe_resource *dst; 85 unsigned dst_level; 86 unsigned dstx, dsty, dstz; 87 struct pipe_resource *src; 88 unsigned src_level; 89 struct pipe_box src_box; 90 }; 91 92 struct call_clear 93 { 94 unsigned buffers; 95 union pipe_color_union color; 96 double depth; 97 unsigned stencil; 98 }; 99 100 struct call_clear_buffer 101 { 102 struct pipe_resource *res; 103 unsigned offset; 104 unsigned size; 105 const void *clear_value; 106 int clear_value_size; 107 }; 108 109 struct call_generate_mipmap { 110 struct pipe_resource *res; 111 enum pipe_format format; 112 unsigned base_level; 113 unsigned last_level; 114 unsigned first_layer; 115 unsigned last_layer; 116 }; 117 118 struct call_draw_info { 119 struct pipe_draw_info draw; 120 struct pipe_draw_indirect_info indirect; 121 }; 122 123 struct call_get_query_result_resource { 124 struct pipe_query *query; 125 enum pipe_query_type query_type; 126 boolean wait; 127 enum pipe_query_value_type result_type; 128 int index; 129 struct pipe_resource *resource; 130 unsigned offset; 131 }; 132 133 struct call_transfer_map { 134 struct pipe_transfer *transfer_ptr; 135 struct pipe_transfer transfer; 136 void *ptr; 137 }; 138 139 struct call_transfer_flush_region { 140 struct pipe_transfer *transfer_ptr; 141 struct pipe_transfer transfer; 142 struct pipe_box box; 143 }; 144 145 struct call_transfer_unmap { 146 struct pipe_transfer *transfer_ptr; 147 struct pipe_transfer transfer; 148 }; 149 150 struct call_buffer_subdata { 151 struct pipe_resource *resource; 152 unsigned usage; 153 unsigned offset; 154 unsigned size; 155 const void *data; 156 }; 157 158 struct call_texture_subdata { 159 struct pipe_resource *resource; 160 unsigned level; 161 unsigned usage; 162 struct pipe_box box; 163 const void *data; 164 unsigned stride; 165 unsigned layer_stride; 166 }; 167 168 struct dd_call 169 { 170 enum call_type type; 171 172 union { 173 struct call_draw_info draw_vbo; 174 struct pipe_grid_info launch_grid; 175 struct call_resource_copy_region resource_copy_region; 176 struct pipe_blit_info blit; 177 struct pipe_resource *flush_resource; 178 struct call_clear clear; 179 struct call_clear_buffer clear_buffer; 180 struct call_generate_mipmap generate_mipmap; 181 struct call_get_query_result_resource get_query_result_resource; 182 struct call_transfer_map transfer_map; 183 struct call_transfer_flush_region transfer_flush_region; 184 struct call_transfer_unmap transfer_unmap; 185 struct call_buffer_subdata buffer_subdata; 186 struct call_texture_subdata texture_subdata; 187 } info; 188 }; 189 190 struct dd_query 191 { 192 unsigned type; 193 struct pipe_query *query; 194 }; 195 196 struct dd_state 197 { 198 void *cso; 199 200 union { 201 struct pipe_blend_state blend; 202 struct pipe_depth_stencil_alpha_state dsa; 203 struct pipe_rasterizer_state rs; 204 struct pipe_sampler_state sampler; 205 struct { 206 struct pipe_vertex_element velems[PIPE_MAX_ATTRIBS]; 207 unsigned count; 208 } velems; 209 struct pipe_shader_state shader; 210 } state; 211 }; 212 213 struct dd_draw_state 214 { 215 struct { 216 struct dd_query *query; 217 bool condition; 218 unsigned mode; 219 } render_cond; 220 221 struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; 222 223 unsigned num_so_targets; 224 struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS]; 225 unsigned so_offsets[PIPE_MAX_SO_BUFFERS]; 226 227 struct dd_state *shaders[PIPE_SHADER_TYPES]; 228 struct pipe_constant_buffer constant_buffers[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; 229 struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; 230 struct dd_state *sampler_states[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; 231 struct pipe_image_view shader_images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES]; 232 struct pipe_shader_buffer shader_buffers[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS]; 233 234 struct dd_state *velems; 235 struct dd_state *rs; 236 struct dd_state *dsa; 237 struct dd_state *blend; 238 239 struct pipe_blend_color blend_color; 240 struct pipe_stencil_ref stencil_ref; 241 unsigned sample_mask; 242 unsigned min_samples; 243 struct pipe_clip_state clip_state; 244 struct pipe_framebuffer_state framebuffer_state; 245 struct pipe_poly_stipple polygon_stipple; 246 struct pipe_scissor_state scissors[PIPE_MAX_VIEWPORTS]; 247 struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS]; 248 float tess_default_levels[6]; 249 250 unsigned apitrace_call_number; 251 }; 252 253 struct dd_draw_state_copy 254 { 255 struct dd_draw_state base; 256 257 /* dd_draw_state_copy does not reference real CSOs. Instead, it points to 258 * these variables, which serve as storage. 259 */ 260 struct dd_query render_cond; 261 struct dd_state shaders[PIPE_SHADER_TYPES]; 262 struct dd_state sampler_states[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; 263 struct dd_state velems; 264 struct dd_state rs; 265 struct dd_state dsa; 266 struct dd_state blend; 267 }; 268 269 struct dd_draw_record { 270 struct list_head list; 271 struct dd_context *dctx; 272 273 int64_t time_before; 274 int64_t time_after; 275 unsigned draw_call; 276 277 struct pipe_fence_handle *prev_bottom_of_pipe; 278 struct pipe_fence_handle *top_of_pipe; 279 struct pipe_fence_handle *bottom_of_pipe; 280 281 struct dd_call call; 282 struct dd_draw_state_copy draw_state; 283 284 struct util_queue_fence driver_finished; 285 struct u_log_page *log_page; 286 }; 287 288 struct dd_context 289 { 290 struct pipe_context base; 291 struct pipe_context *pipe; 292 293 struct dd_draw_state draw_state; 294 unsigned num_draw_calls; 295 296 struct u_log_context log; 297 298 /* Pipelined hang detection. 299 * 300 * This is without unnecessary flushes and waits. There is a memory-based 301 * fence that is incremented by clear_buffer every draw call. Driver fences 302 * are not used. 303 * 304 * After each draw call, a new dd_draw_record is created that contains 305 * a copy of all states, the output of pipe_context::dump_debug_state, 306 * and it has a fence number assigned. That's done without knowing whether 307 * that draw call is problematic or not. The record is added into the list 308 * of all records. 309 * 310 * An independent, separate thread loops over the list of records and checks 311 * their fences. Records with signalled fences are freed. On fence timeout, 312 * the thread dumps the records of in-flight draws. 313 */ 314 thrd_t thread; 315 mtx_t mutex; 316 cnd_t cond; 317 struct dd_draw_record *record_pending; /* currently inside the driver */ 318 struct list_head records; /* oldest record first */ 319 unsigned num_records; 320 bool kill_thread; 321 bool api_stalled; 322 }; 323 324 325 struct pipe_context * 326 dd_context_create(struct dd_screen *dscreen, struct pipe_context *pipe); 327 328 void 329 dd_init_draw_functions(struct dd_context *dctx); 330 331 void 332 dd_thread_join(struct dd_context *dctx); 333 int 334 dd_thread_main(void *input); 335 336 FILE * 337 dd_get_file_stream(struct dd_screen *dscreen, unsigned apitrace_call_number); 338 339 static inline struct dd_context * 340 dd_context(struct pipe_context *pipe) 341 { 342 return (struct dd_context *)pipe; 343 } 344 345 static inline struct dd_screen * 346 dd_screen(struct pipe_screen *screen) 347 { 348 return (struct dd_screen*)screen; 349 } 350 351 static inline struct dd_query * 352 dd_query(struct pipe_query *query) 353 { 354 return (struct dd_query *)query; 355 } 356 357 static inline struct pipe_query * 358 dd_query_unwrap(struct pipe_query *query) 359 { 360 if (query) { 361 return dd_query(query)->query; 362 } else { 363 return NULL; 364 } 365 } 366 367 368 #define CTX_INIT(_member) \ 369 dctx->base._member = dctx->pipe->_member ? dd_context_##_member : NULL 370 371 #endif /* DD_H_ */ 372