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