Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/frontends/d3d10umd/Query.cpp
4565 views
1
/**************************************************************************
2
*
3
* Copyright 2012-2021 VMware, Inc.
4
* All Rights Reserved.
5
*
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:
13
*
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.
21
*
22
* The above copyright notice and this permission notice (including the
23
* next paragraph) shall be included in all copies or substantial portions
24
* of the Software.
25
*
26
**************************************************************************/
27
28
/*
29
* Query.cpp --
30
* Functions that manipulate query resources.
31
*/
32
33
34
#include "Query.h"
35
#include "State.h"
36
37
#include "Debug.h"
38
39
40
/*
41
* ----------------------------------------------------------------------
42
*
43
* CalcPrivateQuerySize --
44
*
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.
49
*
50
* ----------------------------------------------------------------------
51
*/
52
53
SIZE_T APIENTRY
54
CalcPrivateQuerySize(D3D10DDI_HDEVICE hDevice, // IN
55
__in const D3D10DDIARG_CREATEQUERY *pCreateQuery) // IN
56
{
57
return sizeof(Query);
58
}
59
60
61
static uint
62
TranslateQueryType(D3D10DDI_QUERY query)
63
{
64
switch (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;
81
default:
82
LOG_UNSUPPORTED(TRUE);
83
return PIPE_QUERY_TYPES;
84
}
85
}
86
87
88
/*
89
* ----------------------------------------------------------------------
90
*
91
* CreateQuery --
92
*
93
* The CreateQuery function creates driver-side resources for a
94
* query that the Microsoft Direct3D runtime subsequently issues
95
* for processing.
96
*
97
* ----------------------------------------------------------------------
98
*/
99
100
void APIENTRY
101
CreateQuery(D3D10DDI_HDEVICE hDevice, // IN
102
__in const D3D10DDIARG_CREATEQUERY *pCreateQuery, // IN
103
D3D10DDI_HQUERY hQuery, // IN
104
D3D10DDI_HRTQUERY hRTQuery) // IN
105
{
106
LOG_ENTRYPOINT();
107
108
Device *pDevice = CastDevice(hDevice);
109
struct pipe_context *pipe = pDevice->pipe;
110
111
Query *pQuery = CastQuery(hQuery);
112
memset(pQuery, 0, sizeof *pQuery);
113
114
pQuery->Type = pCreateQuery->Query;
115
pQuery->Flags = pCreateQuery->MiscFlags;
116
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);
120
}
121
}
122
123
124
/*
125
* ----------------------------------------------------------------------
126
*
127
* DestroyQuery --
128
*
129
* The DestroyQuery function releases resources for a query.
130
*
131
* ----------------------------------------------------------------------
132
*/
133
134
void APIENTRY
135
DestroyQuery(D3D10DDI_HDEVICE hDevice, // IN
136
D3D10DDI_HQUERY hQuery) // IN
137
{
138
LOG_ENTRYPOINT();
139
140
struct pipe_context *pipe = CastPipeContext(hDevice);
141
Query *pQuery = CastQuery(hQuery);
142
143
if (pQuery->handle) {
144
pipe->destroy_query(pipe, pQuery->handle);
145
}
146
}
147
148
149
/*
150
* ----------------------------------------------------------------------
151
*
152
* QueryBegin --
153
*
154
* The QueryBegin function marks the beginning of a sequence of
155
* graphics commands for a query and transitions the query to the
156
* "building" state.
157
*
158
* ----------------------------------------------------------------------
159
*/
160
161
void APIENTRY
162
QueryBegin(D3D10DDI_HDEVICE hDevice, // IN
163
D3D10DDI_HQUERY hQuery) // IN
164
{
165
LOG_ENTRYPOINT();
166
167
Device *pDevice = CastDevice(hDevice);
168
struct pipe_context *pipe = pDevice->pipe;
169
170
Query *pQuery = CastQuery(hQuery);
171
struct pipe_query *state = CastPipeQuery(hQuery);
172
173
if (state) {
174
assert(pQuery->pipe_type < PIPE_QUERY_TYPES);
175
pipe->begin_query(pipe, state);
176
}
177
}
178
179
180
/*
181
* ----------------------------------------------------------------------
182
*
183
* QueryEnd --
184
*
185
* The QueryEnd function marks the end of a sequence of graphics
186
* commands for a query and transitions the query to the
187
* "issued" state.
188
*
189
* ----------------------------------------------------------------------
190
*/
191
192
void APIENTRY
193
QueryEnd(D3D10DDI_HDEVICE hDevice, // IN
194
D3D10DDI_HQUERY hQuery) // IN
195
{
196
LOG_ENTRYPOINT();
197
198
Device *pDevice = CastDevice(hDevice);
199
struct pipe_context *pipe = pDevice->pipe;
200
Query *pQuery = CastQuery(hQuery);
201
struct pipe_query *state = pQuery->handle;
202
203
pQuery->SeqNo = ++pDevice->LastEmittedQuerySeqNo;
204
pQuery->GetDataCount = 0;
205
206
if (state) {
207
pipe->end_query(pipe, state);
208
}
209
}
210
211
212
/*
213
* ----------------------------------------------------------------------
214
*
215
* QueryGetData --
216
*
217
* The QueryGetData function polls for the state of a query operation.
218
*
219
* ----------------------------------------------------------------------
220
*/
221
222
void APIENTRY
223
QueryGetData(D3D10DDI_HDEVICE hDevice, // IN
224
D3D10DDI_HQUERY hQuery, // IN
225
__out_bcount_full_opt (DataSize) void *pData, // OUT
226
UINT DataSize, // IN
227
UINT Flags) // IN
228
{
229
LOG_ENTRYPOINT();
230
231
Device *pDevice = CastDevice(hDevice);
232
struct pipe_context *pipe = pDevice->pipe;
233
Query *pQuery = CastQuery(hQuery);
234
struct pipe_query *state = pQuery->handle;
235
236
/*
237
* Never return data for recently emitted queries immediately, to make
238
* wgfasync happy.
239
*/
240
if (DataSize == 0 &&
241
(pQuery->SeqNo - pDevice->LastFinishedQuerySeqNo) > 0 &&
242
(pQuery->GetDataCount++) == 0) {
243
SetError(hDevice, DXGI_DDI_ERR_WASSTILLDRAWING);
244
return;
245
}
246
247
boolean wait = !!(Flags & D3D10_DDI_GET_DATA_DO_NOT_FLUSH);
248
union pipe_query_result result;
249
250
memset(&result, 0, sizeof result);
251
252
boolean ret;
253
254
if (state) {
255
ret = pipe->get_query_result(pipe, state, wait, &result);
256
} else {
257
LOG_UNSUPPORTED(TRUE);
258
ret = TRUE;
259
}
260
261
if (!ret) {
262
SetError(hDevice, DXGI_DDI_ERR_WASSTILLDRAWING);
263
return;
264
}
265
266
if (pData) {
267
switch (pQuery->Type) {
268
case D3D10DDI_QUERY_EVENT:
269
case D3D10DDI_QUERY_OCCLUSIONPREDICATE:
270
case D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE:
271
*(BOOL *)pData = result.b;
272
break;
273
case D3D10DDI_QUERY_OCCLUSION:
274
case D3D10DDI_QUERY_TIMESTAMP:
275
*(UINT64 *)pData = result.u64;
276
break;
277
case D3D10DDI_QUERY_TIMESTAMPDISJOINT:
278
{
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;
283
}
284
break;
285
case D3D10DDI_QUERY_PIPELINESTATS:
286
{
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;
300
}
301
break;
302
case D3D10DDI_QUERY_STREAMOUTPUTSTATS:
303
{
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;
308
}
309
break;
310
default:
311
assert(0);
312
break;
313
}
314
}
315
316
/*
317
* Keep track of the last finished query, as wgfasync checks that queries
318
* are completed in order.
319
*/
320
if ((pQuery->SeqNo - pDevice->LastFinishedQuerySeqNo) > 0) {
321
pDevice->LastFinishedQuerySeqNo = pQuery->SeqNo;
322
}
323
pQuery->GetDataCount = 0x80000000;
324
}
325
326
327
/*
328
* ----------------------------------------------------------------------
329
*
330
* SetPredication --
331
*
332
* The SetPredication function specifies whether rendering and
333
* resource-manipulation commands that follow are actually performed.
334
*
335
* ----------------------------------------------------------------------
336
*/
337
338
void APIENTRY
339
SetPredication(D3D10DDI_HDEVICE hDevice, // IN
340
D3D10DDI_HQUERY hQuery, // IN
341
BOOL PredicateValue) // IN
342
{
343
LOG_ENTRYPOINT();
344
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;
350
351
wait = (pQuery && pQuery->Flags & D3D10DDI_QUERY_MISCFLAG_PREDICATEHINT) ?
352
PIPE_RENDER_COND_NO_WAIT : PIPE_RENDER_COND_WAIT;
353
354
pipe->render_condition(pipe, state, PredicateValue, wait);
355
356
pDevice->pPredicate = pQuery;
357
pDevice->PredicateValue = PredicateValue;
358
}
359
360
361
/*
362
* ----------------------------------------------------------------------
363
*
364
* CheckPredicate --
365
*
366
* Check predicate value and whether to draw or not.
367
*
368
* ----------------------------------------------------------------------
369
*/
370
371
BOOL
372
CheckPredicate(Device *pDevice)
373
{
374
Query *pQuery = pDevice->pPredicate;
375
if (!pQuery) {
376
return TRUE;
377
}
378
379
assert(pQuery->Type == D3D10DDI_QUERY_OCCLUSIONPREDICATE ||
380
pQuery->Type == D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE);
381
382
struct pipe_context *pipe = pDevice->pipe;
383
struct pipe_query *query = pQuery->handle;
384
assert(query);
385
386
union pipe_query_result result;
387
memset(&result, 0, sizeof result);
388
389
boolean ret;
390
ret = pipe->get_query_result(pipe, query, TRUE, &result);
391
assert(ret == TRUE);
392
if (!ret) {
393
return TRUE;
394
}
395
396
if (!!result.b == !!pDevice->PredicateValue) {
397
return FALSE;
398
}
399
400
return TRUE;
401
}
402
403
404
/*
405
* ----------------------------------------------------------------------
406
*
407
* CheckCounterInfo --
408
*
409
* The CheckCounterInfo function determines global information that
410
* is related to manipulating counters.
411
*
412
* ----------------------------------------------------------------------
413
*/
414
415
void APIENTRY
416
CheckCounterInfo(D3D10DDI_HDEVICE hDevice, // IN
417
__out D3D10DDI_COUNTER_INFO *pCounterInfo) // OUT
418
{
419
//LOG_ENTRYPOINT();
420
421
pCounterInfo->LastDeviceDependentCounter = (D3D10DDI_QUERY)0;
422
pCounterInfo->NumSimultaneousCounters = 0;
423
pCounterInfo->NumDetectableParallelUnits = 0;
424
}
425
426
427
/*
428
* ----------------------------------------------------------------------
429
*
430
* CheckCounter --
431
*
432
* The CheckCounter function retrieves information that
433
* describes a counter.
434
*
435
* ----------------------------------------------------------------------
436
*/
437
438
void APIENTRY
439
CheckCounter(
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
450
{
451
LOG_ENTRYPOINT();
452
453
SetError(hDevice, DXGI_DDI_ERR_UNSUPPORTED);
454
}
455
456