Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5563 serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 2012-2013 LunarG, Inc.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included
14
 * in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
23
 *
24
 * Authors:
25
 *    Chia-I Wu 
26
 */
27
 
28
#include "intel_winsys.h"
29
 
30
#include "ilo_3d.h"
31
#include "ilo_context.h"
32
#include "ilo_cp.h"
33
#include "ilo_query.h"
34
 
35
static const struct {
36
   const char *name;
37
 
38
   void (*begin)(struct ilo_context *ilo, struct ilo_query *q);
39
   void (*end)(struct ilo_context *ilo, struct ilo_query *q);
40
   void (*process)(struct ilo_context *ilo, struct ilo_query *q);
41
} query_info[PIPE_QUERY_TYPES] = {
42
#define INFO(prefix, desc) {        \
43
   .name = desc,                    \
44
   .begin = prefix ## _begin_query, \
45
   .end = prefix ## _end_query,     \
46
   .process = prefix ## _process_query, \
47
}
48
#define INFOX(prefix, desc) { desc, NULL, NULL, NULL, }
49
 
50
   [PIPE_QUERY_OCCLUSION_COUNTER]      = INFO(ilo_3d, "occlusion counter"),
51
   [PIPE_QUERY_OCCLUSION_PREDICATE]    = INFOX(ilo_3d, "occlusion pred."),
52
   [PIPE_QUERY_TIMESTAMP]              = INFO(ilo_3d, "timestamp"),
53
   [PIPE_QUERY_TIMESTAMP_DISJOINT]     = INFOX(ilo_3d, "timestamp disjoint"),
54
   [PIPE_QUERY_TIME_ELAPSED]           = INFO(ilo_3d, "time elapsed"),
55
   [PIPE_QUERY_PRIMITIVES_GENERATED]   = INFO(ilo_3d, "primitives generated"),
56
   [PIPE_QUERY_PRIMITIVES_EMITTED]     = INFO(ilo_3d, "primitives emitted"),
57
   [PIPE_QUERY_SO_STATISTICS]          = INFOX(ilo_3d, "so statistics"),
58
   [PIPE_QUERY_SO_OVERFLOW_PREDICATE]  = INFOX(ilo_3d, "so overflow pred."),
59
   [PIPE_QUERY_GPU_FINISHED]           = INFOX(ilo_3d, "gpu finished"),
60
   [PIPE_QUERY_PIPELINE_STATISTICS]    = INFOX(ilo_3d, "pipeline statistics"),
61
 
62
#undef INFO
63
#undef INFOX
64
};
65
 
66
static inline struct ilo_query *
67
ilo_query(struct pipe_query *query)
68
{
69
   return (struct ilo_query *) query;
70
}
71
 
72
static struct pipe_query *
73
ilo_create_query(struct pipe_context *pipe, unsigned query_type)
74
{
75
   struct ilo_query *q;
76
 
77
   switch (query_type) {
78
   case PIPE_QUERY_OCCLUSION_COUNTER:
79
   case PIPE_QUERY_TIMESTAMP:
80
   case PIPE_QUERY_TIME_ELAPSED:
81
   case PIPE_QUERY_PRIMITIVES_GENERATED:
82
   case PIPE_QUERY_PRIMITIVES_EMITTED:
83
      break;
84
   default:
85
      return NULL;
86
   }
87
 
88
   q = CALLOC_STRUCT(ilo_query);
89
   if (!q)
90
      return NULL;
91
 
92
   q->type = query_type;
93
   list_inithead(&q->list);
94
 
95
   return (struct pipe_query *) q;
96
}
97
 
98
static void
99
ilo_destroy_query(struct pipe_context *pipe, struct pipe_query *query)
100
{
101
   struct ilo_query *q = ilo_query(query);
102
 
103
   if (q->bo)
104
      intel_bo_unreference(q->bo);
105
 
106
   FREE(q);
107
}
108
 
109
static void
110
ilo_begin_query(struct pipe_context *pipe, struct pipe_query *query)
111
{
112
   struct ilo_context *ilo = ilo_context(pipe);
113
   struct ilo_query *q = ilo_query(query);
114
 
115
   q->active = true;
116
 
117
   query_info[q->type].begin(ilo, q);
118
}
119
 
120
static void
121
ilo_end_query(struct pipe_context *pipe, struct pipe_query *query)
122
{
123
   struct ilo_context *ilo = ilo_context(pipe);
124
   struct ilo_query *q = ilo_query(query);
125
 
126
   query_info[q->type].end(ilo, q);
127
 
128
   /*
129
    * some queries such as timestamp query does not require a call to
130
    * begin_query() so q->active is always false
131
    */
132
   q->active = false;
133
}
134
 
135
/**
136
 * The type (union pipe_query_result) indicates only the size of the buffer.
137
 * Callers expect the result to be "serialized".
138
 */
139
static void
140
serialize_query_data(unsigned type, const union pipe_query_result *data,
141
                     void *buf)
142
{
143
   switch (type) {
144
   case PIPE_QUERY_OCCLUSION_COUNTER:
145
   case PIPE_QUERY_TIMESTAMP:
146
   case PIPE_QUERY_TIME_ELAPSED:
147
   case PIPE_QUERY_PRIMITIVES_GENERATED:
148
   case PIPE_QUERY_PRIMITIVES_EMITTED:
149
      {
150
         uint64_t *r = buf;
151
         r[0] = data->u64;
152
      }
153
      break;
154
   default:
155
      memset(buf, 0, sizeof(union pipe_query_result));
156
      break;
157
   }
158
}
159
 
160
static boolean
161
ilo_get_query_result(struct pipe_context *pipe, struct pipe_query *query,
162
                     boolean wait, union pipe_query_result *result)
163
{
164
   struct ilo_context *ilo = ilo_context(pipe);
165
   struct ilo_query *q = ilo_query(query);
166
 
167
   if (q->active)
168
      return false;
169
 
170
   if (q->bo) {
171
      if (intel_bo_references(ilo->cp->bo, q->bo))
172
         ilo_cp_flush(ilo->cp);
173
 
174
      if (!wait && intel_bo_is_busy(q->bo))
175
         return false;
176
 
177
      query_info[q->type].process(ilo, q);
178
   }
179
 
180
   if (result)
181
      serialize_query_data(q->type, &q->data, (void *) result);
182
 
183
   return true;
184
}
185
 
186
/**
187
 * Allocate a query bo for reading hardware statistics.
188
 *
189
 * \param reg_count specifies how many registers need to be read.
190
 * \param repeat_count specifies how many times the registers are read.  If
191
 *        zero or negative, a 4KB bo is allocated.
192
 */
193
bool
194
ilo_query_alloc_bo(struct ilo_query *q, int reg_count, int repeat_count,
195
                   struct intel_winsys *winsys)
196
{
197
   const char *name;
198
   int reg_total;
199
 
200
   name = query_info[q->type].name;
201
 
202
   reg_total = reg_count * repeat_count;
203
   if (reg_total <= 0)
204
      reg_total = 4096 / sizeof(uint64_t);
205
 
206
   /* (re-)allocate the bo */
207
   if (q->reg_total < reg_total) {
208
      /* registers are 64-bit */
209
      const int size = reg_total * sizeof(uint64_t);
210
 
211
      if (q->bo)
212
         intel_bo_unreference(q->bo);
213
 
214
      q->bo = intel_winsys_alloc_buffer(winsys, name, size, 0);
215
      q->reg_total = (q->bo) ? reg_total : 0;
216
   }
217
 
218
   /* avoid partial reads */
219
   if (reg_count)
220
      q->reg_total -= q->reg_total % reg_count;
221
 
222
   q->reg_read = 0;
223
 
224
   return (q->bo != NULL);
225
}
226
 
227
/**
228
 * Initialize query-related functions.
229
 */
230
void
231
ilo_init_query_functions(struct ilo_context *ilo)
232
{
233
   ilo->base.create_query = ilo_create_query;
234
   ilo->base.destroy_query = ilo_destroy_query;
235
   ilo->base.begin_query = ilo_begin_query;
236
   ilo->base.end_query = ilo_end_query;
237
   ilo->base.get_query_result = ilo_get_query_result;
238
}