From: Dongwon Kim Date: Tue, 15 Oct 2019 19:43:04 +0000 (-0700) Subject: gallium: enable INTEL_PERFORMANCE_QUERY X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=106054ef79558699806b06a51e3d8cf2025ecbc4;p=mesa.git gallium: enable INTEL_PERFORMANCE_QUERY new state tracker APIs added for INTEL_performance_query This extension is enabled if all vendor specific functions for it exist. v2: add st_cb_perfquery.* to the list of sources in Makefile v3: minor code clean-up v4: - add driver hooks for intel-performance-query apis - add PIPE level performance counter and type enums that match to OpenGL enums - do conversion of pipe_perf_counter_type and pipe_perf_counter_data_type enums to GL defines in state_tracker Signed-off-by: Dongwon Kim Reviewed-by: Kenneth Graunke --- diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index b2a6622210f..b8051df57fe 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -191,6 +191,50 @@ struct pipe_context { */ void (*set_active_query_state)(struct pipe_context *pipe, bool enable); + /** + * INTEL Performance Query + */ + /*@{*/ + + unsigned (*init_intel_perf_query_info)(struct pipe_context *pipe); + + void (*get_intel_perf_query_info)(struct pipe_context *pipe, + unsigned query_index, + const char **name, + uint32_t *data_size, + uint32_t *n_counters, + uint32_t *n_active); + + void (*get_intel_perf_query_counter_info)(struct pipe_context *pipe, + unsigned query_index, + unsigned counter_index, + const char **name, + const char **desc, + uint32_t *offset, + uint32_t *data_size, + uint32_t *type_enum, + uint32_t *data_type_enum, + uint64_t *raw_max); + + struct pipe_query *(*new_intel_perf_query_obj)(struct pipe_context *pipe, + unsigned query_index); + + void (*begin_intel_perf_query)(struct pipe_context *pipe, struct pipe_query *q); + + void (*end_intel_perf_query)(struct pipe_context *pipe, struct pipe_query *q); + + void (*delete_intel_perf_query)(struct pipe_context *pipe, struct pipe_query *q); + + void (*wait_intel_perf_query)(struct pipe_context *pipe, struct pipe_query *q); + + bool (*is_intel_perf_query_ready)(struct pipe_context *pipe, struct pipe_query *q); + + void (*get_intel_perf_query_data)(struct pipe_context *pipe, + struct pipe_query *q, + size_t data_size, + uint32_t *data, + uint32_t *bytes_written); + /*@}*/ /** diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index ca98ee55e97..0f6229a57fb 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -1246,6 +1246,29 @@ enum pipe_debug_type PIPE_DEBUG_TYPE_CONFORMANCE, }; +/** + * counter type and counter data type enums used by INTEL_performance_query + * APIs in gallium drivers. + */ +enum pipe_perf_counter_type +{ + PIPE_PERF_COUNTER_TYPE_EVENT, + PIPE_PERF_COUNTER_TYPE_DURATION_NORM, + PIPE_PERF_COUNTER_TYPE_DURATION_RAW, + PIPE_PERF_COUNTER_TYPE_THROUGHPUT, + PIPE_PERF_COUNTER_TYPE_RAW, + PIPE_PERF_COUNTER_TYPE_TIMESTAMP, +}; + +enum pipe_perf_counter_data_type +{ + PIPE_PERF_COUNTER_DATA_TYPE_BOOL32, + PIPE_PERF_COUNTER_DATA_TYPE_UINT32, + PIPE_PERF_COUNTER_DATA_TYPE_UINT64, + PIPE_PERF_COUNTER_DATA_TYPE_FLOAT, + PIPE_PERF_COUNTER_DATA_TYPE_DOUBLE, +}; + #define PIPE_UUID_SIZE 16 #ifdef __cplusplus diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources index dfdff434c4d..e4252ce8006 100644 --- a/src/mesa/Makefile.sources +++ b/src/mesa/Makefile.sources @@ -483,6 +483,8 @@ STATETRACKER_FILES = \ state_tracker/st_cb_msaa.h \ state_tracker/st_cb_perfmon.c \ state_tracker/st_cb_perfmon.h \ + state_tracker/st_cb_perfquery.c \ + state_tracker/st_cb_perfquery.h \ state_tracker/st_cb_program.c \ state_tracker/st_cb_program.h \ state_tracker/st_cb_queryobj.c \ diff --git a/src/mesa/meson.build b/src/mesa/meson.build index 1254ccc619e..4651ef88d6a 100644 --- a/src/mesa/meson.build +++ b/src/mesa/meson.build @@ -527,6 +527,8 @@ files_libmesa_gallium = files( 'state_tracker/st_cb_msaa.h', 'state_tracker/st_cb_perfmon.c', 'state_tracker/st_cb_perfmon.h', + 'state_tracker/st_cb_perfquery.c', + 'state_tracker/st_cb_perfquery.h', 'state_tracker/st_cb_program.c', 'state_tracker/st_cb_program.h', 'state_tracker/st_cb_queryobj.c', diff --git a/src/mesa/state_tracker/st_cb_perfquery.c b/src/mesa/state_tracker/st_cb_perfquery.c new file mode 100644 index 00000000000..b405703e311 --- /dev/null +++ b/src/mesa/state_tracker/st_cb_perfquery.c @@ -0,0 +1,232 @@ +/* + * Copyright © 2019 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * Intel Performance query interface to gallium. + */ + +#include "st_debug.h" +#include "st_context.h" +#include "st_cb_bitmap.h" +#include "st_cb_perfquery.h" +#include "st_util.h" + +#include "util/bitset.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "util/u_memory.h" + +bool +st_have_perfquery(struct st_context *st) +{ + struct pipe_context *pipe = st->pipe; + + return pipe->init_intel_perf_query_info && pipe->get_intel_perf_query_info && + pipe->get_intel_perf_query_counter_info && + pipe->new_intel_perf_query_obj && pipe->begin_intel_perf_query && + pipe->end_intel_perf_query && pipe->delete_intel_perf_query && + pipe->wait_intel_perf_query && pipe->is_intel_perf_query_ready && + pipe->get_intel_perf_query_data; +} + +static unsigned +st_InitPerfQueryInfo(struct gl_context *ctx) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + return pipe->init_intel_perf_query_info(pipe); +} + +static void +st_GetPerfQueryInfo(struct gl_context *ctx, + unsigned query_index, + const char **name, + GLuint *data_size, + GLuint *n_counters, + GLuint *n_active) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + pipe->get_intel_perf_query_info(pipe, query_index, name, data_size, + n_counters, n_active); +} + +static uint32_t +pipe_counter_type_enum_to_gl_type(enum pipe_perf_counter_type type) +{ + switch (type) { + case PIPE_PERF_COUNTER_TYPE_EVENT: return GL_PERFQUERY_COUNTER_EVENT_INTEL; + case PIPE_PERF_COUNTER_TYPE_DURATION_NORM: return GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL; + case PIPE_PERF_COUNTER_TYPE_DURATION_RAW: return GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL; + case PIPE_PERF_COUNTER_TYPE_THROUGHPUT: return GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL; + case PIPE_PERF_COUNTER_TYPE_RAW: return GL_PERFQUERY_COUNTER_RAW_INTEL; + case PIPE_PERF_COUNTER_TYPE_TIMESTAMP: return GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL; + default: + unreachable("Unknown counter type"); + } +} + +static uint32_t +pipe_counter_data_type_to_gl_type(enum pipe_perf_counter_data_type type) +{ + switch (type) { + case PIPE_PERF_COUNTER_DATA_TYPE_BOOL32: return GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL; + case PIPE_PERF_COUNTER_DATA_TYPE_UINT32: return GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL; + case PIPE_PERF_COUNTER_DATA_TYPE_UINT64: return GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL; + case PIPE_PERF_COUNTER_DATA_TYPE_FLOAT: return GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL; + case PIPE_PERF_COUNTER_DATA_TYPE_DOUBLE: return GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL; + default: + unreachable("Unknown counter data type"); + } +} + +static void +st_GetPerfCounterInfo(struct gl_context *ctx, + unsigned query_index, + unsigned counter_index, + const char **name, + const char **desc, + GLuint *offset, + GLuint *data_size, + GLuint *type_enum, + GLuint *data_type_enum, + GLuint64 *raw_max) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + uint32_t pipe_type_enum; + uint32_t pipe_data_type_enum; + + pipe->get_intel_perf_query_counter_info(pipe, query_index, counter_index, + name, desc, offset, data_size, + &pipe_type_enum, &pipe_data_type_enum, raw_max); + *type_enum = pipe_counter_type_enum_to_gl_type(pipe_type_enum); + *data_type_enum = pipe_counter_data_type_to_gl_type(pipe_data_type_enum); +} + +static void +st_DeletePerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + /* We can assume that the frontend waits for a query to complete + * before ever calling into here, so we don't have to worry about + * deleting an in-flight query object. + */ + assert(!o->Active); + assert(!o->Used || o->Ready); + + pipe->delete_intel_perf_query(pipe, (struct pipe_query *)o); +} + +static bool +st_BeginPerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + /* We can assume the frontend hides mistaken attempts to Begin a + * query object multiple times before its End. Similarly if an + * application reuses a query object before results have arrived + * the frontend will wait for prior results so we don't need + * to support abandoning in-flight results. + */ + assert(!o->Active); + assert(!o->Used || o->Ready); /* no in-flight query to worry about */ + + pipe->begin_intel_perf_query(pipe, (struct pipe_query *)o); + + return true; +} + +static void +st_EndPerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + pipe->end_intel_perf_query(pipe, (struct pipe_query *)o); +} + +static void +st_WaitPerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + assert(!o->Ready); + + pipe->wait_intel_perf_query(pipe, (struct pipe_query *)o); +} + +static bool +st_IsPerfQueryReady(struct gl_context *ctx, struct gl_perf_query_object *o) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + if (o->Ready) + return true; + + return pipe->is_intel_perf_query_ready(pipe, (struct pipe_query *)o); +} + +static void +st_GetPerfQueryData(struct gl_context *ctx, + struct gl_perf_query_object *o, + GLsizei data_size, + GLuint *data, + GLuint *bytes_written) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + + assert(st_IsPerfQueryReady(ctx, o)); + + /* We expect that the frontend only calls this hook when it knows + * that results are available. + */ + assert(o->Ready); + + pipe->get_intel_perf_query_data(pipe, (struct pipe_query *)o, data_size, data, + bytes_written); +} + +static struct gl_perf_query_object * +st_NewPerfQueryObject(struct gl_context *ctx, unsigned query_index) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + struct pipe_query *q; + + q = pipe->new_intel_perf_query_obj(pipe, query_index); + + return (struct gl_perf_query_object *)q; +} + +void st_init_perfquery_functions(struct dd_function_table *functions) +{ + functions->InitPerfQueryInfo = st_InitPerfQueryInfo; + functions->GetPerfQueryInfo = st_GetPerfQueryInfo; + functions->GetPerfCounterInfo = st_GetPerfCounterInfo; + functions->NewPerfQueryObject = st_NewPerfQueryObject; + functions->DeletePerfQuery = st_DeletePerfQuery; + functions->BeginPerfQuery = st_BeginPerfQuery; + functions->EndPerfQuery = st_EndPerfQuery; + functions->WaitPerfQuery = st_WaitPerfQuery; + functions->IsPerfQueryReady = st_IsPerfQueryReady; + functions->GetPerfQueryData = st_GetPerfQueryData; +} diff --git a/src/mesa/state_tracker/st_cb_perfquery.h b/src/mesa/state_tracker/st_cb_perfquery.h new file mode 100644 index 00000000000..1fbcd74f859 --- /dev/null +++ b/src/mesa/state_tracker/st_cb_perfquery.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2019 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef ST_CB_PERFQUERY_H +#define ST_CB_PERFQUERY_H + +bool +st_have_perfquery(struct st_context *st); + +extern void +st_init_perfquery_functions(struct dd_function_table *functions); + +#endif diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index e13bc71d185..c45c7f7e5fb 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -57,6 +57,7 @@ #include "st_cb_memoryobjects.h" #include "st_cb_msaa.h" #include "st_cb_perfmon.h" +#include "st_cb_perfquery.h" #include "st_cb_program.h" #include "st_cb_queryobj.h" #include "st_cb_readpixels.h" @@ -720,6 +721,10 @@ st_create_context_priv(struct gl_context *ctx, struct pipe_context *pipe, ctx->Extensions.AMD_performance_monitor = GL_TRUE; } + if (st_have_perfquery(st)) { + ctx->Extensions.INTEL_performance_query = GL_TRUE; + } + /* Enable shader-based fallbacks for ARB_color_buffer_float if needed. */ if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) { if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) { @@ -886,6 +891,7 @@ st_init_driver_functions(struct pipe_screen *screen, st_init_memoryobject_functions(functions); st_init_msaa_functions(functions); st_init_perfmon_functions(functions); + st_init_perfquery_functions(functions); st_init_program_functions(functions); st_init_query_functions(functions); st_init_cond_render_functions(functions);