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:			if(flags != D3DISSUE_END) return INVALIDCALL(); break;
    173 		case D3DQUERYTYPE_TIMESTAMPDISJOINT:	if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    174 		case D3DQUERYTYPE_TIMESTAMPFREQ:		if(flags != D3DISSUE_END) return INVALIDCALL(); break;
    175 		case D3DQUERYTYPE_PIPELINETIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    176 		case D3DQUERYTYPE_INTERFACETIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    177 		case D3DQUERYTYPE_VERTEXTIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    178 		case D3DQUERYTYPE_PIXELTIMINGS:			if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    179 		case D3DQUERYTYPE_BANDWIDTHTIMINGS:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    180 		case D3DQUERYTYPE_CACHEUTILIZATION:		if(flags != D3DISSUE_BEGIN && flags != D3DISSUE_END) return INVALIDCALL(); break;
    181 		default:
    182 			ASSERT(false);
    183 		}
    184 
    185 		return D3D_OK;
    186 	}
    187 
    188 	long Direct3DQuery9::GetData(void *data, unsigned long size, unsigned long flags)
    189 	{
    190 		CriticalSection cs(device);
    191 
    192 		TRACE("void *data = %p, unsigned long size = %d, unsigned long flags = %d", data, size, flags);
    193 
    194 		if(query && query->building)
    195 		{
    196 			return INVALIDCALL();
    197 		}
    198 
    199 		bool signaled = !query || query->reference == 0;
    200 
    201 		if(size && signaled)
    202 		{
    203 			if(!data)
    204 			{
    205 				return INVALIDCALL();
    206 			}
    207 
    208 			// FIXME: Check size
    209 
    210 			switch(type)
    211 			{
    212 			case D3DQUERYTYPE_VCACHE:
    213 				{
    214 					D3DDEVINFO_VCACHE vcache;
    215 
    216 					vcache.Pattern = 'CACH';
    217 					vcache.OptMethod = 1;   // Vertex-cache based optimization
    218 					vcache.CacheSize = 16;
    219 					vcache.MagicNumber = 8;
    220 
    221 					*(D3DDEVINFO_VCACHE*)data = vcache;
    222 				}
    223 				break;
    224 			case D3DQUERYTYPE_RESOURCEMANAGER:		UNIMPLEMENTED(); break;
    225 			case D3DQUERYTYPE_VERTEXSTATS:			UNIMPLEMENTED(); break;
    226 			case D3DQUERYTYPE_EVENT:				*(BOOL*)data = TRUE; break;                       // FIXME
    227 			case D3DQUERYTYPE_OCCLUSION:
    228 				*(DWORD*)data = query->data;
    229 				break;
    230 			case D3DQUERYTYPE_TIMESTAMP:			*(UINT64*)data = sw::Timer::counter(); break;     // FIXME: Verify behaviour
    231 			case D3DQUERYTYPE_TIMESTAMPDISJOINT:	*(BOOL*)data = FALSE; break;                      // FIXME: Verify behaviour
    232 			case D3DQUERYTYPE_TIMESTAMPFREQ:		*(UINT64*)data = sw::Timer::frequency(); break;   // FIXME: Verify behaviour
    233 			case D3DQUERYTYPE_PIPELINETIMINGS:		UNIMPLEMENTED(); break;
    234 			case D3DQUERYTYPE_INTERFACETIMINGS:		UNIMPLEMENTED(); break;
    235 			case D3DQUERYTYPE_VERTEXTIMINGS:		UNIMPLEMENTED(); break;
    236 			case D3DQUERYTYPE_PIXELTIMINGS:			UNIMPLEMENTED(); break;
    237 			case D3DQUERYTYPE_BANDWIDTHTIMINGS:		UNIMPLEMENTED(); break;
    238 			case D3DQUERYTYPE_CACHEUTILIZATION:		UNIMPLEMENTED(); break;
    239 			default:
    240 				ASSERT(false);
    241 			}
    242 		}
    243 
    244 		return signaled ? S_OK : S_FALSE;
    245 	}
    246 }
    247