mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-31 03:20:09 +01:00
mesa: Implement INTEL_performance_query.
Using the existing driver hooks made for AMD_performance_monitor, implement INTEL_performance_query functions. v2: Whitespace changes. v3: Whitespace changes, add a _mesa_warning() Signed-off-by: Petri Latvala <petri.latvala@intel.com> Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
parent
dac82ceac5
commit
8cf5bdad3c
1 changed files with 443 additions and 48 deletions
|
|
@ -137,6 +137,46 @@ get_counter(const struct gl_perf_monitor_group *group_obj, GLuint id)
|
|||
return &group_obj->Counters[id];
|
||||
}
|
||||
|
||||
/* For INTEL_performance_query, query id 0 is reserved to be invalid. We use
|
||||
* index to Groups array + 1 as the query id. Same applies to counter id.
|
||||
*/
|
||||
static inline GLuint
|
||||
queryid_to_index(GLuint queryid)
|
||||
{
|
||||
return queryid - 1;
|
||||
}
|
||||
|
||||
static inline GLuint
|
||||
index_to_queryid(GLuint index)
|
||||
{
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
queryid_valid(const struct gl_context *ctx, GLuint queryid)
|
||||
{
|
||||
return get_group(ctx, queryid_to_index(queryid)) != NULL;
|
||||
}
|
||||
|
||||
static inline GLuint
|
||||
counterid_to_index(GLuint counterid)
|
||||
{
|
||||
return counterid - 1;
|
||||
}
|
||||
|
||||
static inline GLuint
|
||||
index_to_counterid(GLuint index)
|
||||
{
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
counterid_valid(const struct gl_perf_monitor_group *group_obj,
|
||||
GLuint counterid)
|
||||
{
|
||||
return get_counter(group_obj, counterid_to_index(counterid)) != NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void GLAPIENTRY
|
||||
|
|
@ -644,6 +684,7 @@ extern void GLAPIENTRY
|
|||
_mesa_GetFirstPerfQueryIdINTEL(GLuint *queryId)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
unsigned numGroups;
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
|
|
@ -655,16 +696,22 @@ _mesa_GetFirstPerfQueryIdINTEL(GLuint *queryId)
|
|||
return;
|
||||
}
|
||||
|
||||
numGroups = ctx->PerfMonitor.NumGroups;
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "If the given hardware platform doesn't support any performance
|
||||
* queries, then the value of 0 is returned and INVALID_OPERATION error
|
||||
* is raised."
|
||||
*/
|
||||
if (numGroups == 0) {
|
||||
*queryId = 0;
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glGetFirstPerfQueryIdINTEL(no queries supported)");
|
||||
return;
|
||||
}
|
||||
|
||||
*queryId = 0;
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glGetFirstPerfQueryIdINTEL(no queries supported)");
|
||||
*queryId = index_to_queryid(0);
|
||||
}
|
||||
|
||||
extern void GLAPIENTRY
|
||||
|
|
@ -674,40 +721,66 @@ _mesa_GetNextPerfQueryIdINTEL(GLuint queryId, GLuint *nextQueryId)
|
|||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "If nextQueryId pointer is equal to 0, an INVALID_VALUE error is
|
||||
* generated."
|
||||
* "The result is passed in location pointed by nextQueryId. If query
|
||||
* identified by queryId is the last query available the value of 0 is
|
||||
* returned. If the specified performance query identifier is invalid
|
||||
* then INVALID_VALUE error is generated. If nextQueryId pointer is
|
||||
* equal to 0, an INVALID_VALUE error is generated. Whenever error is
|
||||
* generated, the value of 0 is returned."
|
||||
*/
|
||||
|
||||
if (!nextQueryId) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetNextPerfQueryIdINTEL(nextQueryId == NULL)");
|
||||
return;
|
||||
}
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "If the specified performance query identifier is invalid then
|
||||
* INVALID_VALUE error is generated. Whenever error is generated, the
|
||||
* value of 0 is returned."
|
||||
*
|
||||
* No queries are supported, so all queries are invalid.
|
||||
*/
|
||||
*nextQueryId = 0;
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetNextPerfQueryIdINTEL(invalid query)");
|
||||
if (!queryid_valid(ctx, queryId)) {
|
||||
*nextQueryId = 0;
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetNextPerfQueryIdINTEL(invalid query)");
|
||||
return;
|
||||
}
|
||||
|
||||
++queryId;
|
||||
|
||||
if (!queryid_valid(ctx, queryId)) {
|
||||
*nextQueryId = 0;
|
||||
} else {
|
||||
*nextQueryId = queryId;
|
||||
}
|
||||
}
|
||||
|
||||
extern void GLAPIENTRY
|
||||
_mesa_GetPerfQueryIdByNameINTEL(char *queryName, GLuint *queryId)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
unsigned i;
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "If queryName does not reference a valid query name, an INVALID_VALUE
|
||||
* error is generated."
|
||||
*
|
||||
* No queries are supported, so all query names are invalid.
|
||||
*/
|
||||
if (!queryName) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetPerfQueryIdByNameINTEL(queryName == NULL)");
|
||||
return;
|
||||
}
|
||||
|
||||
/* The specification does not state that this produces an error. */
|
||||
if (!queryId) {
|
||||
_mesa_warning(ctx, "glGetPerfQueryIdByNameINTEL(queryId == NULL)");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ctx->PerfMonitor.NumGroups; ++i) {
|
||||
const struct gl_perf_monitor_group *group_obj = get_group(ctx, i);
|
||||
if (strcmp(group_obj->Name, queryName) == 0) {
|
||||
*queryId = index_to_queryid(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetPerfQueryIdByNameINTEL(invalid query name)");
|
||||
|
|
@ -721,17 +794,69 @@ _mesa_GetPerfQueryInfoINTEL(GLuint queryId,
|
|||
GLuint *capsMask)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
unsigned i;
|
||||
|
||||
const struct gl_perf_monitor_group *group_obj =
|
||||
get_group(ctx, queryid_to_index(queryId));
|
||||
|
||||
if (group_obj == NULL) {
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "If queryId does not reference a valid query type, an
|
||||
* INVALID_VALUE error is generated."
|
||||
*/
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetPerfQueryInfoINTEL(invalid query)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (queryName) {
|
||||
strncpy(queryName, group_obj->Name, queryNameLength);
|
||||
|
||||
/* No specification given about whether the string needs to be
|
||||
* zero-terminated. Zero-terminate the string always as we don't
|
||||
* otherwise communicate the length of the returned string.
|
||||
*/
|
||||
if (queryNameLength > 0) {
|
||||
queryName[queryNameLength - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (dataSize) {
|
||||
unsigned size = 0;
|
||||
for (i = 0; i < group_obj->NumCounters; ++i) {
|
||||
/* What we get from the driver is group id (uint32_t) + counter id
|
||||
* (uint32_t) + value.
|
||||
*/
|
||||
size += 2 * sizeof(uint32_t) + _mesa_perf_monitor_counter_size(&group_obj->Counters[i]);
|
||||
}
|
||||
*dataSize = size;
|
||||
}
|
||||
|
||||
if (noCounters) {
|
||||
*noCounters = group_obj->NumCounters;
|
||||
}
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "If queryId does not reference a valid query type, an INVALID_VALUE
|
||||
* error is generated."
|
||||
* "-- the actual number of already created query instances in
|
||||
* maxInstances location"
|
||||
*
|
||||
* No queries are supported, so all queries are invalid.
|
||||
* 1) Typo in the specification, should be noActiveInstances.
|
||||
* 2) Another typo in the specification, maxInstances parameter is not listed
|
||||
* in the declaration of this function in the list of new functions.
|
||||
*/
|
||||
if (noActiveInstances) {
|
||||
*noActiveInstances = _mesa_HashNumEntries(ctx->PerfMonitor.Monitors);
|
||||
}
|
||||
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetPerfQueryInfoINTEL(invalid query)");
|
||||
if (capsMask) {
|
||||
/* TODO: This information not yet available in the monitor structs. For
|
||||
* now, we hardcode SINGLE_CONTEXT, since that's what the implementation
|
||||
* currently tries very hard to do.
|
||||
*/
|
||||
*capsMask = GL_PERFQUERY_SINGLE_CONTEXT_INTEL;
|
||||
}
|
||||
}
|
||||
|
||||
extern void GLAPIENTRY
|
||||
|
|
@ -743,73 +868,281 @@ _mesa_GetPerfCounterInfoINTEL(GLuint queryId, GLuint counterId,
|
|||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
const struct gl_perf_monitor_group *group_obj;
|
||||
const struct gl_perf_monitor_counter *counter_obj;
|
||||
unsigned counterIndex;
|
||||
unsigned i;
|
||||
|
||||
group_obj = get_group(ctx, queryid_to_index(queryId));
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "If the pair of queryId and counterId does not reference a valid
|
||||
* counter, an INVALID_VALUE error is generated."
|
||||
*
|
||||
* No queries are supported, so all queries are invalid.
|
||||
*/
|
||||
if (group_obj == NULL) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetPerfCounterInfoINTEL(invalid queryId)");
|
||||
return;
|
||||
}
|
||||
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetPerfCounterInfoINTEL(invalid counterId)");
|
||||
counterIndex = counterid_to_index(counterId);
|
||||
counter_obj = get_counter(group_obj, counterIndex);
|
||||
|
||||
if (counter_obj == NULL) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetPerfCounterInfoINTEL(invalid counterId)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (counterName) {
|
||||
strncpy(counterName, counter_obj->Name, counterNameLength);
|
||||
|
||||
/* No specification given about whether the string needs to be
|
||||
* zero-terminated. Zero-terminate the string always as we don't
|
||||
* otherwise communicate the length of the returned string.
|
||||
*/
|
||||
if (counterNameLength > 0) {
|
||||
counterName[counterNameLength - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (counterDesc) {
|
||||
/* TODO: No separate description text at the moment. We pass the name
|
||||
* again for the moment.
|
||||
*/
|
||||
strncpy(counterDesc, counter_obj->Name, counterDescLength);
|
||||
|
||||
/* No specification given about whether the string needs to be
|
||||
* zero-terminated. Zero-terminate the string always as we don't
|
||||
* otherwise communicate the length of the returned string.
|
||||
*/
|
||||
if (counterDescLength > 0) {
|
||||
counterDesc[counterDescLength - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (counterOffset) {
|
||||
unsigned offset = 0;
|
||||
for (i = 0; i < counterIndex; ++i) {
|
||||
/* What we get from the driver is group id (uint32_t) + counter id
|
||||
* (uint32_t) + value.
|
||||
*/
|
||||
offset += 2 * sizeof(uint32_t) + _mesa_perf_monitor_counter_size(&group_obj->Counters[i]);
|
||||
}
|
||||
*counterOffset = 2 * sizeof(uint32_t) + offset;
|
||||
}
|
||||
|
||||
if (counterDataSize) {
|
||||
*counterDataSize = _mesa_perf_monitor_counter_size(counter_obj);
|
||||
}
|
||||
|
||||
if (counterTypeEnum) {
|
||||
/* TODO: Different counter types (semantic type, not data type) not
|
||||
* supported as of yet.
|
||||
*/
|
||||
*counterTypeEnum = GL_PERFQUERY_COUNTER_RAW_INTEL;
|
||||
}
|
||||
|
||||
if (counterDataTypeEnum) {
|
||||
switch (counter_obj->Type) {
|
||||
case GL_FLOAT:
|
||||
case GL_PERCENTAGE_AMD:
|
||||
*counterDataTypeEnum = GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL;
|
||||
break;
|
||||
case GL_UNSIGNED_INT:
|
||||
*counterDataTypeEnum = GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL;
|
||||
break;
|
||||
case GL_UNSIGNED_INT64_AMD:
|
||||
*counterDataTypeEnum = GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL;
|
||||
break;
|
||||
default:
|
||||
assert(!"Should not get here: invalid counter type");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (rawCounterMaxValue) {
|
||||
/* This value is (implicitly) specified to be used only with
|
||||
* GL_PERFQUERY_COUNTER_RAW_INTEL counters. When semantic types for
|
||||
* counters are added, that needs to be checked.
|
||||
*/
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "for some raw counters for which the maximal value is
|
||||
* deterministic, the maximal value of the counter in 1 second is
|
||||
* returned in the location pointed by rawCounterMaxValue, otherwise,
|
||||
* the location is written with the value of 0."
|
||||
*
|
||||
* The maximum value reported by the driver at the moment is not with
|
||||
* these semantics, so write 0 always to be safe.
|
||||
*/
|
||||
*rawCounterMaxValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern void GLAPIENTRY
|
||||
_mesa_CreatePerfQueryINTEL(GLuint queryId, GLuint *queryHandle)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
GLuint first;
|
||||
GLuint group;
|
||||
const struct gl_perf_monitor_group *group_obj;
|
||||
struct gl_perf_monitor_object *m;
|
||||
unsigned i;
|
||||
|
||||
/* This is not specified in the extension, but is the only sane thing to
|
||||
* do.
|
||||
*/
|
||||
if (queryHandle == NULL) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glCreatePerfQueryINTEL(queryHandle == NULL)");
|
||||
return;
|
||||
}
|
||||
|
||||
group = queryid_to_index(queryId);
|
||||
group_obj = get_group(ctx, group);
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "If queryId does not reference a valid query type, an INVALID_VALUE
|
||||
* error is generated."
|
||||
*
|
||||
* No queries are supported, so all queries are invalid.
|
||||
*/
|
||||
if (group_obj == NULL) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glCreatePerfQueryINTEL(invalid queryId)");
|
||||
return;
|
||||
}
|
||||
|
||||
/* The query object created here is the counterpart of a `monitor' in
|
||||
* AMD_performance_monitor. This call is equivalent to calling
|
||||
* GenPerfMonitorsAMD and SelectPerfMonitorCountersAMD with a list of all
|
||||
* counters in a group.
|
||||
*/
|
||||
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glCreatePerfQueryINTEL(invalid queryId)");
|
||||
/* We keep the monitor ids contiguous */
|
||||
first = _mesa_HashFindFreeKeyBlock(ctx->PerfMonitor.Monitors, 1);
|
||||
if (!first) {
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "If the query instance cannot be created due to exceeding the
|
||||
* number of allowed instances or driver fails query creation due to
|
||||
* an insufficient memory reason, an OUT_OF_MEMORY error is
|
||||
* generated, and the location pointed by queryHandle returns NULL."
|
||||
*/
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCreatePerfQueryINTEL");
|
||||
return;
|
||||
}
|
||||
|
||||
m = new_performance_monitor(ctx, first);
|
||||
_mesa_HashInsert(ctx->PerfMonitor.Monitors, first, m);
|
||||
*queryHandle = first;
|
||||
|
||||
ctx->Driver.ResetPerfMonitor(ctx, m);
|
||||
|
||||
for (i = 0; i < group_obj->NumCounters; ++i) {
|
||||
++m->ActiveGroups[group];
|
||||
/* Counters are a continuous range of integers, 0 to NumCounters (excl),
|
||||
* so i is the counter value to use here.
|
||||
*/
|
||||
BITSET_SET(m->ActiveCounters[group], i);
|
||||
}
|
||||
}
|
||||
|
||||
extern void GLAPIENTRY
|
||||
_mesa_DeletePerfQueryINTEL(GLuint queryHandle)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
struct gl_perf_monitor_object *m;
|
||||
|
||||
/* The queryHandle is the counterpart to AMD_performance_monitor's monitor
|
||||
* id.
|
||||
*/
|
||||
m = lookup_monitor(ctx, queryHandle);
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "If a query handle doesn't reference a previously created performance
|
||||
* query instance, an INVALID_VALUE error is generated."
|
||||
*
|
||||
* No queries are supported, so all queries are invalid.
|
||||
*/
|
||||
if (m == NULL) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glDeletePerfQueryINTEL(invalid queryHandle)");
|
||||
return;
|
||||
}
|
||||
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glDeletePerfQueryINTEL(invalid queryHandle)");
|
||||
/* Let the driver stop the monitor if it's active. */
|
||||
if (m->Active) {
|
||||
ctx->Driver.ResetPerfMonitor(ctx, m);
|
||||
m->Ended = false;
|
||||
}
|
||||
|
||||
_mesa_HashRemove(ctx->PerfMonitor.Monitors, queryHandle);
|
||||
ralloc_free(m->ActiveGroups);
|
||||
ralloc_free(m->ActiveCounters);
|
||||
ctx->Driver.DeletePerfMonitor(ctx, m);
|
||||
}
|
||||
|
||||
extern void GLAPIENTRY
|
||||
_mesa_BeginPerfQueryINTEL(GLuint queryHandle)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
struct gl_perf_monitor_object *m;
|
||||
|
||||
/* The queryHandle is the counterpart to AMD_performance_monitor's monitor
|
||||
* id.
|
||||
*/
|
||||
|
||||
m = lookup_monitor(ctx, queryHandle);
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "If a query handle doesn't reference a previously created performance
|
||||
* query instance, an INVALID_VALUE error is generated."
|
||||
*
|
||||
* No queries are supported, so all queries are invalid.
|
||||
*/
|
||||
if (m == NULL) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glBeginPerfQueryINTEL(invalid queryHandle)");
|
||||
return;
|
||||
}
|
||||
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glBeginPerfQueryINTEL(invalid queryHandle)");
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "Note that some query types, they cannot be collected in the same
|
||||
* time. Therefore calls of BeginPerfQueryINTEL() cannot be nested if
|
||||
* they refer to queries of such different types. In such case
|
||||
* INVALID_OPERATION error is generated."
|
||||
*
|
||||
* We also generate an INVALID_OPERATION error if the driver can't begin
|
||||
* monitoring for its own reasons, and for nesting the same query.
|
||||
*/
|
||||
if (m->Active) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glBeginPerfQueryINTEL(already active)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->Driver.BeginPerfMonitor(ctx, m)) {
|
||||
m->Active = true;
|
||||
m->Ended = false;
|
||||
} else {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glBeginPerfQueryINTEL(driver unable to begin monitoring)");
|
||||
}
|
||||
}
|
||||
|
||||
extern void GLAPIENTRY
|
||||
_mesa_EndPerfQueryINTEL(GLuint queryHandle)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
struct gl_perf_monitor_object *m;
|
||||
|
||||
/* The queryHandle is the counterpart to AMD_performance_monitor's monitor
|
||||
* id.
|
||||
*/
|
||||
|
||||
m = lookup_monitor(ctx, queryHandle);
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
|
|
@ -818,13 +1151,24 @@ _mesa_EndPerfQueryINTEL(GLuint queryHandle)
|
|||
*
|
||||
* The specification doesn't state that an invalid handle would be an
|
||||
* INVALID_VALUE error. Regardless, query for such a handle will not be
|
||||
* started, so we generate an INVALID_OPERATION in that case.
|
||||
*
|
||||
* No queries are supported, so all handles are invalid.
|
||||
* started, so we generate an INVALID_OPERATION in that case too.
|
||||
*/
|
||||
if (m == NULL) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glEndPerfQueryINTEL(invalid queryHandle)");
|
||||
return;
|
||||
}
|
||||
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glEndPerfQueryINTEL(query not started)");
|
||||
if (!m->Active) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glEndPerfQueryINTEL(not active)");
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->Driver.EndPerfMonitor(ctx, m);
|
||||
|
||||
m->Active = false;
|
||||
m->Ended = true;
|
||||
}
|
||||
|
||||
extern void GLAPIENTRY
|
||||
|
|
@ -832,6 +1176,8 @@ _mesa_GetPerfQueryDataINTEL(GLuint queryHandle, GLuint flags,
|
|||
GLsizei dataSize, void *data, GLuint *bytesWritten)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
struct gl_perf_monitor_object *m;
|
||||
bool result_available;
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
|
|
@ -844,6 +1190,12 @@ _mesa_GetPerfQueryDataINTEL(GLuint queryHandle, GLuint flags,
|
|||
return;
|
||||
}
|
||||
|
||||
/* The queryHandle is the counterpart to AMD_performance_monitor's monitor
|
||||
* id.
|
||||
*/
|
||||
|
||||
m = lookup_monitor(ctx, queryHandle);
|
||||
|
||||
/* The specification doesn't state that an invalid handle generates an
|
||||
* error. We could interpret that to mean the case should be handled as
|
||||
* "measurement not ready for this query", but what should be done if
|
||||
|
|
@ -851,10 +1203,53 @@ _mesa_GetPerfQueryDataINTEL(GLuint queryHandle, GLuint flags,
|
|||
*
|
||||
* To resolve this, we just generate an INVALID_VALUE from an invalid query
|
||||
* handle.
|
||||
*
|
||||
* No queries are supported, so all handles are invalid.
|
||||
*/
|
||||
if (m == NULL) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetPerfQueryDataINTEL(invalid queryHandle)");
|
||||
return;
|
||||
}
|
||||
|
||||
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||
"glGetPerfQueryDataINTEL(invalid queryHandle)");
|
||||
/* We need at least enough room for a single value. */
|
||||
if (dataSize < sizeof(GLuint)) {
|
||||
*bytesWritten = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* The GL_INTEL_performance_query spec says:
|
||||
*
|
||||
* "The call may end without returning any data if they are not ready
|
||||
* for reading as the measurement session is still pending (the
|
||||
* EndPerfQueryINTEL() command processing is not finished by
|
||||
* hardware). In this case location pointed by the bytesWritten
|
||||
* parameter will be set to 0."
|
||||
*
|
||||
* If EndPerfQueryINTEL() is not called at all, we follow this.
|
||||
*/
|
||||
if (!m->Ended) {
|
||||
*bytesWritten = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
result_available = ctx->Driver.IsPerfMonitorResultAvailable(ctx, m);
|
||||
|
||||
if (!result_available) {
|
||||
if (flags == GL_PERFQUERY_FLUSH_INTEL) {
|
||||
ctx->Driver.Flush(ctx);
|
||||
} else if (flags == GL_PERFQUERY_WAIT_INTEL) {
|
||||
/* Assume Finish() is both enough and not too much to wait for
|
||||
* results. If results are still not available after Finish(), the
|
||||
* later code automatically bails out with 0 for bytesWritten.
|
||||
*/
|
||||
ctx->Driver.Finish(ctx);
|
||||
result_available =
|
||||
ctx->Driver.IsPerfMonitorResultAvailable(ctx, m);
|
||||
}
|
||||
}
|
||||
|
||||
if (result_available) {
|
||||
ctx->Driver.GetPerfMonitorResult(ctx, m, dataSize, data, (GLint*)bytesWritten);
|
||||
} else {
|
||||
*bytesWritten = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue