[PATCH 1/6] wined3d: Implement WINED3D_QUERY_TYPE_PIPELINE_STATISTICS.

Józef Kucia jkucia at codeweavers.com
Sun Jun 4 17:47:34 CDT 2017


From: Michael Müller <michael at fds-team.de>

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---

With some modifications.

I should submit fixes for the D3D10 version of the query in the next series.

---
 dlls/d3d10core/tests/device.c  |   2 +-
 dlls/d3d11/tests/d3d11.c       |   2 +-
 dlls/wined3d/context.c         |  58 +++++++++++
 dlls/wined3d/directx.c         |   1 +
 dlls/wined3d/query.c           | 227 +++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/wined3d_gl.h      |   1 +
 dlls/wined3d/wined3d_private.h |  39 +++++++
 include/wine/wined3d.h         |  15 +++
 8 files changed, 343 insertions(+), 2 deletions(-)

diff --git a/dlls/d3d10core/tests/device.c b/dlls/d3d10core/tests/device.c
index 364a2ab..311ffeb 100644
--- a/dlls/d3d10core/tests/device.c
+++ b/dlls/d3d10core/tests/device.c
@@ -3824,7 +3824,7 @@ static void test_create_query(void)
         {D3D10_QUERY_OCCLUSION,             FALSE, FALSE},
         {D3D10_QUERY_TIMESTAMP,             FALSE, FALSE},
         {D3D10_QUERY_TIMESTAMP_DISJOINT,    FALSE, FALSE},
-        {D3D10_QUERY_PIPELINE_STATISTICS,   FALSE, TRUE},
+        {D3D10_QUERY_PIPELINE_STATISTICS,   FALSE, FALSE},
         {D3D10_QUERY_OCCLUSION_PREDICATE,   TRUE,  FALSE},
         {D3D10_QUERY_SO_STATISTICS,         FALSE, TRUE},
         {D3D10_QUERY_SO_OVERFLOW_PREDICATE, TRUE,  TRUE},
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c
index 84ffe4e..addc3ee 100644
--- a/dlls/d3d11/tests/d3d11.c
+++ b/dlls/d3d11/tests/d3d11.c
@@ -4598,7 +4598,7 @@ static void test_create_query(void)
         {D3D11_QUERY_OCCLUSION,                     D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, FALSE},
         {D3D11_QUERY_TIMESTAMP,                     D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, FALSE},
         {D3D11_QUERY_TIMESTAMP_DISJOINT,            D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, FALSE},
-        {D3D11_QUERY_PIPELINE_STATISTICS,           D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, TRUE},
+        {D3D11_QUERY_PIPELINE_STATISTICS,           D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, FALSE},
         {D3D11_QUERY_OCCLUSION_PREDICATE,           D3D_FEATURE_LEVEL_10_0, TRUE,  TRUE,  FALSE},
         {D3D11_QUERY_SO_STATISTICS,                 D3D_FEATURE_LEVEL_10_0, FALSE, FALSE, TRUE},
         {D3D11_QUERY_SO_OVERFLOW_PREDICATE,         D3D_FEATURE_LEVEL_10_0, TRUE,  TRUE,  TRUE},
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 8ab0e10..0f60542 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -933,6 +933,43 @@ void context_free_so_statistics_query(struct wined3d_so_statistics_query *query)
     context->free_so_statistics_queries[context->free_so_statistics_query_count++] = query->u;
 }
 
+void context_alloc_pipeline_statistics_query(struct wined3d_context *context,
+        struct wined3d_pipeline_statistics_query *query)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (context->free_pipeline_statistics_query_count)
+    {
+        query->u = context->free_pipeline_statistics_queries[--context->free_pipeline_statistics_query_count];
+    }
+    else
+    {
+        GL_EXTCALL(glGenQueries(ARRAY_SIZE(query->u.id), query->u.id));
+        checkGLcall("glGenQueries");
+    }
+
+    query->context = context;
+    list_add_head(&context->pipeline_statistics_queries, &query->entry);
+}
+
+void context_free_pipeline_statistics_query(struct wined3d_pipeline_statistics_query *query)
+{
+    struct wined3d_context *context = query->context;
+
+    list_remove(&query->entry);
+    query->context = NULL;
+
+    if (!wined3d_array_reserve((void **)&context->free_pipeline_statistics_queries,
+            &context->free_pipeline_statistics_query_size, context->free_pipeline_statistics_query_count + 1,
+            sizeof(*context->free_pipeline_statistics_queries)))
+    {
+        ERR("Failed to grow free list, leaking GL queries in context %p.\n", context);
+        return;
+    }
+
+    context->free_pipeline_statistics_queries[context->free_pipeline_statistics_query_count++] = query->u;
+}
+
 typedef void (context_fbo_entry_func_t)(struct wined3d_context *context, struct fbo_entry *entry);
 
 static void context_enum_fbo_entries(const struct wined3d_device *device,
@@ -1223,6 +1260,7 @@ static void context_update_window(struct wined3d_context *context)
 
 static void context_destroy_gl_resources(struct wined3d_context *context)
 {
+    struct wined3d_pipeline_statistics_query *pipeline_statistics_query;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct wined3d_so_statistics_query *so_statistics_query;
     struct wined3d_timestamp_query *timestamp_query;
@@ -1249,6 +1287,14 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
         so_statistics_query->context = NULL;
     }
 
+    LIST_FOR_EACH_ENTRY(pipeline_statistics_query, &context->pipeline_statistics_queries,
+            struct wined3d_pipeline_statistics_query, entry)
+    {
+        if (context->valid)
+            GL_EXTCALL(glDeleteQueries(ARRAY_SIZE(pipeline_statistics_query->u.id), pipeline_statistics_query->u.id));
+        pipeline_statistics_query->context = NULL;
+    }
+
     LIST_FOR_EACH_ENTRY(timestamp_query, &context->timestamp_queries, struct wined3d_timestamp_query, entry)
     {
         if (context->valid)
@@ -1305,6 +1351,15 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
             }
         }
 
+        if (gl_info->supported[ARB_PIPELINE_STATISTICS_QUERY])
+        {
+            for (i = 0; i < context->free_pipeline_statistics_query_count; ++i)
+            {
+                union wined3d_gl_pipeline_statistics_query *q = &context->free_pipeline_statistics_queries[i];
+                GL_EXTCALL(glDeleteQueries(ARRAY_SIZE(q->id), q->id));
+            }
+        }
+
         if (gl_info->supported[ARB_TIMER_QUERY])
             GL_EXTCALL(glDeleteQueries(context->free_timestamp_query_count, context->free_timestamp_queries));
 
@@ -1337,6 +1392,7 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
     }
 
     HeapFree(GetProcessHeap(), 0, context->free_so_statistics_queries);
+    HeapFree(GetProcessHeap(), 0, context->free_pipeline_statistics_queries);
     HeapFree(GetProcessHeap(), 0, context->free_timestamp_queries);
     HeapFree(GetProcessHeap(), 0, context->free_occlusion_queries);
     HeapFree(GetProcessHeap(), 0, context->free_event_queries);
@@ -1801,6 +1857,8 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
 
     list_init(&ret->so_statistics_queries);
 
+    list_init(&ret->pipeline_statistics_queries);
+
     list_init(&ret->fbo_list);
     list_init(&ret->fbo_destroy_list);
 
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 9614e16..7ad944f 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -144,6 +144,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ARB_multisample",                  ARB_MULTISAMPLE               },
     {"GL_ARB_multitexture",                 ARB_MULTITEXTURE              },
     {"GL_ARB_occlusion_query",              ARB_OCCLUSION_QUERY           },
+    {"GL_ARB_pipeline_statistics_query",    ARB_PIPELINE_STATISTICS_QUERY },
     {"GL_ARB_pixel_buffer_object",          ARB_PIXEL_BUFFER_OBJECT       },
     {"GL_ARB_point_parameters",             ARB_POINT_PARAMETERS          },
     {"GL_ARB_point_sprite",                 ARB_POINT_SPRITE              },
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index 5587113..cf12c74 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -61,6 +61,12 @@ static struct wined3d_so_statistics_query *wined3d_so_statistics_query_from_quer
     return CONTAINING_RECORD(query, struct wined3d_so_statistics_query, query);
 }
 
+static struct wined3d_pipeline_statistics_query *wined3d_pipeline_statistics_query_from_query(
+        struct wined3d_query *query)
+{
+    return CONTAINING_RECORD(query, struct wined3d_pipeline_statistics_query, query);
+}
+
 BOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info)
 {
     return gl_info->supported[ARB_SYNC] || gl_info->supported[NV_FENCE] || gl_info->supported[APPLE_FENCE];
@@ -729,6 +735,181 @@ static BOOL wined3d_so_statistics_query_ops_issue(struct wined3d_query *query, D
     return poll;
 }
 
+static BOOL wined3d_pipeline_query_ops_poll(struct wined3d_query *query, DWORD flags)
+{
+    struct wined3d_pipeline_statistics_query *pq = wined3d_pipeline_statistics_query_from_query(query);
+    struct wined3d_device *device = query->device;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    GLuint available;
+    int i;
+
+    TRACE("query %p, flags %#x.\n", query, flags);
+
+    if (!(context = context_reacquire(device, pq->context)))
+    {
+        FIXME("%p Wrong thread.\n", query);
+        memset(&pq->statistics, 0, sizeof(pq->statistics));
+        return TRUE;
+    }
+    gl_info = context->gl_info;
+
+    for (i = 0; i < ARRAY_SIZE(pq->u.id); ++i)
+    {
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.id[i], GL_QUERY_RESULT_AVAILABLE, &available));
+        if (!available)
+            goto done;
+    }
+
+    if (gl_info->supported[ARB_TIMER_QUERY])
+    {
+        GLuint64 result;
+        GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.vertices, GL_QUERY_RESULT, &result));
+        pq->statistics.vertices_submitted = result;
+        GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.primitives, GL_QUERY_RESULT, &result));
+        pq->statistics.primitives_submitted = result;
+        GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.vertex_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.vs_invocations = result;
+        GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.tess_control_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.hs_invocations = result;
+        GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.tess_eval_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.ds_invocations = result;
+        GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.geometry_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.gs_invocations = result;
+        GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.geometry_primitives, GL_QUERY_RESULT, &result));
+        pq->statistics.gs_primitives = result;
+        GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.fragment_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.ps_invocations = result;
+        GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.compute_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.cs_invocations = result;
+        GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.clipping_input, GL_QUERY_RESULT, &result));
+        pq->statistics.clipping_input_primitives = result;
+        GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.clipping_output, GL_QUERY_RESULT, &result));
+        pq->statistics.clipping_output_primitives = result;
+    }
+    else
+    {
+        GLuint result;
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.vertices, GL_QUERY_RESULT, &result));
+        pq->statistics.vertices_submitted = result;
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.primitives, GL_QUERY_RESULT, &result));
+        pq->statistics.primitives_submitted = result;
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.vertex_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.vs_invocations = result;
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.tess_control_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.hs_invocations = result;
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.tess_eval_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.ds_invocations = result;
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.geometry_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.gs_invocations = result;
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.geometry_primitives, GL_QUERY_RESULT, &result));
+        pq->statistics.gs_primitives = result;
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.fragment_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.ps_invocations = result;
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.compute_shader, GL_QUERY_RESULT, &result));
+        pq->statistics.cs_invocations = result;
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.clipping_input, GL_QUERY_RESULT, &result));
+        pq->statistics.clipping_input_primitives = result;
+        GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.clipping_output, GL_QUERY_RESULT, &result));
+        pq->statistics.clipping_output_primitives = result;
+    }
+
+done:
+    checkGLcall("poll pipeline statistics query");
+    context_release(context);
+    return available;
+}
+
+static void wined3d_pipeline_statistics_query_end(struct wined3d_pipeline_statistics_query *query,
+        struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    GL_EXTCALL(glEndQuery(GL_VERTICES_SUBMITTED_ARB));
+    GL_EXTCALL(glEndQuery(GL_PRIMITIVES_SUBMITTED_ARB));
+    GL_EXTCALL(glEndQuery(GL_VERTEX_SHADER_INVOCATIONS_ARB));
+    GL_EXTCALL(glEndQuery(GL_TESS_CONTROL_SHADER_PATCHES_ARB));
+    GL_EXTCALL(glEndQuery(GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB));
+    GL_EXTCALL(glEndQuery(GL_GEOMETRY_SHADER_INVOCATIONS));
+    GL_EXTCALL(glEndQuery(GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB));
+    GL_EXTCALL(glEndQuery(GL_FRAGMENT_SHADER_INVOCATIONS_ARB));
+    GL_EXTCALL(glEndQuery(GL_COMPUTE_SHADER_INVOCATIONS_ARB));
+    GL_EXTCALL(glEndQuery(GL_CLIPPING_INPUT_PRIMITIVES_ARB));
+    GL_EXTCALL(glEndQuery(GL_CLIPPING_OUTPUT_PRIMITIVES_ARB));
+    checkGLcall("end query");
+}
+
+static BOOL wined3d_pipeline_query_ops_issue(struct wined3d_query *query, DWORD flags)
+{
+    struct wined3d_pipeline_statistics_query *pq = wined3d_pipeline_statistics_query_from_query(query);
+    struct wined3d_device *device = query->device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct wined3d_context *context;
+    BOOL poll = FALSE;
+
+    TRACE("query %p, flags %#x.\n", query, flags);
+
+    if (flags & WINED3DISSUE_BEGIN)
+    {
+        if (pq->started)
+        {
+            if ((context = context_reacquire(device, pq->context)))
+            {
+                wined3d_pipeline_statistics_query_end(pq, context);
+            }
+            else
+            {
+                FIXME("Wrong thread, can't restart query.\n");
+                context_free_pipeline_statistics_query(pq);
+                context = context_acquire(device, NULL, 0);
+                context_alloc_pipeline_statistics_query(context, pq);
+            }
+        }
+        else
+        {
+            if (pq->context)
+                context_free_pipeline_statistics_query(pq);
+            context = context_acquire(device, NULL, 0);
+            context_alloc_pipeline_statistics_query(context, pq);
+        }
+
+        GL_EXTCALL(glBeginQuery(GL_VERTICES_SUBMITTED_ARB, pq->u.query.vertices));
+        GL_EXTCALL(glBeginQuery(GL_PRIMITIVES_SUBMITTED_ARB, pq->u.query.primitives));
+        GL_EXTCALL(glBeginQuery(GL_VERTEX_SHADER_INVOCATIONS_ARB, pq->u.query.vertex_shader));
+        GL_EXTCALL(glBeginQuery(GL_TESS_CONTROL_SHADER_PATCHES_ARB, pq->u.query.tess_control_shader));
+        GL_EXTCALL(glBeginQuery(GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB, pq->u.query.tess_eval_shader));
+        GL_EXTCALL(glBeginQuery(GL_GEOMETRY_SHADER_INVOCATIONS, pq->u.query.geometry_shader));
+        GL_EXTCALL(glBeginQuery(GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB, pq->u.query.geometry_primitives));
+        GL_EXTCALL(glBeginQuery(GL_FRAGMENT_SHADER_INVOCATIONS_ARB, pq->u.query.fragment_shader));
+        GL_EXTCALL(glBeginQuery(GL_COMPUTE_SHADER_INVOCATIONS_ARB, pq->u.query.compute_shader));
+        GL_EXTCALL(glBeginQuery(GL_CLIPPING_INPUT_PRIMITIVES_ARB, pq->u.query.clipping_input));
+        GL_EXTCALL(glBeginQuery(GL_CLIPPING_OUTPUT_PRIMITIVES_ARB, pq->u.query.clipping_output));
+        checkGLcall("begin query");
+
+        context_release(context);
+        pq->started = TRUE;
+    }
+    if (flags & WINED3DISSUE_END)
+    {
+        if (pq->started)
+        {
+            if ((context = context_reacquire(device, pq->context)))
+            {
+                wined3d_pipeline_statistics_query_end(pq, context);
+                context_release(context);
+                poll = TRUE;
+            }
+            else
+            {
+                FIXME("Wrong thread, can't end query.\n");
+            }
+        }
+        pq->started = FALSE;
+    }
+
+    return poll;
+}
+
 static void wined3d_event_query_ops_destroy(struct wined3d_query *query)
 {
     struct wined3d_event_query *event_query = wined3d_event_query_from_query(query);
@@ -981,6 +1162,49 @@ static HRESULT wined3d_so_statistics_query_create(struct wined3d_device *device,
     return WINED3D_OK;
 }
 
+static void wined3d_pipeline_query_ops_destroy(struct wined3d_query *query)
+{
+    struct wined3d_pipeline_statistics_query *pq = wined3d_pipeline_statistics_query_from_query(query);
+    if (pq->context)
+        context_free_pipeline_statistics_query(pq);
+    HeapFree(GetProcessHeap(), 0, pq);
+}
+
+static const struct wined3d_query_ops pipeline_query_ops =
+{
+    wined3d_pipeline_query_ops_poll,
+    wined3d_pipeline_query_ops_issue,
+    wined3d_pipeline_query_ops_destroy,
+};
+
+static HRESULT wined3d_pipeline_query_create(struct wined3d_device *device,
+        enum wined3d_query_type type, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_query **query)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct wined3d_pipeline_statistics_query *object;
+
+    TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
+            device, type, parent, parent_ops, query);
+
+    if (!gl_info->supported[ARB_PIPELINE_STATISTICS_QUERY])
+    {
+        WARN("OpenGL implementation does not support pipeline statistics queries.\n");
+        return WINED3DERR_NOTAVAILABLE;
+    }
+
+    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    wined3d_query_init(&object->query, device, type, &object->statistics,
+            sizeof(object->statistics), &pipeline_query_ops, parent, parent_ops);
+
+    TRACE("Created query %p.\n", object);
+    *query = &object->query;
+
+    return WINED3D_OK;
+}
+
 HRESULT CDECL wined3d_query_create(struct wined3d_device *device, enum wined3d_query_type type,
         void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_query **query)
 {
@@ -1008,6 +1232,9 @@ HRESULT CDECL wined3d_query_create(struct wined3d_device *device, enum wined3d_q
         case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
             return wined3d_so_statistics_query_create(device, type, parent, parent_ops, query);
 
+        case WINED3D_QUERY_TYPE_PIPELINE_STATISTICS:
+            return wined3d_pipeline_query_create(device, type, parent, parent_ops, query);
+
         default:
             FIXME("Unhandled query type %#x.\n", type);
             return WINED3DERR_NOTAVAILABLE;
diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h
index 3806869..8b25220 100644
--- a/dlls/wined3d/wined3d_gl.h
+++ b/dlls/wined3d/wined3d_gl.h
@@ -78,6 +78,7 @@ enum wined3d_gl_extension
     ARB_MULTISAMPLE,
     ARB_MULTITEXTURE,
     ARB_OCCLUSION_QUERY,
+    ARB_PIPELINE_STATISTICS_QUERY,
     ARB_PIXEL_BUFFER_OBJECT,
     ARB_POINT_PARAMETERS,
     ARB_POINT_SPRITE,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 1810985..1025c98 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1721,6 +1721,40 @@ void context_alloc_so_statistics_query(struct wined3d_context *context,
         struct wined3d_so_statistics_query *query) DECLSPEC_HIDDEN;
 void context_free_so_statistics_query(struct wined3d_so_statistics_query *query) DECLSPEC_HIDDEN;
 
+union wined3d_gl_pipeline_statistics_query
+{
+    GLuint id[11];
+    struct
+    {
+        GLuint vertices;
+        GLuint primitives;
+        GLuint vertex_shader;
+        GLuint tess_control_shader;
+        GLuint tess_eval_shader;
+        GLuint geometry_shader;
+        GLuint geometry_primitives;
+        GLuint fragment_shader;
+        GLuint compute_shader;
+        GLuint clipping_input;
+        GLuint clipping_output;
+    } query;
+};
+
+struct wined3d_pipeline_statistics_query
+{
+    struct wined3d_query query;
+
+    struct list entry;
+    union wined3d_gl_pipeline_statistics_query u;
+    struct wined3d_context *context;
+    struct wined3d_query_data_pipeline_statistics statistics;
+    BOOL started;
+};
+
+void context_alloc_pipeline_statistics_query(struct wined3d_context *context,
+        struct wined3d_pipeline_statistics_query *query) DECLSPEC_HIDDEN;
+void context_free_pipeline_statistics_query(struct wined3d_pipeline_statistics_query *query) DECLSPEC_HIDDEN;
+
 struct wined3d_gl_view
 {
     GLenum target;
@@ -1857,6 +1891,11 @@ struct wined3d_context
     unsigned int free_so_statistics_query_count;
     struct list so_statistics_queries;
 
+    union wined3d_gl_pipeline_statistics_query *free_pipeline_statistics_queries;
+    SIZE_T free_pipeline_statistics_query_size;
+    unsigned int free_pipeline_statistics_query_count;
+    struct list pipeline_statistics_queries;
+
     struct wined3d_stream_info stream_info;
 
     /* Fences for GL_APPLE_flush_buffer_range */
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 8ead497..7a64608 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -726,6 +726,21 @@ struct wined3d_query_data_so_statistics
     UINT64 primitives_generated;
 };
 
+struct wined3d_query_data_pipeline_statistics
+{
+    UINT64 vertices_submitted;
+    UINT64 primitives_submitted;
+    UINT64 vs_invocations;
+    UINT64 gs_invocations;
+    UINT64 gs_primitives;
+    UINT64 clipping_input_primitives;
+    UINT64 clipping_output_primitives;
+    UINT64 ps_invocations;
+    UINT64 hs_invocations;
+    UINT64 ds_invocations;
+    UINT64 cs_invocations;
+};
+
 #define WINED3DISSUE_BEGIN                                      (1u << 1)
 #define WINED3DISSUE_END                                        (1u << 0)
 #define WINED3DGETDATA_FLUSH                                    (1u << 0)
-- 
2.10.2




More information about the wine-patches mailing list