Path: blob/21.2-virgl/src/gallium/frontends/d3d10umd/Query.cpp
4565 views
/**************************************************************************1*2* Copyright 2012-2021 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL16* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,17* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR18* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE19* USE OR OTHER DEALINGS IN THE SOFTWARE.20*21* The above copyright notice and this permission notice (including the22* next paragraph) shall be included in all copies or substantial portions23* of the Software.24*25**************************************************************************/2627/*28* Query.cpp --29* Functions that manipulate query resources.30*/313233#include "Query.h"34#include "State.h"3536#include "Debug.h"373839/*40* ----------------------------------------------------------------------41*42* CalcPrivateQuerySize --43*44* The CalcPrivateQuerySize function determines the size of the45* user-mode display driver's private region of memory (that is,46* the size of internal driver structures, not the size of the47* resource video memory) for a query.48*49* ----------------------------------------------------------------------50*/5152SIZE_T APIENTRY53CalcPrivateQuerySize(D3D10DDI_HDEVICE hDevice, // IN54__in const D3D10DDIARG_CREATEQUERY *pCreateQuery) // IN55{56return sizeof(Query);57}585960static uint61TranslateQueryType(D3D10DDI_QUERY query)62{63switch (query) {64case D3D10DDI_QUERY_EVENT:65return PIPE_QUERY_GPU_FINISHED;66case D3D10DDI_QUERY_OCCLUSION:67return PIPE_QUERY_OCCLUSION_COUNTER;68case D3D10DDI_QUERY_TIMESTAMP:69return PIPE_QUERY_TIMESTAMP;70case D3D10DDI_QUERY_TIMESTAMPDISJOINT:71return PIPE_QUERY_TIMESTAMP_DISJOINT;72case D3D10DDI_QUERY_PIPELINESTATS:73return PIPE_QUERY_PIPELINE_STATISTICS;74case D3D10DDI_QUERY_OCCLUSIONPREDICATE:75return PIPE_QUERY_OCCLUSION_PREDICATE;76case D3D10DDI_QUERY_STREAMOUTPUTSTATS:77return PIPE_QUERY_SO_STATISTICS;78case D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE:79return PIPE_QUERY_SO_OVERFLOW_PREDICATE;80default:81LOG_UNSUPPORTED(TRUE);82return PIPE_QUERY_TYPES;83}84}858687/*88* ----------------------------------------------------------------------89*90* CreateQuery --91*92* The CreateQuery function creates driver-side resources for a93* query that the Microsoft Direct3D runtime subsequently issues94* for processing.95*96* ----------------------------------------------------------------------97*/9899void APIENTRY100CreateQuery(D3D10DDI_HDEVICE hDevice, // IN101__in const D3D10DDIARG_CREATEQUERY *pCreateQuery, // IN102D3D10DDI_HQUERY hQuery, // IN103D3D10DDI_HRTQUERY hRTQuery) // IN104{105LOG_ENTRYPOINT();106107Device *pDevice = CastDevice(hDevice);108struct pipe_context *pipe = pDevice->pipe;109110Query *pQuery = CastQuery(hQuery);111memset(pQuery, 0, sizeof *pQuery);112113pQuery->Type = pCreateQuery->Query;114pQuery->Flags = pCreateQuery->MiscFlags;115116pQuery->pipe_type = TranslateQueryType(pCreateQuery->Query);117if (pQuery->pipe_type < PIPE_QUERY_TYPES) {118pQuery->handle = pipe->create_query(pipe, pQuery->pipe_type, 0);119}120}121122123/*124* ----------------------------------------------------------------------125*126* DestroyQuery --127*128* The DestroyQuery function releases resources for a query.129*130* ----------------------------------------------------------------------131*/132133void APIENTRY134DestroyQuery(D3D10DDI_HDEVICE hDevice, // IN135D3D10DDI_HQUERY hQuery) // IN136{137LOG_ENTRYPOINT();138139struct pipe_context *pipe = CastPipeContext(hDevice);140Query *pQuery = CastQuery(hQuery);141142if (pQuery->handle) {143pipe->destroy_query(pipe, pQuery->handle);144}145}146147148/*149* ----------------------------------------------------------------------150*151* QueryBegin --152*153* The QueryBegin function marks the beginning of a sequence of154* graphics commands for a query and transitions the query to the155* "building" state.156*157* ----------------------------------------------------------------------158*/159160void APIENTRY161QueryBegin(D3D10DDI_HDEVICE hDevice, // IN162D3D10DDI_HQUERY hQuery) // IN163{164LOG_ENTRYPOINT();165166Device *pDevice = CastDevice(hDevice);167struct pipe_context *pipe = pDevice->pipe;168169Query *pQuery = CastQuery(hQuery);170struct pipe_query *state = CastPipeQuery(hQuery);171172if (state) {173assert(pQuery->pipe_type < PIPE_QUERY_TYPES);174pipe->begin_query(pipe, state);175}176}177178179/*180* ----------------------------------------------------------------------181*182* QueryEnd --183*184* The QueryEnd function marks the end of a sequence of graphics185* commands for a query and transitions the query to the186* "issued" state.187*188* ----------------------------------------------------------------------189*/190191void APIENTRY192QueryEnd(D3D10DDI_HDEVICE hDevice, // IN193D3D10DDI_HQUERY hQuery) // IN194{195LOG_ENTRYPOINT();196197Device *pDevice = CastDevice(hDevice);198struct pipe_context *pipe = pDevice->pipe;199Query *pQuery = CastQuery(hQuery);200struct pipe_query *state = pQuery->handle;201202pQuery->SeqNo = ++pDevice->LastEmittedQuerySeqNo;203pQuery->GetDataCount = 0;204205if (state) {206pipe->end_query(pipe, state);207}208}209210211/*212* ----------------------------------------------------------------------213*214* QueryGetData --215*216* The QueryGetData function polls for the state of a query operation.217*218* ----------------------------------------------------------------------219*/220221void APIENTRY222QueryGetData(D3D10DDI_HDEVICE hDevice, // IN223D3D10DDI_HQUERY hQuery, // IN224__out_bcount_full_opt (DataSize) void *pData, // OUT225UINT DataSize, // IN226UINT Flags) // IN227{228LOG_ENTRYPOINT();229230Device *pDevice = CastDevice(hDevice);231struct pipe_context *pipe = pDevice->pipe;232Query *pQuery = CastQuery(hQuery);233struct pipe_query *state = pQuery->handle;234235/*236* Never return data for recently emitted queries immediately, to make237* wgfasync happy.238*/239if (DataSize == 0 &&240(pQuery->SeqNo - pDevice->LastFinishedQuerySeqNo) > 0 &&241(pQuery->GetDataCount++) == 0) {242SetError(hDevice, DXGI_DDI_ERR_WASSTILLDRAWING);243return;244}245246boolean wait = !!(Flags & D3D10_DDI_GET_DATA_DO_NOT_FLUSH);247union pipe_query_result result;248249memset(&result, 0, sizeof result);250251boolean ret;252253if (state) {254ret = pipe->get_query_result(pipe, state, wait, &result);255} else {256LOG_UNSUPPORTED(TRUE);257ret = TRUE;258}259260if (!ret) {261SetError(hDevice, DXGI_DDI_ERR_WASSTILLDRAWING);262return;263}264265if (pData) {266switch (pQuery->Type) {267case D3D10DDI_QUERY_EVENT:268case D3D10DDI_QUERY_OCCLUSIONPREDICATE:269case D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE:270*(BOOL *)pData = result.b;271break;272case D3D10DDI_QUERY_OCCLUSION:273case D3D10DDI_QUERY_TIMESTAMP:274*(UINT64 *)pData = result.u64;275break;276case D3D10DDI_QUERY_TIMESTAMPDISJOINT:277{278D3D10_DDI_QUERY_DATA_TIMESTAMP_DISJOINT *pResult =279(D3D10_DDI_QUERY_DATA_TIMESTAMP_DISJOINT *)pData;280pResult->Frequency = result.timestamp_disjoint.frequency;281pResult->Disjoint = result.timestamp_disjoint.disjoint;282}283break;284case D3D10DDI_QUERY_PIPELINESTATS:285{286D3D10_DDI_QUERY_DATA_PIPELINE_STATISTICS *pResult =287(D3D10_DDI_QUERY_DATA_PIPELINE_STATISTICS *)pData;288pResult->IAVertices = result.pipeline_statistics.ia_vertices;289pResult->IAPrimitives = result.pipeline_statistics.ia_primitives;290pResult->VSInvocations = result.pipeline_statistics.vs_invocations;291pResult->GSInvocations = result.pipeline_statistics.gs_invocations;292pResult->GSPrimitives = result.pipeline_statistics.gs_primitives;293pResult->CInvocations = result.pipeline_statistics.c_invocations;294pResult->CPrimitives = result.pipeline_statistics.c_primitives;295pResult->PSInvocations = result.pipeline_statistics.ps_invocations;296//pResult->HSInvocations = result.pipeline_statistics.hs_invocations;297//pResult->DSInvocations = result.pipeline_statistics.ds_invocations;298//pResult->CSInvocations = result.pipeline_statistics.cs_invocations;299}300break;301case D3D10DDI_QUERY_STREAMOUTPUTSTATS:302{303D3D10_DDI_QUERY_DATA_SO_STATISTICS *pResult =304(D3D10_DDI_QUERY_DATA_SO_STATISTICS *)pData;305pResult->NumPrimitivesWritten = result.so_statistics.num_primitives_written;306pResult->PrimitivesStorageNeeded = result.so_statistics.primitives_storage_needed;307}308break;309default:310assert(0);311break;312}313}314315/*316* Keep track of the last finished query, as wgfasync checks that queries317* are completed in order.318*/319if ((pQuery->SeqNo - pDevice->LastFinishedQuerySeqNo) > 0) {320pDevice->LastFinishedQuerySeqNo = pQuery->SeqNo;321}322pQuery->GetDataCount = 0x80000000;323}324325326/*327* ----------------------------------------------------------------------328*329* SetPredication --330*331* The SetPredication function specifies whether rendering and332* resource-manipulation commands that follow are actually performed.333*334* ----------------------------------------------------------------------335*/336337void APIENTRY338SetPredication(D3D10DDI_HDEVICE hDevice, // IN339D3D10DDI_HQUERY hQuery, // IN340BOOL PredicateValue) // IN341{342LOG_ENTRYPOINT();343344Device *pDevice = CastDevice(hDevice);345struct pipe_context *pipe = pDevice->pipe;346Query *pQuery = CastQuery(hQuery);347struct pipe_query *state = CastPipeQuery(hQuery);348enum pipe_render_cond_flag wait;349350wait = (pQuery && pQuery->Flags & D3D10DDI_QUERY_MISCFLAG_PREDICATEHINT) ?351PIPE_RENDER_COND_NO_WAIT : PIPE_RENDER_COND_WAIT;352353pipe->render_condition(pipe, state, PredicateValue, wait);354355pDevice->pPredicate = pQuery;356pDevice->PredicateValue = PredicateValue;357}358359360/*361* ----------------------------------------------------------------------362*363* CheckPredicate --364*365* Check predicate value and whether to draw or not.366*367* ----------------------------------------------------------------------368*/369370BOOL371CheckPredicate(Device *pDevice)372{373Query *pQuery = pDevice->pPredicate;374if (!pQuery) {375return TRUE;376}377378assert(pQuery->Type == D3D10DDI_QUERY_OCCLUSIONPREDICATE ||379pQuery->Type == D3D10DDI_QUERY_STREAMOVERFLOWPREDICATE);380381struct pipe_context *pipe = pDevice->pipe;382struct pipe_query *query = pQuery->handle;383assert(query);384385union pipe_query_result result;386memset(&result, 0, sizeof result);387388boolean ret;389ret = pipe->get_query_result(pipe, query, TRUE, &result);390assert(ret == TRUE);391if (!ret) {392return TRUE;393}394395if (!!result.b == !!pDevice->PredicateValue) {396return FALSE;397}398399return TRUE;400}401402403/*404* ----------------------------------------------------------------------405*406* CheckCounterInfo --407*408* The CheckCounterInfo function determines global information that409* is related to manipulating counters.410*411* ----------------------------------------------------------------------412*/413414void APIENTRY415CheckCounterInfo(D3D10DDI_HDEVICE hDevice, // IN416__out D3D10DDI_COUNTER_INFO *pCounterInfo) // OUT417{418//LOG_ENTRYPOINT();419420pCounterInfo->LastDeviceDependentCounter = (D3D10DDI_QUERY)0;421pCounterInfo->NumSimultaneousCounters = 0;422pCounterInfo->NumDetectableParallelUnits = 0;423}424425426/*427* ----------------------------------------------------------------------428*429* CheckCounter --430*431* The CheckCounter function retrieves information that432* describes a counter.433*434* ----------------------------------------------------------------------435*/436437void APIENTRY438CheckCounter(439D3D10DDI_HDEVICE hDevice, // IN440D3D10DDI_QUERY Query, // IN441__out D3D10DDI_COUNTER_TYPE *pCounterType, // OUT442__out UINT *pActiveCounters, // OUT443__out_ecount_part_z_opt (*pNameLength, *pNameLength) LPSTR pName, // OUT444__inout_opt UINT *pNameLength, // OUT445__out_ecount_part_z_opt (*pUnitsLength, *pUnitsLength) LPSTR pUnits, // OUT446__inout_opt UINT *pUnitsLength, // OUT447__out_ecount_part_z_opt (*pDescriptionLength, *pDescriptionLength) LPSTR pDescription, // OUT448__inout_opt UINT* pDescriptionLength) // OUT449{450LOG_ENTRYPOINT();451452SetError(hDevice, DXGI_DDI_ERR_UNSUPPORTED);453}454455456