diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 0abebe79..e761cad2 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -8795,14 +8795,21 @@ fi # | * [#20776] Add stubs for QUERY_TYPE_SO_STATISTICS and QUERY_TYPE_SO_OVERFLOW # | # | Modified files: -# | * dlls/d3d10core/tests/device.c, dlls/d3d11/tests/d3d11.c, dlls/wined3d/query.c, include/wine/wined3d.h +# | * dlls/d3d10core/tests/device.c, dlls/d3d11/tests/d3d11.c, dlls/wined3d/context.c, dlls/wined3d/directx.c, +# | dlls/wined3d/query.c, dlls/wined3d/wined3d_gl.h, dlls/wined3d/wined3d_private.h, include/wine/wined3d.h # | if test "$enable_wined3d_QUERY_Stubs" -eq 1; then patch_apply wined3d-QUERY_Stubs/0001-wined3d-Add-stubs-for-QUERY_TYPE_SO_STATISTICS-and-Q.patch patch_apply wined3d-QUERY_Stubs/0002-d3d11-Add-dummy-support-for-D3D11_QUERY_PIPELINE_STA.patch + patch_apply wined3d-QUERY_Stubs/0003-wined3d-Don-t-leak-free_so_statistics_queries-on-dev.patch + patch_apply wined3d-QUERY_Stubs/0004-wined3d-Implement-WINED3D_QUERY_TYPE_PIPELINE_STATIS.patch + patch_apply wined3d-QUERY_Stubs/0005-d3d11-tests-Add-basic-test-for-D3D11_QUERY_PIPELINE_.patch ( printf '%s\n' '+ { "Michael Müller", "wined3d: Add stubs for QUERY_TYPE_SO_STATISTICS and QUERY_TYPE_SO_OVERFLOW.", 1 },'; printf '%s\n' '+ { "Michael Müller", "d3d11: Add dummy support for D3D11_QUERY_PIPELINE_STATISTICS query.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "wined3d: Don'\''t leak free_so_statistics_queries on device destruction.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "wined3d: Implement WINED3D_QUERY_TYPE_PIPELINE_STATISTICS.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "d3d11/tests: Add basic test for D3D11_QUERY_PIPELINE_STATISTICS.", 1 },'; ) >> "$patchlist" fi diff --git a/patches/wined3d-CSMT_Main/9999-IfDefined.patch b/patches/wined3d-CSMT_Main/9999-IfDefined.patch index 81c1bc7d..e0489bfe 100644 --- a/patches/wined3d-CSMT_Main/9999-IfDefined.patch +++ b/patches/wined3d-CSMT_Main/9999-IfDefined.patch @@ -622,7 +622,7 @@ diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -2727,6 +2727,16 @@ struct wined3d_state +@@ -2766,6 +2766,16 @@ struct wined3d_state struct wined3d_rasterizer_state *rasterizer_state; }; @@ -639,7 +639,7 @@ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h #define WINED3D_UNMAPPED_STAGE ~0u /* Multithreaded flag. Removed from the public header to signal that -@@ -2838,6 +2848,12 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL +@@ -2877,6 +2887,12 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; @@ -652,7 +652,7 @@ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) { -@@ -3025,7 +3041,11 @@ struct wined3d_texture +@@ -3064,7 +3080,11 @@ struct wined3d_texture unsigned int map_count; DWORD locations; @@ -664,7 +664,7 @@ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h } sub_resources[1]; }; -@@ -3340,6 +3360,9 @@ struct wined3d_cs_queue +@@ -3379,6 +3399,9 @@ struct wined3d_cs_queue struct wined3d_cs_ops { diff --git a/patches/wined3d-QUERY_Stubs/0003-wined3d-Don-t-leak-free_so_statistics_queries-on-dev.patch b/patches/wined3d-QUERY_Stubs/0003-wined3d-Don-t-leak-free_so_statistics_queries-on-dev.patch new file mode 100644 index 00000000..11c4c496 --- /dev/null +++ b/patches/wined3d-QUERY_Stubs/0003-wined3d-Don-t-leak-free_so_statistics_queries-on-dev.patch @@ -0,0 +1,24 @@ +From d9ca35b4d4489e101caa4950d086413a3a08a0e7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sun, 28 May 2017 03:59:24 +0200 +Subject: wined3d: Don't leak free_so_statistics_queries on device destruction. + +--- + dlls/wined3d/context.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index bdcdf007a42..8d674c1cf88 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -1343,6 +1343,7 @@ static void context_destroy_gl_resources(struct wined3d_context *context) + checkGLcall("context cleanup"); + } + ++ HeapFree(GetProcessHeap(), 0, context->free_so_statistics_queries); + HeapFree(GetProcessHeap(), 0, context->free_timestamp_queries); + HeapFree(GetProcessHeap(), 0, context->free_occlusion_queries); + HeapFree(GetProcessHeap(), 0, context->free_event_queries); +-- +2.12.2 + diff --git a/patches/wined3d-QUERY_Stubs/0004-wined3d-Implement-WINED3D_QUERY_TYPE_PIPELINE_STATIS.patch b/patches/wined3d-QUERY_Stubs/0004-wined3d-Implement-WINED3D_QUERY_TYPE_PIPELINE_STATIS.patch new file mode 100644 index 00000000..4d1077b7 --- /dev/null +++ b/patches/wined3d-QUERY_Stubs/0004-wined3d-Implement-WINED3D_QUERY_TYPE_PIPELINE_STATIS.patch @@ -0,0 +1,443 @@ +From f38e263c61ba7273b01fa0f9e82680e08f089d35 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sun, 28 May 2017 04:49:57 +0200 +Subject: wined3d: Implement WINED3D_QUERY_TYPE_PIPELINE_STATISTICS. + +--- + dlls/wined3d/context.c | 58 ++++++++++++ + dlls/wined3d/directx.c | 1 + + dlls/wined3d/query.c | 196 +++++++++++++++++++++++++++++++++++++++-- + dlls/wined3d/wined3d_gl.h | 1 + + dlls/wined3d/wined3d_private.h | 39 ++++++++ + 5 files changed, 286 insertions(+), 9 deletions(-) + +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index 8d674c1cf88..68c173344b0 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -940,6 +940,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, +@@ -1232,6 +1269,7 @@ static void context_destroy_gl_resources(struct wined3d_context *context) + { + const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_so_statistics_query *so_statistics_query; ++ struct wined3d_pipeline_statistics_query *pipeline_statistics_query; + struct wined3d_timestamp_query *timestamp_query; + struct wined3d_occlusion_query *occlusion_query; + struct wined3d_event_query *event_query; +@@ -1256,6 +1294,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) +@@ -1312,6 +1358,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)); + +@@ -1344,6 +1399,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); +@@ -1812,6 +1868,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 7a7fbe0578a..ee43cfac449 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 db747362ab5..bbeab020c27 100644 +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -61,6 +61,11 @@ 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]; +@@ -319,6 +324,9 @@ static void wined3d_query_destroy_object(void *object) + } + else if (query->type == WINED3D_QUERY_TYPE_PIPELINE_STATISTICS) + { ++ 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, query); + } + else +@@ -815,16 +823,179 @@ static BOOL wined3d_overflow_query_ops_issue(struct wined3d_query *query, DWORD + + 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); + +- return TRUE; ++ if (!(context = context_reacquire(device, pq->context))) ++ { ++ FIXME("%p Wrong thread, returning 0 primitives.\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.ia_vertices = result; ++ GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.primitives, GL_QUERY_RESULT, &result)); ++ pq->statistics.ia_primitives = 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.c_invocations = result; ++ GL_EXTCALL(glGetQueryObjectui64v(pq->u.query.clipping_output, GL_QUERY_RESULT, &result)); ++ pq->statistics.c_primitives = result; ++ } ++ else ++ { ++ GLuint result; ++ GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.vertices, GL_QUERY_RESULT, &result)); ++ pq->statistics.ia_vertices = result; ++ GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.primitives, GL_QUERY_RESULT, &result)); ++ pq->statistics.ia_primitives = 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.c_invocations = result; ++ GL_EXTCALL(glGetQueryObjectuiv(pq->u.query.clipping_output, GL_QUERY_RESULT, &result)); ++ pq->statistics.c_primitives = result; ++ } ++ ++done: ++ checkGLcall("poll pipeline statistics query"); ++ context_release(context); ++ return available; + } + + static BOOL wined3d_pipeline_query_ops_issue(struct wined3d_query *query, DWORD flags) + { +- FIXME("query %p, flags %#x.\n", query, 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; + +- return FALSE; ++ TRACE("query %p, flags %#x.\n", query, flags); ++ ++ if (flags & WINED3DISSUE_BEGIN) ++ { ++ if (pq->started) ++ { ++ if ((context = context_reacquire(device, pq->context))) ++ { ++ 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)); ++ } ++ 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))) ++ { ++ 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"); ++ ++ context_release(context); ++ poll = TRUE; ++ } ++ else ++ { ++ FIXME("Wrong thread, can't end query.\n"); ++ } ++ } ++ pq->started = FALSE; ++ } ++ ++ return poll; + } + + static const struct wined3d_query_ops event_query_ops = +@@ -1097,19 +1268,26 @@ 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) + { +- static const struct wined3d_query_data_pipeline_statistics data; +- struct wined3d_query *object; ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++ struct wined3d_pipeline_statistics_query *object; + +- FIXME("device %p, type %#x, parent %p, query %p.\n", device, type, parent, query); ++ 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 statistic queries.\n"); ++ return WINED3DERR_NOTAVAILABLE; ++ } + + if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) + return E_OUTOFMEMORY; + +- wined3d_query_init(object, device, type, &data, +- sizeof(data), &pipeline_query_ops, parent, parent_ops); ++ 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 = &object->query; + + return WINED3D_OK; + } +diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h +index fc4c1bb11f8..80fc6809238 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 183c856e07c..315e89d098b 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 */ +-- +2.12.2 + diff --git a/patches/wined3d-QUERY_Stubs/0005-d3d11-tests-Add-basic-test-for-D3D11_QUERY_PIPELINE_.patch b/patches/wined3d-QUERY_Stubs/0005-d3d11-tests-Add-basic-test-for-D3D11_QUERY_PIPELINE_.patch new file mode 100644 index 00000000..270107a1 --- /dev/null +++ b/patches/wined3d-QUERY_Stubs/0005-d3d11-tests-Add-basic-test-for-D3D11_QUERY_PIPELINE_.patch @@ -0,0 +1,107 @@ +From 4aefdfaa464c49aeece5e1803478a63bcdb55562 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sun, 28 May 2017 04:52:59 +0200 +Subject: d3d11/tests: Add basic test for D3D11_QUERY_PIPELINE_STATISTICS. + +--- + dlls/d3d11/tests/d3d11.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 77 insertions(+) + +diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c +index 5a14dd4d55c..8fe6835c831 100644 +--- a/dlls/d3d11/tests/d3d11.c ++++ b/dlls/d3d11/tests/d3d11.c +@@ -5380,6 +5380,82 @@ if (0) + release_test_context(&test_context); + } + ++static void test_pipeline_query(void) ++{ ++ static const struct vec4 red = {1.0f, 0.0f, 0.0f, 1.0f}; ++ static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; ++ ++ D3D11_QUERY_DATA_PIPELINE_STATISTICS data; ++ struct d3d11_test_context test_context; ++ ID3D11DeviceContext *context; ++ D3D11_QUERY_DESC query_desc; ++ ID3D11Asynchronous *query; ++ unsigned int data_size, i; ++ ID3D11Device *device; ++ HRESULT hr; ++ ++ if (!init_test_context(&test_context, NULL)) ++ return; ++ ++ device = test_context.device; ++ context = test_context.immediate_context; ++ ++ ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); ++ ++ query_desc.Query = D3D11_QUERY_PIPELINE_STATISTICS; ++ query_desc.MiscFlags = 0; ++ hr = ID3D11Device_CreateQuery(device, &query_desc, (ID3D11Query **)&query); ++ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ++ data_size = ID3D11Asynchronous_GetDataSize(query); ++ ok(data_size == sizeof(data), "Got unexpected data size %u.\n", data_size); ++ ++ memset(&data, 0xff, sizeof(data)); ++ hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0); ++ ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ++ hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(data), 0); ++ ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ++ ++ ID3D11DeviceContext_End(context, query); ++ ID3D11DeviceContext_Begin(context, query); ++ ID3D11DeviceContext_Begin(context, query); ++ ++ memset(&data, 0xff, sizeof(data)); ++ hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0); ++ todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ++ hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(data), 0); ++ todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); ++ ok(data.IAVertices == 0xffffffffffffffff, "Data was modified.\n"); ++ ++ draw_color_quad(&test_context, &red); ++ ++ ID3D11DeviceContext_End(context, query); ++ for (i = 0; i < 500; ++i) ++ { ++ if ((hr = ID3D11DeviceContext_GetData(context, query, NULL, 0, 0)) != S_FALSE) ++ break; ++ Sleep(10); ++ } ++ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ++ ++ memset(&data, 0xff, sizeof(data)); ++ hr = ID3D11DeviceContext_GetData(context, query, &data, sizeof(data), 0); ++ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); ++ ok(data.IAVertices == 4, "Got unexpected IAVertices count: %u\n", (unsigned int)data.IAVertices); ++ ok(data.IAPrimitives == 2, "Got unexpected IAPrimitives count: %u\n", (unsigned int)data.IAPrimitives); ++ ok(data.VSInvocations == 4, "Got unexpected VSInvocations count: %u\n", (unsigned int)data.VSInvocations); ++ ok(data.GSInvocations == 0, "Got unexpected GSInvocations count: %u\n", (unsigned int)data.GSInvocations); ++ ok(data.GSPrimitives == 0, "Got unexpected GSPrimitives count: %u\n", (unsigned int)data.GSPrimitives); ++ ok(data.CInvocations == 2, "Got unexpected CInvocations count: %u\n", (unsigned int)data.CInvocations); ++ ok(data.CPrimitives == 2, "Got unexpected CPrimitives count: %u\n", (unsigned int)data.CPrimitives); ++ ok(data.PSInvocations >= 640*480, "Got unexpected PSInvocations count: %u\n", (unsigned int)data.PSInvocations); ++ ok(data.HSInvocations == 0, "Got unexpected HSInvocations count: %u\n", (unsigned int)data.HSInvocations); ++ ok(data.DSInvocations == 0, "Got unexpected DSInvocations count: %u\n", (unsigned int)data.DSInvocations); ++ ok(data.CSInvocations == 0, "Got unexpected CSInvocations count: %u\n", (unsigned int)data.CSInvocations); ++ ++ ID3D11Asynchronous_Release(query); ++ release_test_context(&test_context); ++} ++ + static void test_timestamp_query(void) + { + static const struct vec4 red = {1.0f, 0.0f, 0.0f, 1.0f}; +@@ -21008,6 +21084,7 @@ START_TEST(d3d11) + test_create_rasterizer_state(); + test_create_query(); + test_occlusion_query(); ++ test_pipeline_query(); + test_timestamp_query(); + test_device_removed_reason(); + test_private_data(); +-- +2.12.2 + diff --git a/patches/wined3d-QUERY_Stubs/definition b/patches/wined3d-QUERY_Stubs/definition index 50d60a44..54815ada 100644 --- a/patches/wined3d-QUERY_Stubs/definition +++ b/patches/wined3d-QUERY_Stubs/definition @@ -1,2 +1,2 @@ Fixes: [20776] Add stubs for QUERY_TYPE_SO_STATISTICS and QUERY_TYPE_SO_OVERFLOW -Fixes: Add stub for QUERY_TYPE_PIPELINE_STATISTICS +Fixes: Add implementation for QUERY_TYPE_PIPELINE_STATISTICS