1
/**************************************************************************
3
* Copyright 2012-2021 VMware, Inc.
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the
8
* "Software"), to deal in the Software without restriction, including
9
* without limitation the rights to use, copy, modify, merge, publish,
10
* distribute, sub license, and/or sell copies of the Software, and to
11
* permit persons to whom the Software is furnished to do so, subject to
12
* the following conditions:
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
* USE OR OTHER DEALINGS IN THE SOFTWARE.
22
* The above copyright notice and this permission notice (including the
23
* next paragraph) shall be included in all copies or substantial portions
26
**************************************************************************/
30
* Functions that manipulate query resources.
41
* ----------------------------------------------------------------------
43
* CalcPrivateQuerySize --
45
* The CalcPrivateQuerySize function determines the size of the
46
* user-mode display driver's private region of memory (that is,
47
* the size of internal driver structures, not the size of the
48
* resource video memory) for a query.
50
* ----------------------------------------------------------------------
54
CalcPrivateQuerySize(D3D10DDI_HDEVICE hDevice, // IN
55
__in const D3D10DDIARG_CREATEQUERY *pCreateQuery) // IN
62
TranslateQueryType(D3D10DDI_QUERY query)
65
case D3D10DDI_QUERY_EVENT:
66
return PIPE_QUERY_GPU_FINISHED;
67
case D3D10DDI_QUERY_OCCLUSION:
68
return PIPE_QUERY_OCCLUSION_COUNTER;
69
case D3D10DDI_QUERY_TIMESTAMP:
70
return PIPE_QUERY_TIMESTAMP;
71
case D3D10DDI_QUERY_TIMESTAMPDISJOINT:
72
return PIPE_QUERY_TIMESTAMP_DISJOINT;
73
case D3D10DDI_QUERY_PIPELINESTATS:
74
return PIPE_QUERY_PIPELINE_STATISTICS;
75
case D3D10DDI_QUERY_OCCLUSIONPREDICATE:
76
return PIPE_QUERY_OCCLUSION_PREDICATE;
77
case D3D10DDI_QUERY_STREAMOUTPUTSTATS:
78
return PIPE_QUERY_SO_STATISTICS;
79
case D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE:
80
return PIPE_QUERY_SO_OVERFLOW_PREDICATE;
82
LOG_UNSUPPORTED(TRUE);
83
return PIPE_QUERY_TYPES;
89
* ----------------------------------------------------------------------
93
* The CreateQuery function creates driver-side resources for a
94
* query that the Microsoft Direct3D runtime subsequently issues
97
* ----------------------------------------------------------------------
101
CreateQuery(D3D10DDI_HDEVICE hDevice, // IN
102
__in const D3D10DDIARG_CREATEQUERY *pCreateQuery, // IN
103
D3D10DDI_HQUERY hQuery, // IN
104
D3D10DDI_HRTQUERY hRTQuery) // IN
108
Device *pDevice = CastDevice(hDevice);
109
struct pipe_context *pipe = pDevice->pipe;
111
Query *pQuery = CastQuery(hQuery);
112
memset(pQuery, 0, sizeof *pQuery);
114
pQuery->Type = pCreateQuery->Query;
115
pQuery->Flags = pCreateQuery->MiscFlags;
117
pQuery->pipe_type = TranslateQueryType(pCreateQuery->Query);
118
if (pQuery->pipe_type < PIPE_QUERY_TYPES) {
119
pQuery->handle = pipe->create_query(pipe, pQuery->pipe_type, 0);
125
* ----------------------------------------------------------------------
129
* The DestroyQuery function releases resources for a query.
131
* ----------------------------------------------------------------------
135
DestroyQuery(D3D10DDI_HDEVICE hDevice, // IN
136
D3D10DDI_HQUERY hQuery) // IN
140
struct pipe_context *pipe = CastPipeContext(hDevice);
141
Query *pQuery = CastQuery(hQuery);
143
if (pQuery->handle) {
144
pipe->destroy_query(pipe, pQuery->handle);
150
* ----------------------------------------------------------------------
154
* The QueryBegin function marks the beginning of a sequence of
155
* graphics commands for a query and transitions the query to the
158
* ----------------------------------------------------------------------
162
QueryBegin(D3D10DDI_HDEVICE hDevice, // IN
163
D3D10DDI_HQUERY hQuery) // IN
167
Device *pDevice = CastDevice(hDevice);
168
struct pipe_context *pipe = pDevice->pipe;
170
Query *pQuery = CastQuery(hQuery);
171
struct pipe_query *state = CastPipeQuery(hQuery);
174
assert(pQuery->pipe_type < PIPE_QUERY_TYPES);
175
pipe->begin_query(pipe, state);
181
* ----------------------------------------------------------------------
185
* The QueryEnd function marks the end of a sequence of graphics
186
* commands for a query and transitions the query to the
189
* ----------------------------------------------------------------------
193
QueryEnd(D3D10DDI_HDEVICE hDevice, // IN
194
D3D10DDI_HQUERY hQuery) // IN
198
Device *pDevice = CastDevice(hDevice);
199
struct pipe_context *pipe = pDevice->pipe;
200
Query *pQuery = CastQuery(hQuery);
201
struct pipe_query *state = pQuery->handle;
203
pQuery->SeqNo = ++pDevice->LastEmittedQuerySeqNo;
204
pQuery->GetDataCount = 0;
207
pipe->end_query(pipe, state);
213
* ----------------------------------------------------------------------
217
* The QueryGetData function polls for the state of a query operation.
219
* ----------------------------------------------------------------------
223
QueryGetData(D3D10DDI_HDEVICE hDevice, // IN
224
D3D10DDI_HQUERY hQuery, // IN
225
__out_bcount_full_opt (DataSize) void *pData, // OUT
231
Device *pDevice = CastDevice(hDevice);
232
struct pipe_context *pipe = pDevice->pipe;
233
Query *pQuery = CastQuery(hQuery);
234
struct pipe_query *state = pQuery->handle;
237
* Never return data for recently emitted queries immediately, to make
241
(pQuery->SeqNo - pDevice->LastFinishedQuerySeqNo) > 0 &&
242
(pQuery->GetDataCount++) == 0) {
243
SetError(hDevice, DXGI_DDI_ERR_WASSTILLDRAWING);
247
boolean wait = !!(Flags & D3D10_DDI_GET_DATA_DO_NOT_FLUSH);
248
union pipe_query_result result;
250
memset(&result, 0, sizeof result);
255
ret = pipe->get_query_result(pipe, state, wait, &result);
257
LOG_UNSUPPORTED(TRUE);
262
SetError(hDevice, DXGI_DDI_ERR_WASSTILLDRAWING);
267
switch (pQuery->Type) {
268
case D3D10DDI_QUERY_EVENT:
269
case D3D10DDI_QUERY_OCCLUSIONPREDICATE:
270
case D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE:
271
*(BOOL *)pData = result.b;
273
case D3D10DDI_QUERY_OCCLUSION:
274
case D3D10DDI_QUERY_TIMESTAMP:
275
*(UINT64 *)pData = result.u64;
277
case D3D10DDI_QUERY_TIMESTAMPDISJOINT:
279
D3D10_DDI_QUERY_DATA_TIMESTAMP_DISJOINT *pResult =
280
(D3D10_DDI_QUERY_DATA_TIMESTAMP_DISJOINT *)pData;
281
pResult->Frequency = result.timestamp_disjoint.frequency;
282
pResult->Disjoint = result.timestamp_disjoint.disjoint;
285
case D3D10DDI_QUERY_PIPELINESTATS:
287
D3D10_DDI_QUERY_DATA_PIPELINE_STATISTICS *pResult =
288
(D3D10_DDI_QUERY_DATA_PIPELINE_STATISTICS *)pData;
289
pResult->IAVertices = result.pipeline_statistics.ia_vertices;
290
pResult->IAPrimitives = result.pipeline_statistics.ia_primitives;
291
pResult->VSInvocations = result.pipeline_statistics.vs_invocations;
292
pResult->GSInvocations = result.pipeline_statistics.gs_invocations;
293
pResult->GSPrimitives = result.pipeline_statistics.gs_primitives;
294
pResult->CInvocations = result.pipeline_statistics.c_invocations;
295
pResult->CPrimitives = result.pipeline_statistics.c_primitives;
296
pResult->PSInvocations = result.pipeline_statistics.ps_invocations;
297
//pResult->HSInvocations = result.pipeline_statistics.hs_invocations;
298
//pResult->DSInvocations = result.pipeline_statistics.ds_invocations;
299
//pResult->CSInvocations = result.pipeline_statistics.cs_invocations;
302
case D3D10DDI_QUERY_STREAMOUTPUTSTATS:
304
D3D10_DDI_QUERY_DATA_SO_STATISTICS *pResult =
305
(D3D10_DDI_QUERY_DATA_SO_STATISTICS *)pData;
306
pResult->NumPrimitivesWritten = result.so_statistics.num_primitives_written;
307
pResult->PrimitivesStorageNeeded = result.so_statistics.primitives_storage_needed;
317
* Keep track of the last finished query, as wgfasync checks that queries
318
* are completed in order.
320
if ((pQuery->SeqNo - pDevice->LastFinishedQuerySeqNo) > 0) {
321
pDevice->LastFinishedQuerySeqNo = pQuery->SeqNo;
323
pQuery->GetDataCount = 0x80000000;
328
* ----------------------------------------------------------------------
332
* The SetPredication function specifies whether rendering and
333
* resource-manipulation commands that follow are actually performed.
335
* ----------------------------------------------------------------------
339
SetPredication(D3D10DDI_HDEVICE hDevice, // IN
340
D3D10DDI_HQUERY hQuery, // IN
341
BOOL PredicateValue) // IN
345
Device *pDevice = CastDevice(hDevice);
346
struct pipe_context *pipe = pDevice->pipe;
347
Query *pQuery = CastQuery(hQuery);
348
struct pipe_query *state = CastPipeQuery(hQuery);
349
enum pipe_render_cond_flag wait;
351
wait = (pQuery && pQuery->Flags & D3D10DDI_QUERY_MISCFLAG_PREDICATEHINT) ?
352
PIPE_RENDER_COND_NO_WAIT : PIPE_RENDER_COND_WAIT;
354
pipe->render_condition(pipe, state, PredicateValue, wait);
356
pDevice->pPredicate = pQuery;
357
pDevice->PredicateValue = PredicateValue;
362
* ----------------------------------------------------------------------
366
* Check predicate value and whether to draw or not.
368
* ----------------------------------------------------------------------
372
CheckPredicate(Device *pDevice)
374
Query *pQuery = pDevice->pPredicate;
379
assert(pQuery->Type == D3D10DDI_QUERY_OCCLUSIONPREDICATE ||
380
pQuery->Type == D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE);
382
struct pipe_context *pipe = pDevice->pipe;
383
struct pipe_query *query = pQuery->handle;
386
union pipe_query_result result;
387
memset(&result, 0, sizeof result);
390
ret = pipe->get_query_result(pipe, query, TRUE, &result);
396
if (!!result.b == !!pDevice->PredicateValue) {
405
* ----------------------------------------------------------------------
407
* CheckCounterInfo --
409
* The CheckCounterInfo function determines global information that
410
* is related to manipulating counters.
412
* ----------------------------------------------------------------------
416
CheckCounterInfo(D3D10DDI_HDEVICE hDevice, // IN
417
__out D3D10DDI_COUNTER_INFO *pCounterInfo) // OUT
421
pCounterInfo->LastDeviceDependentCounter = (D3D10DDI_QUERY)0;
422
pCounterInfo->NumSimultaneousCounters = 0;
423
pCounterInfo->NumDetectableParallelUnits = 0;
428
* ----------------------------------------------------------------------
432
* The CheckCounter function retrieves information that
433
* describes a counter.
435
* ----------------------------------------------------------------------
440
D3D10DDI_HDEVICE hDevice, // IN
441
D3D10DDI_QUERY Query, // IN
442
__out D3D10DDI_COUNTER_TYPE *pCounterType, // OUT
443
__out UINT *pActiveCounters, // OUT
444
__out_ecount_part_z_opt (*pNameLength, *pNameLength) LPSTR pName, // OUT
445
__inout_opt UINT *pNameLength, // OUT
446
__out_ecount_part_z_opt (*pUnitsLength, *pUnitsLength) LPSTR pUnits, // OUT
447
__inout_opt UINT *pUnitsLength, // OUT
448
__out_ecount_part_z_opt (*pDescriptionLength, *pDescriptionLength) LPSTR pDescription, // OUT
449
__inout_opt UINT* pDescriptionLength) // OUT
453
SetError(hDevice, DXGI_DDI_ERR_UNSUPPORTED);