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
37enum dd_mode {
38   DD_DETECT_HANGS,
39   DD_DETECT_HANGS_PIPELINED,
40   DD_DUMP_ALL_CALLS,
41   DD_DUMP_APITRACE_CALL,
42};
43
44struct 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
56enum 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
70struct 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
80struct call_clear
81{
82   unsigned buffers;
83   union pipe_color_union color;
84   double depth;
85   unsigned stencil;
86};
87
88struct 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
97struct 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
106struct 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
122struct dd_query
123{
124   unsigned type;
125   struct pipe_query *query;
126};
127
128struct 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
145struct 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
186struct 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
202struct 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
213struct 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
249struct pipe_context *
250dd_context_create(struct dd_screen *dscreen, struct pipe_context *pipe);
251
252void
253dd_init_draw_functions(struct dd_context *dctx);
254PIPE_THREAD_ROUTINE(dd_thread_pipelined_hang_detect, input);
255
256
257static inline struct dd_context *
258dd_context(struct pipe_context *pipe)
259{
260   return (struct dd_context *)pipe;
261}
262
263static inline struct dd_screen *
264dd_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