Home | History | Annotate | Download | only in ddebug
      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