]> git.cworth.org Git - fips/blob - metrics-info.c
Add explicit link to libpthread, to work around debugging issues
[fips] / metrics-info.c
1 /* Copyright © 2013, Intel Corporation
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to deal
5  * in the Software without restriction, including without limitation the rights
6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  * copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19  * THE SOFTWARE.
20  */
21
22 #include "metrics-info.h"
23
24 #include "xmalloc.h"
25
26 static void
27 metrics_group_info_init (metrics_group_info_t *group, GLuint id)
28 {
29         GLsizei length;
30         unsigned i;
31
32         group->id = id;
33
34         /* Get name */
35         glGetPerfMonitorGroupStringAMD (id, 0, &length, NULL);
36
37         group->name = xmalloc (length + 1);
38
39         glGetPerfMonitorGroupStringAMD (id, length + 1, NULL, group->name);
40
41         /* Get number of counters */
42         group->num_counters = 0;
43         group->max_active_counters = 0;
44         glGetPerfMonitorCountersAMD (group->id,
45                                      (int *) &group->num_counters,
46                                      (int *) &group->max_active_counters,
47                                      0, NULL);
48
49         /* Get counter numbers */
50         group->counter_ids = xmalloc (group->num_counters * sizeof (GLuint));
51
52         glGetPerfMonitorCountersAMD (group->id, NULL, NULL,
53                                      group->num_counters,
54                                      group->counter_ids);
55
56         /* Get counter names */
57         group->counter_names = xmalloc (group->num_counters * sizeof (char *));
58         group->counter_types = xmalloc (group->num_counters * sizeof (GLuint));
59
60         for (i = 0; i < group->num_counters; i++) {
61                 glGetPerfMonitorCounterInfoAMD (group->id,
62                                                 group->counter_ids[i],
63                                                 GL_COUNTER_TYPE_AMD,
64                                                 &group->counter_types[i]);
65
66                 glGetPerfMonitorCounterStringAMD (group->id,
67                                                   group->counter_ids[i],
68                                                   0, &length, NULL);
69
70                 group->counter_names[i] = xmalloc (length + 1);
71
72                 glGetPerfMonitorCounterStringAMD (group->id,
73                                                   group->counter_ids[i],
74                                                   length + 1, NULL,
75                                                   group->counter_names[i]);
76         }
77 }
78
79 static void
80 metrics_group_info_fini (metrics_group_info_t *group)
81 {
82         unsigned i;
83
84         for (i = 0; i < group->num_counters; i++)
85                 free (group->counter_names[i]);
86
87         free (group->counter_types);
88         free (group->counter_names);
89         free (group->counter_ids);
90
91         free (group->name);
92 }
93
94 /* A helper function, part of metrics_info_init below. */
95
96 typedef enum {
97         SHADER_ACTIVE,
98         SHADER_STALL
99 } shader_phase_t;
100
101 static void
102 _add_shader_stage (metrics_info_t *info, const char *name,
103                    GLuint group_index, GLuint counter_index,
104                    shader_phase_t phase)
105 {
106         shader_stage_info_t *stage;
107         char *stage_name, *space;
108         unsigned i;
109
110         stage_name = xstrdup (name);
111
112         /* Terminate the stage name at the first space.
113          *
114          * This is valid for counter names such as:
115          *
116          *      "Vertex Shader Active Time"
117          * or
118          *      "Vertex Shader Stall Time - Core Stall"
119          */
120         space = strchr (stage_name, ' ');
121         if (space)
122                 *space = '\0';
123
124         /* Look for an existing stage of the given name. */
125         stage = NULL;
126
127         for (i = 0; i < info->num_shader_stages; i++) {
128                 if (strcmp (info->stages[i].name, stage_name) == 0) {
129                         stage = &info->stages[i];
130                         break;
131                 }
132         }
133
134         if (stage == NULL) {
135                 info->num_shader_stages++;
136                 info->stages = xrealloc (info->stages,
137                                          info->num_shader_stages *
138                                          sizeof (shader_stage_info_t));
139                 stage = &info->stages[info->num_shader_stages - 1];
140                 stage->name = xstrdup (stage_name);
141                 stage->active_group_index = 0;
142                 stage->active_counter_index = 0;
143                 stage->stall_group_index = 0;
144                 stage->stall_counter_index = 0;
145         }
146
147         if (phase == SHADER_ACTIVE) {
148                 stage->active_group_index = group_index;
149                 stage->active_counter_index = counter_index;
150         } else {
151                 stage->stall_group_index = group_index;
152                 stage->stall_counter_index = counter_index;
153         }
154
155         free (stage_name);
156 }
157
158 void
159 metrics_info_init (metrics_info_t *info, bool have_perfmon)
160 {
161         unsigned i, j;
162         GLuint *group_ids;
163
164         info->have_perfmon = have_perfmon;
165
166         if (! have_perfmon) {
167                 info->groups = NULL;
168                 info->num_groups = 0;
169                 info->num_shader_stages = 0;
170                 info->stages = NULL;
171                 info->initialized = 1;
172
173                 return;
174         }
175
176         glGetPerfMonitorGroupsAMD ((int *) &info->num_groups, 0, NULL);
177
178         group_ids = xmalloc (info->num_groups * sizeof (GLuint));
179
180         glGetPerfMonitorGroupsAMD (NULL, info->num_groups, group_ids);
181
182         info->groups = xmalloc (info->num_groups * sizeof (metrics_group_info_t));
183
184         for (i = 0; i < info->num_groups; i++)
185                 metrics_group_info_init (&info->groups[i], group_ids[i]);
186
187         free (group_ids);
188
189         /* Identify each shader stage (by looking at
190          * performance-counter names for specific patterns) and
191          * initialize structures referring to the corresponding
192          * counter numbers for each stage. */
193         info->num_shader_stages = 0;
194         info->stages = NULL;
195
196         for (i = 0; i < info->num_groups; i++) {
197                 metrics_group_info_t *group = &info->groups[i];
198                 for (j = 0; j < group->num_counters; j++) {
199                         char *name = group->counter_names[j];
200                         if (strstr (name, "Shader Active Time")) {
201                                 _add_shader_stage (info, name, i, j,
202                                                    SHADER_ACTIVE);
203                         }
204                         if (strstr (name, "Shader Stall Time")) {
205                                 _add_shader_stage (info, name, i, j,
206                                                    SHADER_STALL);
207                         }
208                 }
209         }
210
211         info->initialized = 1;
212 }
213
214 void
215 metrics_info_fini (metrics_info_t *info)
216 {
217         unsigned i;
218         if (! info->initialized)
219                 return;
220
221         for (i = 0; i < info->num_groups; i++)
222                 metrics_group_info_fini (&info->groups[i]);
223
224         free (info->groups);
225         info->groups = NULL;
226
227         for (i = 0; i < info->num_shader_stages; i++)
228                 free (info->stages[i].name);
229
230         free (info->stages);
231         info->stages = NULL;
232
233         info->initialized = 0;
234 }