Home | History | Annotate | Download | only in D3D9
      1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "Direct3DQuery9.hpp"
     16 
     17 #include "Direct3DDevice9.hpp"
     18 #include "Timer.hpp"
     19 #include "Renderer.hpp"
     20 #include "Debug.hpp"
     21 
     22 #include <assert.h>
     23 
     24 namespace D3D9
     25 {
     26 	Direct3DQuery9::Direct3DQuery9(Direct3DDevice9 *device, D3DQUERYTYPE type) : device(device), type(type)
     27 	{
     28 		if(type == D3DQUERYTYPE_OCCLUSION)
     29 		{
     30 			query = new sw::Query(sw::Query::FRAGMENTS_PASSED);
     31 		}
     32 		else
     33 		{
     34 			query = 0;
     35 		}
     36 	}
     37 
     38 	Direct3DQuery9::~Direct3DQuery9()
     39 	{
     40 		if(query)
     41 		{
     42 			device->removeQuery(query);
     43 
     44 			delete query;
     45 		}
     46 	}
     47 
     48 	long Direct3DQuery9::QueryInterface(const IID &iid, void **object)
     49 	{
     50 		CriticalSection cs(device);
     51 
     52 		TRACE("");
     53 
     54 		if(iid == IID_IDirect3DQuery9 ||
     55 		   iid == IID_IUnknown)
     56 		{
     57 			AddRef();
     58 			*object = this;
     59 
     60 			return S_OK;
     61 		}
     62 
     63 		*object = 0;
     64 
     65 		return NOINTERFACE(iid);
     66 	}
     67 
     68 	unsigned long Direct3DQuery9::AddRef()
     69 	{
     70 		TRACE("");
     71 
     72 		return Unknown::AddRef();
     73 	}
     74 
     75 	unsigned long Direct3DQuery9::Release()
     76 	{
     77 		TRACE("");
     78 
     79 		return Unknown::Release();
     80 	}
     81 
     82 	long __stdcall Direct3DQuery9::GetDevice(IDirect3DDevice9 **device)
     83 	{
     84 		CriticalSection cs(this->device);
     85 
     86 		TRACE("");
     87 
     88 		if(!device)
     89 		{
     90 			return INVALIDCALL();
     91 		}
     92 
     93 		this->device->AddRef();
     94 		*device = this->device;
     95 
     96 		return D3D_OK;
     97 	}
     98 
     99 	D3DQUERYTYPE Direct3DQuery9::GetType()
    100 	{
    101 		CriticalSection cs(device);
    102 
    103 		return type;
    104 	}
    105 
    106 	unsigned long Direct3DQuery9::GetDataSize()
    107 	{
    108 		CriticalSection cs(device);
    109 
    110 		TRACE("");
    111 
    112 		switch(type)
    113 		{
    114 		case D3DQUERYTYPE_VCACHE:				return sizeof(D3DDEVINFO_VCACHE);
    115 		case D3DQUERYTYPE_RESOURCEMANAGER:		return sizeof(D3DDEVINFO_RESOURCEMANAGER);
    116 		case D3DQUERYTYPE_VERTEXSTATS:			return sizeof(D3DDEVINFO_D3DVERTEXSTATS);
    117 		case D3DQUERYTYPE_EVENT:				return sizeof(BOOL);
    118 		case D3DQUERYTYPE_OCCLUSION:			return sizeof(DWORD);
    119 		case D3DQUERYTYPE_TIMESTAMP:			return sizeof(UINT64);
    120 		case D3DQUERYTYPE_TIMESTAMPDISJOINT:	return sizeof(BOOL);
    121 		case D3DQUERYTYPE_TIMESTAMPFREQ:		return sizeof(UINT64);
    122 		case D3DQUERYTYPE_PIPELINETIMINGS:		return sizeof(D3DDEVINFO_D3D9PIPELINETIMINGS);
    123 		case D3DQUERYTYPE_INTERFACETIMINGS:		return sizeof(D3DDEVINFO_D3D9INTERFACETIMINGS);
    124 		case D3DQUERYTYPE_VERTEXTIMINGS:		return sizeof(D3DDEVINFO_D3D9STAGETIMINGS);
    125 		case D3DQUERYTYPE_PIXELTIMINGS:			return sizeof(D3DDEVINFO_D3D9PIPELINETIMINGS);
    126 		case D3DQUERYTYPE_BANDWIDTHTIMINGS:		return sizeof(D3DDEVINFO_D3D9BANDWIDTHTIMINGS);
    127 		case D3DQUERYTYPE_CACHEUTILIZATION:		return sizeof(D3DDEVINFO_D3D9CACHEUTILIZATION);
    128 		default:
    129 			ASSERT(false);
    130 		}
    131 
    132 		return D3D_OK;
    133 	}
    134 
    135 	long Direct3DQuery9::Issue(unsigned long flags)
    136 	{
    137 		CriticalSection cs(device);
    138 
    139 		TRACE("");
    140 
    141 		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END)
    142 		{
    143 			return INVALIDCALL();
    144 		}
    145 
    146 		switch(type)
    147 		{
    148 		case D3DQUERYTYPE_VCACHE:				if(flags != D3DISSUE_END) return INVALIDCALL(); break;
    149 		case D3DQUERYTYPE_RESOURCEMANAGER:		if(flags != D3DISSUE_END) return INVALIDCALL(); break;
    150 		case D3DQUERYTYPE_VERTEXSTATS:			if(flags != D3DISSUE_END) return INVALIDCALL(); break;
    151 		case D3DQUERYTYPE_EVENT:
    152 			if(flags == D3DISSUE_END)
    153 			{
    154 			//	device->renderer->synchronize();   // FIXME
    155 			}
    156 			else return INVALIDCALL();
    157 			break;
    158 		case D3DQUERYTYPE_OCCLUSION:
    159 			if(flags == D3DISSUE_BEGIN)
    160 			{
    161 				query->begin();
    162 				device->addQuery(query);
    163 				device->setOcclusionEnabled(true);
    164 			}
    165 			else   // flags == D3DISSUE_END
    166 			{
    167 				query->end();
    168 				device->removeQuery(query);
    169 				device->setOcclusionEnabled(false);
    170 			}
    171 			break;
    172 		case D3DQUERYTYPE_TIMESTAMP:
    173 			if(flags == D3DISSUE_END)
    174 			{
    175 				timestamp = sw::Timer::counter();
    176 			}
    177 			else return INVALIDCALL();
    178 			break;
    179 		case D3DQUERYTYPE_TIMESTAMPDISJOINT:	if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    180 		case D3DQUERYTYPE_TIMESTAMPFREQ:		if(flags != D3DISSUE_END) return INVALIDCALL(); break;
    181 		case D3DQUERYTYPE_PIPELINETIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    182 		case D3DQUERYTYPE_INTERFACETIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    183 		case D3DQUERYTYPE_VERTEXTIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    184 		case D3DQUERYTYPE_PIXELTIMINGS:			if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    185 		case D3DQUERYTYPE_BANDWIDTHTIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    186 		case D3DQUERYTYPE_CACHEUTILIZATION:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    187 		default:
    188 			ASSERT(false);
    189 		}
    190 
    191 		return D3D_OK;
    192 	}
    193 
    194 	long Direct3DQuery9::GetData(void *data, unsigned long size, unsigned long flags)
    195 	{
    196 		CriticalSection cs(device);
    197 
    198 		TRACE("void *data = %p, unsigned long size = %d, unsigned long flags = %d", data, size, flags);
    199 
    200 		if(query && query->building)
    201 		{
    202 			return INVALIDCALL();
    203 		}
    204 
    205 		bool signaled = !query || query->reference == 0;
    206 
    207 		if(size && signaled)
    208 		{
    209 			if(!data)
    210 			{
    211 				return INVALIDCALL();
    212 			}
    213 
    214 			// FIXME: Check size
    215 
    216 			switch(type)
    217 			{
    218 			case D3DQUERYTYPE_VCACHE:
    219 				{
    220 					D3DDEVINFO_VCACHE vcache;
    221 
    222 					vcache.Pattern = 'CACH';
    223 					vcache.OptMethod = 1;   // Vertex-cache based optimization
    224 					vcache.CacheSize = 16;
    225 					vcache.MagicNumber = 8;
    226 
    227 					*(D3DDEVINFO_VCACHE*)data = vcache;
    228 				}
    229 				break;
    230 			case D3DQUERYTYPE_RESOURCEMANAGER:		UNIMPLEMENTED(); break;
    231 			case D3DQUERYTYPE_VERTEXSTATS:			UNIMPLEMENTED(); break;
    232 			case D3DQUERYTYPE_EVENT:				*(BOOL*)data = TRUE; break;                       // FIXME
    233 			case D3DQUERYTYPE_OCCLUSION:
    234 				*(DWORD*)data = query->data;
    235 				break;
    236 			case D3DQUERYTYPE_TIMESTAMP:			*(UINT64*)data = timestamp; break;                // FIXME: Verify behaviour
    237 			case D3DQUERYTYPE_TIMESTAMPDISJOINT:	*(BOOL*)data = FALSE; break;                      // FIXME: Verify behaviour
    238 			case D3DQUERYTYPE_TIMESTAMPFREQ:		*(UINT64*)data = sw::Timer::frequency(); break;   // FIXME: Verify behaviour
    239 			case D3DQUERYTYPE_PIPELINETIMINGS:		UNIMPLEMENTED(); break;
    240 			case D3DQUERYTYPE_INTERFACETIMINGS:		UNIMPLEMENTED(); break;
    241 			case D3DQUERYTYPE_VERTEXTIMINGS:		UNIMPLEMENTED(); break;
    242 			case D3DQUERYTYPE_PIXELTIMINGS:			UNIMPLEMENTED(); break;
    243 			case D3DQUERYTYPE_BANDWIDTHTIMINGS:		UNIMPLEMENTED(); break;
    244 			case D3DQUERYTYPE_CACHEUTILIZATION:		UNIMPLEMENTED(); break;
    245 			default:
    246 				ASSERT(false);
    247 			}
    248 		}
    249 
    250 		return signaled ? S_OK : S_FALSE;
    251 	}
    252 }
    253