renderer_d3d.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * Copyright 2011-2016 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #ifndef BGFX_RENDERER_D3D_H_HEADER_GUARD
  6. #define BGFX_RENDERER_D3D_H_HEADER_GUARD
  7. #if 0 // BGFX_CONFIG_DEBUG && BGFX_CONFIG_RENDERER_DIRECT3D9 && !(BX_COMPILER_GCC || BX_COMPILER_CLANG)
  8. # include <sal.h>
  9. # include <dxerr.h>
  10. # if BX_COMPILER_MSVC
  11. # pragma comment(lib, "dxerr.lib")
  12. # endif // BX_COMPILER_MSVC
  13. # define DX_CHECK_EXTRA_F " (%s): %s"
  14. # define DX_CHECK_EXTRA_ARGS , DXGetErrorString(__hr__), DXGetErrorDescription(__hr__)
  15. #else
  16. # define DX_CHECK_EXTRA_F ""
  17. # define DX_CHECK_EXTRA_ARGS
  18. #endif // BGFX_CONFIG_DEBUG && BGFX_CONFIG_RENDERER_DIRECT3D9
  19. namespace bgfx
  20. {
  21. #if BX_PLATFORM_XBOXONE
  22. typedef ::IGraphicsUnknown IUnknown;
  23. #else
  24. typedef ::IUnknown IUnknown;
  25. #endif // BX_PLATFORM_XBOXONE
  26. #define _DX_CHECK(_call) \
  27. BX_MACRO_BLOCK_BEGIN \
  28. HRESULT __hr__ = _call; \
  29. BX_CHECK(SUCCEEDED(__hr__), #_call " FAILED 0x%08x" DX_CHECK_EXTRA_F "\n" \
  30. , (uint32_t)__hr__ \
  31. DX_CHECK_EXTRA_ARGS \
  32. ); \
  33. BX_MACRO_BLOCK_END
  34. #define _DX_RELEASE(_ptr, _expected, _check) \
  35. BX_MACRO_BLOCK_BEGIN \
  36. if (NULL != (_ptr) ) \
  37. { \
  38. ULONG count = (_ptr)->Release(); \
  39. _check(isGraphicsDebuggerPresent() || _expected == count, "%p RefCount is %d (expected %d).", _ptr, count, _expected); BX_UNUSED(count); \
  40. _ptr = NULL; \
  41. } \
  42. BX_MACRO_BLOCK_END
  43. #define _DX_CHECK_REFCOUNT(_ptr, _expected) \
  44. BX_MACRO_BLOCK_BEGIN \
  45. ULONG count = getRefCount(_ptr); \
  46. BX_CHECK(isGraphicsDebuggerPresent() || _expected == count, "%p RefCount is %d (expected %d).", _ptr, count, _expected); \
  47. BX_MACRO_BLOCK_END
  48. #define _DX_NAME(_ptr, _format, ...) setDebugObjectName(_ptr, _format, ##__VA_ARGS__)
  49. #if BGFX_CONFIG_DEBUG
  50. # define DX_CHECK(_call) _DX_CHECK(_call)
  51. # define DX_CHECK_REFCOUNT(_ptr, _expected) _DX_CHECK_REFCOUNT(_ptr, _expected)
  52. #else
  53. # define DX_CHECK(_call) _call
  54. # define DX_CHECK_REFCOUNT(_ptr, _expected)
  55. #endif // BGFX_CONFIG_DEBUG
  56. #if BGFX_CONFIG_DEBUG_OBJECT_NAME
  57. # define DX_NAME(_ptr, _format, ...) _DX_NAME(_ptr, _format, ##__VA_ARGS__)
  58. #else
  59. # define DX_NAME(_ptr, _format, ...)
  60. #endif // BGFX_CONFIG_DEBUG_OBJECT_NAME
  61. #define DX_RELEASE(_ptr, _expected) _DX_RELEASE(_ptr, _expected, BX_CHECK)
  62. #define DX_RELEASE_WARNONLY(_ptr, _expected) _DX_RELEASE(_ptr, _expected, BX_WARN)
  63. typedef int (WINAPI* PFN_D3DPERF_BEGIN_EVENT)(DWORD _color, LPCWSTR _wszName);
  64. typedef int (WINAPI* PFN_D3DPERF_END_EVENT)();
  65. typedef void (WINAPI* PFN_D3DPERF_SET_MARKER)(DWORD _color, LPCWSTR _wszName);
  66. typedef void (WINAPI* PFN_D3DPERF_SET_REGION)(DWORD _color, LPCWSTR _wszName);
  67. typedef BOOL (WINAPI* PFN_D3DPERF_QUERY_REPEAT_FRAME)();
  68. typedef void (WINAPI* PFN_D3DPERF_SET_OPTIONS)(DWORD _options);
  69. typedef DWORD (WINAPI* PFN_D3DPERF_GET_STATUS)();
  70. typedef HRESULT (WINAPI* PFN_CREATE_DXGI_FACTORY)(REFIID _riid, void** _factory);
  71. typedef HRESULT (WINAPI* PFN_GET_DEBUG_INTERFACE)(REFIID _riid, void** _debug);
  72. typedef HRESULT (WINAPI* PFN_GET_DEBUG_INTERFACE1)(UINT _flags, REFIID _riid, void** _debug);
  73. #define _PIX_SETMARKER(_col, _name) D3DPERF_SetMarker(_col, _name)
  74. #define _PIX_BEGINEVENT(_col, _name) D3DPERF_BeginEvent(_col, _name)
  75. #define _PIX_ENDEVENT() D3DPERF_EndEvent()
  76. #if BGFX_CONFIG_DEBUG_PIX
  77. # define PIX_SETMARKER(_color, _name) _PIX_SETMARKER(_color, _name)
  78. # define PIX_BEGINEVENT(_color, _name) _PIX_BEGINEVENT(_color, _name)
  79. # define PIX_ENDEVENT() _PIX_ENDEVENT()
  80. #else
  81. # define PIX_SETMARKER(_color, _name) BX_UNUSED(_name)
  82. # define PIX_BEGINEVENT(_color, _name) BX_UNUSED(_name)
  83. # define PIX_ENDEVENT()
  84. #endif // BGFX_CONFIG_DEBUG_PIX
  85. inline int getRefCount(IUnknown* _interface)
  86. {
  87. _interface->AddRef();
  88. return _interface->Release();
  89. }
  90. template<typename Ty>
  91. class StateCacheT
  92. {
  93. public:
  94. void add(uint64_t _key, Ty* _value)
  95. {
  96. invalidate(_key);
  97. m_hashMap.insert(stl::make_pair(_key, _value) );
  98. BX_CHECK(isGraphicsDebuggerPresent()
  99. || 1 == getRefCount(_value), "Interface ref count %d, hash %" PRIx64 "."
  100. , getRefCount(_value)
  101. , _key
  102. );
  103. }
  104. Ty* find(uint64_t _key)
  105. {
  106. typename HashMap::iterator it = m_hashMap.find(_key);
  107. if (it != m_hashMap.end() )
  108. {
  109. return it->second;
  110. }
  111. return NULL;
  112. }
  113. void invalidate(uint64_t _key)
  114. {
  115. typename HashMap::iterator it = m_hashMap.find(_key);
  116. if (it != m_hashMap.end() )
  117. {
  118. DX_RELEASE_WARNONLY(it->second, 0);
  119. m_hashMap.erase(it);
  120. }
  121. }
  122. void invalidate()
  123. {
  124. for (typename HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it)
  125. {
  126. DX_CHECK_REFCOUNT(it->second, 1);
  127. it->second->Release();
  128. }
  129. m_hashMap.clear();
  130. }
  131. uint32_t getCount() const
  132. {
  133. return uint32_t(m_hashMap.size() );
  134. }
  135. private:
  136. typedef stl::unordered_map<uint64_t, Ty*> HashMap;
  137. HashMap m_hashMap;
  138. };
  139. class StateCache
  140. {
  141. public:
  142. void add(uint64_t _key, uint16_t _value)
  143. {
  144. invalidate(_key);
  145. m_hashMap.insert(stl::make_pair(_key, _value) );
  146. }
  147. uint16_t find(uint64_t _key)
  148. {
  149. HashMap::iterator it = m_hashMap.find(_key);
  150. if (it != m_hashMap.end() )
  151. {
  152. return it->second;
  153. }
  154. return UINT16_MAX;
  155. }
  156. void invalidate(uint64_t _key)
  157. {
  158. HashMap::iterator it = m_hashMap.find(_key);
  159. if (it != m_hashMap.end() )
  160. {
  161. m_hashMap.erase(it);
  162. }
  163. }
  164. void invalidate()
  165. {
  166. m_hashMap.clear();
  167. }
  168. uint32_t getCount() const
  169. {
  170. return uint32_t(m_hashMap.size() );
  171. }
  172. private:
  173. typedef stl::unordered_map<uint64_t, uint16_t> HashMap;
  174. HashMap m_hashMap;
  175. };
  176. template<typename Ty>
  177. inline void release(Ty)
  178. {
  179. }
  180. template<>
  181. inline void release<IUnknown*>(IUnknown* _ptr)
  182. {
  183. DX_RELEASE(_ptr, 0);
  184. }
  185. template <typename Ty, uint16_t MaxHandleT>
  186. class StateCacheLru
  187. {
  188. public:
  189. void add(uint64_t _key, Ty _value, uint16_t _parent)
  190. {
  191. uint16_t handle = m_alloc.alloc();
  192. if (UINT16_MAX == handle)
  193. {
  194. uint16_t back = m_alloc.getBack();
  195. invalidate(back);
  196. handle = m_alloc.alloc();
  197. }
  198. BX_CHECK(UINT16_MAX != handle, "Failed to find handle.");
  199. Data& data = m_data[handle];
  200. data.m_hash = _key;
  201. data.m_value = _value;
  202. data.m_parent = _parent;
  203. m_hashMap.insert(stl::make_pair(_key, handle) );
  204. }
  205. Ty* find(uint64_t _key)
  206. {
  207. HashMap::iterator it = m_hashMap.find(_key);
  208. if (it != m_hashMap.end() )
  209. {
  210. uint16_t handle = it->second;
  211. m_alloc.touch(handle);
  212. return &m_data[handle].m_value;
  213. }
  214. return NULL;
  215. }
  216. void invalidate(uint64_t _key)
  217. {
  218. HashMap::iterator it = m_hashMap.find(_key);
  219. if (it != m_hashMap.end() )
  220. {
  221. uint16_t handle = it->second;
  222. m_alloc.free(handle);
  223. m_hashMap.erase(it);
  224. release(m_data[handle].m_value);
  225. }
  226. }
  227. void invalidate(uint16_t _handle)
  228. {
  229. if (m_alloc.isValid(_handle) )
  230. {
  231. m_alloc.free(_handle);
  232. Data& data = m_data[_handle];
  233. m_hashMap.erase(m_hashMap.find(data.m_hash) );
  234. release(data.m_value);
  235. }
  236. }
  237. void invalidateWithParent(uint16_t _parent)
  238. {
  239. for (uint16_t ii = 0; ii < m_alloc.getNumHandles();)
  240. {
  241. uint16_t handle = m_alloc.getHandleAt(ii);
  242. Data& data = m_data[handle];
  243. if (data.m_parent == _parent)
  244. {
  245. m_alloc.free(handle);
  246. m_hashMap.erase(m_hashMap.find(data.m_hash) );
  247. release(data.m_value);
  248. }
  249. else
  250. {
  251. ++ii;
  252. }
  253. }
  254. }
  255. void invalidate()
  256. {
  257. for (uint16_t ii = 0, num = m_alloc.getNumHandles(); ii < num; ++ii)
  258. {
  259. uint16_t handle = m_alloc.getHandleAt(ii);
  260. Data& data = m_data[handle];
  261. release(data.m_value);
  262. }
  263. m_hashMap.clear();
  264. m_alloc.reset();
  265. }
  266. uint32_t getCount() const
  267. {
  268. return uint32_t(m_hashMap.size() );
  269. }
  270. private:
  271. typedef stl::unordered_map<uint64_t, uint16_t> HashMap;
  272. HashMap m_hashMap;
  273. bx::HandleAllocLruT<MaxHandleT> m_alloc;
  274. struct Data
  275. {
  276. uint64_t m_hash;
  277. Ty m_value;
  278. uint16_t m_parent;
  279. };
  280. Data m_data[MaxHandleT];
  281. };
  282. } // namespace bgfx
  283. #endif // BGFX_RENDERER_D3D_H_HEADER_GUARD