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 40struct dd_context; 41 42enum dd_dump_mode { 43 DD_DUMP_ONLY_HANGS, 44 DD_DUMP_ALL_CALLS, 45 DD_DUMP_APITRACE_CALL, 46}; 47 48struct 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 61enum call_type 62{ 63 CALL_FLUSH, 64 CALL_DRAW_VBO, 65 CALL_LAUNCH_GRID, 66 CALL_RESOURCE_COPY_REGION, 67 CALL_BLIT, 68 CALL_FLUSH_RESOURCE, 69 CALL_CLEAR, 70 CALL_CLEAR_BUFFER, 71 CALL_CLEAR_TEXTURE, 72 CALL_CLEAR_RENDER_TARGET, 73 CALL_CLEAR_DEPTH_STENCIL, 74 CALL_GENERATE_MIPMAP, 75 CALL_GET_QUERY_RESULT_RESOURCE, 76 CALL_TRANSFER_MAP, 77 CALL_TRANSFER_FLUSH_REGION, 78 CALL_TRANSFER_UNMAP, 79 CALL_BUFFER_SUBDATA, 80 CALL_TEXTURE_SUBDATA, 81}; 82 83struct call_resource_copy_region 84{ 85 struct pipe_resource *dst; 86 unsigned dst_level; 87 unsigned dstx, dsty, dstz; 88 struct pipe_resource *src; 89 unsigned src_level; 90 struct pipe_box src_box; 91}; 92 93struct call_clear 94{ 95 unsigned buffers; 96 struct pipe_scissor_state scissor_state; 97 union pipe_color_union color; 98 double depth; 99 unsigned stencil; 100}; 101 102struct call_clear_buffer 103{ 104 struct pipe_resource *res; 105 unsigned offset; 106 unsigned size; 107 const void *clear_value; 108 int clear_value_size; 109}; 110 111struct call_generate_mipmap { 112 struct pipe_resource *res; 113 enum pipe_format format; 114 unsigned base_level; 115 unsigned last_level; 116 unsigned first_layer; 117 unsigned last_layer; 118}; 119 120struct call_flush { 121 unsigned flags; 122}; 123 124struct call_draw_info { 125 struct pipe_draw_info info; 126 unsigned drawid_offset; 127 struct pipe_draw_indirect_info indirect; 128 struct pipe_draw_start_count_bias draw; 129}; 130 131struct call_get_query_result_resource { 132 struct pipe_query *query; 133 enum pipe_query_type query_type; 134 enum pipe_query_flags flags; 135 enum pipe_query_value_type result_type; 136 int index; 137 struct pipe_resource *resource; 138 unsigned offset; 139}; 140 141struct call_transfer_map { 142 struct pipe_transfer *transfer_ptr; 143 struct pipe_transfer transfer; 144 void *ptr; 145}; 146 147struct call_transfer_flush_region { 148 struct pipe_transfer *transfer_ptr; 149 struct pipe_transfer transfer; 150 struct pipe_box box; 151}; 152 153struct call_transfer_unmap { 154 struct pipe_transfer *transfer_ptr; 155 struct pipe_transfer transfer; 156}; 157 158struct call_buffer_subdata { 159 struct pipe_resource *resource; 160 unsigned usage; 161 unsigned offset; 162 unsigned size; 163 const void *data; 164}; 165 166struct call_texture_subdata { 167 struct pipe_resource *resource; 168 unsigned level; 169 unsigned usage; 170 struct pipe_box box; 171 const void *data; 172 unsigned stride; 173 unsigned layer_stride; 174}; 175 176struct dd_call 177{ 178 enum call_type type; 179 180 union { 181 struct call_flush flush; 182 struct call_draw_info draw_vbo; 183 struct pipe_grid_info launch_grid; 184 struct call_resource_copy_region resource_copy_region; 185 struct pipe_blit_info blit; 186 struct pipe_resource *flush_resource; 187 struct call_clear clear; 188 struct call_clear_buffer clear_buffer; 189 struct call_generate_mipmap generate_mipmap; 190 struct call_get_query_result_resource get_query_result_resource; 191 struct call_transfer_map transfer_map; 192 struct call_transfer_flush_region transfer_flush_region; 193 struct call_transfer_unmap transfer_unmap; 194 struct call_buffer_subdata buffer_subdata; 195 struct call_texture_subdata texture_subdata; 196 } info; 197}; 198 199struct dd_query 200{ 201 unsigned type; 202 struct pipe_query *query; 203}; 204 205struct dd_state 206{ 207 void *cso; 208 209 union { 210 struct pipe_blend_state blend; 211 struct pipe_depth_stencil_alpha_state dsa; 212 struct pipe_rasterizer_state rs; 213 struct pipe_sampler_state sampler; 214 struct { 215 struct pipe_vertex_element velems[PIPE_MAX_ATTRIBS]; 216 unsigned count; 217 } velems; 218 struct pipe_shader_state shader; 219 } state; 220}; 221 222struct dd_draw_state 223{ 224 struct { 225 struct dd_query *query; 226 bool condition; 227 unsigned mode; 228 } render_cond; 229 230 struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; 231 232 unsigned num_so_targets; 233 struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS]; 234 unsigned so_offsets[PIPE_MAX_SO_BUFFERS]; 235 236 struct dd_state *shaders[PIPE_SHADER_TYPES]; 237 struct pipe_constant_buffer constant_buffers[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; 238 struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; 239 struct dd_state *sampler_states[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; 240 struct pipe_image_view shader_images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES]; 241 struct pipe_shader_buffer shader_buffers[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS]; 242 243 struct dd_state *velems; 244 struct dd_state *rs; 245 struct dd_state *dsa; 246 struct dd_state *blend; 247 248 struct pipe_blend_color blend_color; 249 struct pipe_stencil_ref stencil_ref; 250 unsigned sample_mask; 251 unsigned min_samples; 252 struct pipe_clip_state clip_state; 253 struct pipe_framebuffer_state framebuffer_state; 254 struct pipe_poly_stipple polygon_stipple; 255 struct pipe_scissor_state scissors[PIPE_MAX_VIEWPORTS]; 256 struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS]; 257 float tess_default_levels[6]; 258 259 unsigned apitrace_call_number; 260}; 261 262struct dd_draw_state_copy 263{ 264 struct dd_draw_state base; 265 266 /* dd_draw_state_copy does not reference real CSOs. Instead, it points to 267 * these variables, which serve as storage. 268 */ 269 struct dd_query render_cond; 270 struct dd_state shaders[PIPE_SHADER_TYPES]; 271 struct dd_state sampler_states[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; 272 struct dd_state velems; 273 struct dd_state rs; 274 struct dd_state dsa; 275 struct dd_state blend; 276}; 277 278struct dd_draw_record { 279 struct list_head list; 280 struct dd_context *dctx; 281 282 int64_t time_before; 283 int64_t time_after; 284 unsigned draw_call; 285 286 /* The fence pointers are guaranteed to be valid once driver_finished is signalled */ 287 struct pipe_fence_handle *prev_bottom_of_pipe; 288 struct pipe_fence_handle *top_of_pipe; 289 struct pipe_fence_handle *bottom_of_pipe; 290 291 struct dd_call call; 292 struct dd_draw_state_copy draw_state; 293 294 struct util_queue_fence driver_finished; 295 struct u_log_page *log_page; 296}; 297 298struct dd_context 299{ 300 struct pipe_context base; 301 struct pipe_context *pipe; 302 303 struct dd_draw_state draw_state; 304 unsigned num_draw_calls; 305 306 struct u_log_context log; 307 308 /* Pipelined hang detection. 309 * 310 * Before each draw call, a new dd_draw_record is created that contains 311 * a copy of all states. After each draw call, the driver's log is added 312 * to this record. Additionally, deferred fences are associated to each 313 * record both before and after the draw. 314 * 315 * The records are handed off to a separate thread which waits on the 316 * records' fences. Records with signalled fences are freed. When a timeout 317 * is detected, the thread dumps the records of in-flight draws. 318 */ 319 thrd_t thread; 320 mtx_t mutex; 321 cnd_t cond; 322 struct list_head records; /* oldest record first */ 323 unsigned num_records; 324 bool kill_thread; 325 bool api_stalled; 326}; 327 328 329struct pipe_context * 330dd_context_create(struct dd_screen *dscreen, struct pipe_context *pipe); 331 332void 333dd_init_draw_functions(struct dd_context *dctx); 334 335void 336dd_thread_join(struct dd_context *dctx); 337int 338dd_thread_main(void *input); 339 340FILE * 341dd_get_file_stream(struct dd_screen *dscreen, unsigned apitrace_call_number); 342 343static inline struct dd_context * 344dd_context(struct pipe_context *pipe) 345{ 346 return (struct dd_context *)pipe; 347} 348 349static inline struct dd_screen * 350dd_screen(struct pipe_screen *screen) 351{ 352 return (struct dd_screen*)screen; 353} 354 355static inline struct dd_query * 356dd_query(struct pipe_query *query) 357{ 358 return (struct dd_query *)query; 359} 360 361static inline struct pipe_query * 362dd_query_unwrap(struct pipe_query *query) 363{ 364 if (query) { 365 return dd_query(query)->query; 366 } else { 367 return NULL; 368 } 369} 370 371 372#define CTX_INIT(_member) \ 373 dctx->base._member = dctx->pipe->_member ? dd_context_##_member : NULL 374 375#endif /* DD_H_ */ 376