1 /*
2  * Copyright 2011 Christoph Bumiller
3  * Copyright 2015 Samuel Pitoiset
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "nvc0/nvc0_context.h"
25 
26 #include "nvc0_query_sw.h"
27 
28 /* === DRIVER STATISTICS === */
29 
30 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
31 
32 static const char *nvc0_sw_query_drv_stat_names[] =
33 {
34    "drv-tex_obj_current_count",
35    "drv-tex_obj_current_bytes",
36    "drv-buf_obj_current_count",
37    "drv-buf_obj_current_bytes_vid",
38    "drv-buf_obj_current_bytes_sys",
39    "drv-tex_transfers_rd",
40    "drv-tex_transfers_wr",
41    "drv-tex_copy_count",
42    "drv-tex_blit_count",
43    "drv-tex_cache_flush_count",
44    "drv-buf_transfers_rd",
45    "drv-buf_transfers_wr",
46    "drv-buf_read_bytes_staging_vid",
47    "drv-buf_write_bytes_direct",
48    "drv-buf_write_bytes_staging_vid",
49    "drv-buf_write_bytes_staging_sys",
50    "drv-buf_copy_bytes",
51    "drv-buf_non_kernel_fence_sync_count",
52    "drv-any_non_kernel_fence_sync_count",
53    "drv-query_sync_count",
54    "drv-gpu_serialize_count",
55    "drv-draw_calls_array",
56    "drv-draw_calls_indexed",
57    "drv-draw_calls_fallback_count",
58    "drv-user_buffer_upload_bytes",
59    "drv-constbuf_upload_count",
60    "drv-constbuf_upload_bytes",
61    "drv-pushbuf_count",
62    "drv-resource_validate_count"
63 };
64 
65 #endif /* NOUVEAU_ENABLE_DRIVER_STATISTICS */
66 
67 static void
nvc0_sw_destroy_query(struct nvc0_context * nvc0,struct nvc0_query * q)68 nvc0_sw_destroy_query(struct nvc0_context *nvc0, struct nvc0_query *q)
69 {
70    struct nvc0_sw_query *sq = nvc0_sw_query(q);
71    FREE(sq);
72 }
73 
74 static boolean
nvc0_sw_begin_query(struct nvc0_context * nvc0,struct nvc0_query * q)75 nvc0_sw_begin_query(struct nvc0_context *nvc0, struct nvc0_query *q)
76 {
77 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
78    struct nvc0_sw_query *sq = nvc0_sw_query(q);
79 
80    if (q->index >= 5) {
81       sq->value = nvc0->screen->base.stats.v[q->index];
82    } else {
83       sq->value = 0;
84    }
85 #endif
86    return true;
87 }
88 
89 static void
nvc0_sw_end_query(struct nvc0_context * nvc0,struct nvc0_query * q)90 nvc0_sw_end_query(struct nvc0_context *nvc0, struct nvc0_query *q)
91 {
92 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
93    struct nvc0_sw_query *sq = nvc0_sw_query(q);
94    sq->value = nvc0->screen->base.stats.v[q->index] - sq->value;
95 #endif
96 }
97 
98 static boolean
nvc0_sw_get_query_result(struct nvc0_context * nvc0,struct nvc0_query * q,boolean wait,union pipe_query_result * result)99 nvc0_sw_get_query_result(struct nvc0_context *nvc0, struct nvc0_query *q,
100                          boolean wait, union pipe_query_result *result)
101 {
102 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
103    struct nvc0_sw_query *sq = nvc0_sw_query(q);
104    uint64_t *res64 = (uint64_t *)result;
105 
106    res64[0] = sq->value;
107 #endif
108    return true;
109 }
110 
111 static const struct nvc0_query_funcs sw_query_funcs = {
112    .destroy_query = nvc0_sw_destroy_query,
113    .begin_query = nvc0_sw_begin_query,
114    .end_query = nvc0_sw_end_query,
115    .get_query_result = nvc0_sw_get_query_result,
116 };
117 
118 struct nvc0_query *
nvc0_sw_create_query(struct nvc0_context * nvcO,unsigned type,unsigned index)119 nvc0_sw_create_query(struct nvc0_context *nvcO, unsigned type, unsigned index)
120 {
121    struct nvc0_sw_query *sq;
122    struct nvc0_query *q;
123 
124    if (type < NVC0_SW_QUERY_DRV_STAT(0) || type > NVC0_SW_QUERY_DRV_STAT_LAST)
125       return NULL;
126 
127    sq = CALLOC_STRUCT(nvc0_sw_query);
128    if (!sq)
129       return NULL;
130 
131    q = &sq->base;
132    q->funcs = &sw_query_funcs;
133    q->type = type;
134    q->index = type - NVC0_SW_QUERY_DRV_STAT(0);
135 
136    return q;
137 }
138 
139 int
nvc0_sw_get_driver_query_info(struct nvc0_screen * screen,unsigned id,struct pipe_driver_query_info * info)140 nvc0_sw_get_driver_query_info(struct nvc0_screen *screen, unsigned id,
141                               struct pipe_driver_query_info *info)
142 {
143    int count = 0;
144 
145    count += NVC0_SW_QUERY_DRV_STAT_COUNT;
146    if (!info)
147       return count;
148 
149 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
150    if (id < count) {
151       info->name = nvc0_sw_query_drv_stat_names[id];
152       info->query_type = NVC0_SW_QUERY_DRV_STAT(id);
153       info->type = PIPE_DRIVER_QUERY_TYPE_UINT64;
154       info->max_value.u64 = 0;
155       if (strstr(info->name, "bytes"))
156          info->type = PIPE_DRIVER_QUERY_TYPE_BYTES;
157       info->group_id = NVC0_SW_QUERY_DRV_STAT_GROUP;
158       return 1;
159    }
160 #endif
161    return 0;
162 }
163