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 37 enum dd_mode { 38 DD_DETECT_HANGS, 39 DD_DETECT_HANGS_PIPELINED, 40 DD_DUMP_ALL_CALLS, 41 DD_DUMP_APITRACE_CALL, 42 }; 43 44 struct dd_screen 45 { 46 struct pipe_screen base; 47 struct pipe_screen *screen; 48 unsigned timeout_ms; 49 enum dd_mode mode; 50 bool no_flush; 51 bool verbose; 52 unsigned skip_count; 53 unsigned apitrace_dump_call; 54 }; 55 56 enum call_type 57 { 58 CALL_DRAW_VBO, 59 CALL_LAUNCH_GRID, 60 CALL_RESOURCE_COPY_REGION, 61 CALL_BLIT, 62 CALL_FLUSH_RESOURCE, 63 CALL_CLEAR, 64 CALL_CLEAR_BUFFER, 65 CALL_CLEAR_RENDER_TARGET, 66 CALL_CLEAR_DEPTH_STENCIL, 67 CALL_GENERATE_MIPMAP, 68 }; 69 70 struct call_resource_copy_region 71 { 72 struct pipe_resource *dst; 73 unsigned dst_level; 74 unsigned dstx, dsty, dstz; 75 struct pipe_resource *src; 76 unsigned src_level; 77 struct pipe_box src_box; 78 }; 79 80 struct call_clear 81 { 82 unsigned buffers; 83 union pipe_color_union color; 84 double depth; 85 unsigned stencil; 86 }; 87 88 struct call_clear_buffer 89 { 90 struct pipe_resource *res; 91 unsigned offset; 92 unsigned size; 93 const void *clear_value; 94 int clear_value_size; 95 }; 96 97 struct call_generate_mipmap { 98 struct pipe_resource *res; 99 enum pipe_format format; 100 unsigned base_level; 101 unsigned last_level; 102 unsigned first_layer; 103 unsigned last_layer; 104 }; 105 106 struct dd_call 107 { 108 enum call_type type; 109 110 union { 111 struct pipe_draw_info draw_vbo; 112 struct pipe_grid_info launch_grid; 113 struct call_resource_copy_region resource_copy_region; 114 struct pipe_blit_info blit; 115 struct pipe_resource *flush_resource; 116 struct call_clear clear; 117 struct call_clear_buffer clear_buffer; 118 struct call_generate_mipmap generate_mipmap; 119 } info; 120 }; 121 122 struct dd_query 123 { 124 unsigned type; 125 struct pipe_query *query; 126 }; 127 128 struct dd_state 129 { 130 void *cso; 131 132 union { 133 struct pipe_blend_state blend; 134 struct pipe_depth_stencil_alpha_state dsa; 135 struct pipe_rasterizer_state rs; 136 struct pipe_sampler_state sampler; 137 struct { 138 struct pipe_vertex_element velems[PIPE_MAX_ATTRIBS]; 139 unsigned count; 140 } velems; 141 struct pipe_shader_state shader; 142 } state; 143 }; 144 145 struct dd_draw_state 146 { 147 struct { 148 struct dd_query *query; 149 bool condition; 150 unsigned mode; 151 } render_cond; 152 153 struct pipe_index_buffer index_buffer; 154 struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; 155 156 unsigned num_so_targets; 157 struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS]; 158 unsigned so_offsets[PIPE_MAX_SO_BUFFERS]; 159 160 struct dd_state *shaders[PIPE_SHADER_TYPES]; 161 struct pipe_constant_buffer constant_buffers[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; 162 struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; 163 struct dd_state *sampler_states[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; 164 struct pipe_image_view shader_images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES]; 165 struct pipe_shader_buffer shader_buffers[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS]; 166 167 struct dd_state *velems; 168 struct dd_state *rs; 169 struct dd_state *dsa; 170 struct dd_state *blend; 171 172 struct pipe_blend_color blend_color; 173 struct pipe_stencil_ref stencil_ref; 174 unsigned sample_mask; 175 unsigned min_samples; 176 struct pipe_clip_state clip_state; 177 struct pipe_framebuffer_state framebuffer_state; 178 struct pipe_poly_stipple polygon_stipple; 179 struct pipe_scissor_state scissors[PIPE_MAX_VIEWPORTS]; 180 struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS]; 181 float tess_default_levels[6]; 182 183 unsigned apitrace_call_number; 184 }; 185 186 struct dd_draw_state_copy 187 { 188 struct dd_draw_state base; 189 190 /* dd_draw_state_copy does not reference real CSOs. Instead, it points to 191 * these variables, which serve as storage. 192 */ 193 struct dd_query render_cond; 194 struct dd_state shaders[PIPE_SHADER_TYPES]; 195 struct dd_state sampler_states[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; 196 struct dd_state velems; 197 struct dd_state rs; 198 struct dd_state dsa; 199 struct dd_state blend; 200 }; 201 202 struct dd_draw_record { 203 struct dd_draw_record *next; 204 205 int64_t timestamp; 206 uint32_t sequence_no; 207 208 struct dd_call call; 209 struct dd_draw_state_copy draw_state; 210 char *driver_state_log; 211 }; 212 213 struct dd_context 214 { 215 struct pipe_context base; 216 struct pipe_context *pipe; 217 218 struct dd_draw_state draw_state; 219 unsigned num_draw_calls; 220 221 /* Pipelined hang detection. 222 * 223 * This is without unnecessary flushes and waits. There is a memory-based 224 * fence that is incremented by clear_buffer every draw call. Driver fences 225 * are not used. 226 * 227 * After each draw call, a new dd_draw_record is created that contains 228 * a copy of all states, the output of pipe_context::dump_debug_state, 229 * and it has a fence number assigned. That's done without knowing whether 230 * that draw call is problematic or not. The record is added into the list 231 * of all records. 232 * 233 * An independent, separate thread loops over the list of records and checks 234 * their fences. Records with signalled fences are freed. On fence timeout, 235 * the thread dumps the record of the oldest unsignalled fence. 236 */ 237 pipe_thread thread; 238 pipe_mutex mutex; 239 int kill_thread; 240 struct pipe_resource *fence; 241 struct pipe_transfer *fence_transfer; 242 uint32_t *mapped_fence; 243 uint32_t sequence_no; 244 struct dd_draw_record *records; 245 int max_log_buffer_size; 246 }; 247 248 249 struct pipe_context * 250 dd_context_create(struct dd_screen *dscreen, struct pipe_context *pipe); 251 252 void 253 dd_init_draw_functions(struct dd_context *dctx); 254 PIPE_THREAD_ROUTINE(dd_thread_pipelined_hang_detect, input); 255 256 257 static inline struct dd_context * 258 dd_context(struct pipe_context *pipe) 259 { 260 return (struct dd_context *)pipe; 261 } 262 263 static inline struct dd_screen * 264 dd_screen(struct pipe_screen *screen) 265 { 266 return (struct dd_screen*)screen; 267 } 268 269 270 #define CTX_INIT(_member) \ 271 dctx->base._member = dctx->pipe->_member ? dd_context_##_member : NULL 272 273 #endif /* DD_H_ */ 274