2013-02-22 00:07:31 -05:00
|
|
|
/*
|
2015-01-01 18:04:46 -05:00
|
|
|
* Copyright 2011-2015 Branimir Karadzic. All rights reserved.
|
2013-02-22 00:07:31 -05:00
|
|
|
* License: http://www.opensource.org/licenses/BSD-2-Clause
|
|
|
|
*/
|
|
|
|
|
2013-11-14 00:54:36 -05:00
|
|
|
#ifndef BGFX_RENDERER_D3D_H_HEADER_GUARD
|
|
|
|
#define BGFX_RENDERER_D3D_H_HEADER_GUARD
|
2013-02-22 00:07:31 -05:00
|
|
|
|
2014-09-23 10:46:39 -04:00
|
|
|
#if 0 // BGFX_CONFIG_DEBUG && BGFX_CONFIG_RENDERER_DIRECT3D9 && !(BX_COMPILER_GCC || BX_COMPILER_CLANG)
|
2013-04-07 16:44:10 -04:00
|
|
|
# include <sal.h>
|
2013-02-22 00:07:31 -05:00
|
|
|
# include <dxerr.h>
|
2013-04-07 17:08:20 -04:00
|
|
|
# if BX_COMPILER_MSVC
|
|
|
|
# pragma comment(lib, "dxerr.lib")
|
|
|
|
# endif // BX_COMPILER_MSVC
|
2013-02-22 00:07:31 -05:00
|
|
|
# define DX_CHECK_EXTRA_F " (%s): %s"
|
|
|
|
# define DX_CHECK_EXTRA_ARGS , DXGetErrorString(__hr__), DXGetErrorDescription(__hr__)
|
|
|
|
#else
|
|
|
|
# define DX_CHECK_EXTRA_F ""
|
|
|
|
# define DX_CHECK_EXTRA_ARGS
|
2013-04-07 17:08:20 -04:00
|
|
|
#endif // BGFX_CONFIG_DEBUG && BGFX_CONFIG_RENDERER_DIRECT3D9
|
2013-02-22 00:07:31 -05:00
|
|
|
|
|
|
|
namespace bgfx
|
|
|
|
{
|
|
|
|
#define _DX_CHECK(_call) \
|
2014-06-08 23:57:39 -04:00
|
|
|
BX_MACRO_BLOCK_BEGIN \
|
2013-02-22 00:07:31 -05:00
|
|
|
HRESULT __hr__ = _call; \
|
|
|
|
BX_CHECK(SUCCEEDED(__hr__), #_call " FAILED 0x%08x" DX_CHECK_EXTRA_F "\n" \
|
|
|
|
, (uint32_t)__hr__ \
|
|
|
|
DX_CHECK_EXTRA_ARGS \
|
|
|
|
); \
|
2014-06-08 23:57:39 -04:00
|
|
|
BX_MACRO_BLOCK_END
|
2013-02-22 00:07:31 -05:00
|
|
|
|
2013-10-19 01:34:23 -04:00
|
|
|
#define _DX_RELEASE(_ptr, _expected, _check) \
|
2014-06-08 23:57:39 -04:00
|
|
|
BX_MACRO_BLOCK_BEGIN \
|
2015-08-08 21:06:33 -04:00
|
|
|
if (NULL != (_ptr) ) \
|
2013-10-19 01:34:23 -04:00
|
|
|
{ \
|
2015-08-08 21:06:33 -04:00
|
|
|
ULONG count = (_ptr)->Release(); \
|
2013-10-19 01:34:23 -04:00
|
|
|
_check(isGraphicsDebuggerPresent() || _expected == count, "%p RefCount is %d (expected %d).", _ptr, count, _expected); BX_UNUSED(count); \
|
|
|
|
_ptr = NULL; \
|
|
|
|
} \
|
2014-06-08 23:57:39 -04:00
|
|
|
BX_MACRO_BLOCK_END
|
2013-10-19 01:34:23 -04:00
|
|
|
|
2015-07-29 02:18:25 -04:00
|
|
|
#define _DX_CHECK_REFCOUNT(_ptr, _expected) \
|
2014-06-08 23:57:39 -04:00
|
|
|
BX_MACRO_BLOCK_BEGIN \
|
2013-10-19 01:34:23 -04:00
|
|
|
ULONG count = getRefCount(_ptr); \
|
|
|
|
BX_CHECK(isGraphicsDebuggerPresent() || _expected == count, "%p RefCount is %d (expected %d).", _ptr, count, _expected); \
|
2014-06-08 23:57:39 -04:00
|
|
|
BX_MACRO_BLOCK_END
|
2013-10-19 01:34:23 -04:00
|
|
|
|
2015-07-29 02:18:25 -04:00
|
|
|
#define _DX_NAME(_ptr, _format, ...) setDebugObjectName(_ptr, _format, ##__VA_ARGS__)
|
|
|
|
|
2013-02-22 00:07:31 -05:00
|
|
|
#if BGFX_CONFIG_DEBUG
|
|
|
|
# define DX_CHECK(_call) _DX_CHECK(_call)
|
2013-10-19 01:34:23 -04:00
|
|
|
# define DX_CHECK_REFCOUNT(_ptr, _expected) _DX_CHECK_REFCOUNT(_ptr, _expected)
|
2013-02-22 00:07:31 -05:00
|
|
|
#else
|
|
|
|
# define DX_CHECK(_call) _call
|
2013-10-19 01:34:23 -04:00
|
|
|
# define DX_CHECK_REFCOUNT(_ptr, _expected)
|
2013-02-22 00:07:31 -05:00
|
|
|
#endif // BGFX_CONFIG_DEBUG
|
|
|
|
|
2015-07-29 02:18:25 -04:00
|
|
|
#if BGFX_CONFIG_DEBUG_OBJECT_NAME
|
|
|
|
# define DX_NAME(_ptr, _format, ...) _DX_NAME(_ptr, _format, ##__VA_ARGS__)
|
|
|
|
#else
|
|
|
|
# define DX_NAME(_ptr, _format, ...)
|
|
|
|
#endif // BGFX_CONFIG_DEBUG_OBJECT_NAME
|
|
|
|
|
2013-10-19 01:34:23 -04:00
|
|
|
#define DX_RELEASE(_ptr, _expected) _DX_RELEASE(_ptr, _expected, BX_CHECK)
|
|
|
|
#define DX_RELEASE_WARNONLY(_ptr, _expected) _DX_RELEASE(_ptr, _expected, BX_WARN)
|
|
|
|
|
2014-10-07 01:10:55 -04:00
|
|
|
typedef int (WINAPI* PFN_D3DPERF_BEGIN_EVENT)(DWORD _color, LPCWSTR _wszName);
|
|
|
|
typedef int (WINAPI* PFN_D3DPERF_END_EVENT)();
|
|
|
|
typedef void (WINAPI* PFN_D3DPERF_SET_MARKER)(DWORD _color, LPCWSTR _wszName);
|
|
|
|
typedef void (WINAPI* PFN_D3DPERF_SET_REGION)(DWORD _color, LPCWSTR _wszName);
|
|
|
|
typedef BOOL (WINAPI* PFN_D3DPERF_QUERY_REPEAT_FRAME)();
|
|
|
|
typedef void (WINAPI* PFN_D3DPERF_SET_OPTIONS)(DWORD _options);
|
|
|
|
typedef DWORD (WINAPI* PFN_D3DPERF_GET_STATUS)();
|
|
|
|
typedef HRESULT (WINAPI* PFN_CREATE_DXGI_FACTORY)(REFIID _riid, void** _factory);
|
2015-07-29 17:49:24 -04:00
|
|
|
typedef HRESULT (WINAPI* PFN_GET_DEBUG_INTERFACE)(REFIID _riid, void** _debug);
|
|
|
|
typedef HRESULT (WINAPI* PFN_GET_DEBUG_INTERFACE1)(UINT _flags, REFIID _riid, void** _debug);
|
2013-06-09 18:28:25 -04:00
|
|
|
|
2014-10-07 01:10:55 -04:00
|
|
|
#define _PIX_SETMARKER(_col, _name) D3DPERF_SetMarker(_col, _name)
|
|
|
|
#define _PIX_BEGINEVENT(_col, _name) D3DPERF_BeginEvent(_col, _name)
|
|
|
|
#define _PIX_ENDEVENT() D3DPERF_EndEvent()
|
2013-06-09 18:28:25 -04:00
|
|
|
|
|
|
|
#if BGFX_CONFIG_DEBUG_PIX
|
2014-10-26 03:55:49 -04:00
|
|
|
# define PIX_SETMARKER(_color, _name) _PIX_SETMARKER(_color, _name)
|
2013-06-09 18:28:25 -04:00
|
|
|
# define PIX_BEGINEVENT(_color, _name) _PIX_BEGINEVENT(_color, _name)
|
|
|
|
# define PIX_ENDEVENT() _PIX_ENDEVENT()
|
|
|
|
#else
|
2014-10-26 03:55:49 -04:00
|
|
|
# define PIX_SETMARKER(_color, _name) BX_UNUSED(_name)
|
|
|
|
# define PIX_BEGINEVENT(_color, _name) BX_UNUSED(_name)
|
2013-06-09 18:28:25 -04:00
|
|
|
# define PIX_ENDEVENT()
|
|
|
|
#endif // BGFX_CONFIG_DEBUG_PIX
|
|
|
|
|
2013-02-22 00:07:31 -05:00
|
|
|
inline int getRefCount(IUnknown* _interface)
|
|
|
|
{
|
|
|
|
_interface->AddRef();
|
|
|
|
return _interface->Release();
|
|
|
|
}
|
|
|
|
|
2014-10-08 01:05:35 -04:00
|
|
|
template <typename Ty>
|
|
|
|
class StateCacheT
|
|
|
|
{
|
|
|
|
public:
|
2015-08-15 21:07:43 -04:00
|
|
|
void add(uint64_t _key, Ty* _value)
|
2014-10-08 01:05:35 -04:00
|
|
|
{
|
2015-08-15 21:07:43 -04:00
|
|
|
invalidate(_key);
|
|
|
|
m_hashMap.insert(stl::make_pair(_key, _value) );
|
2014-10-08 01:05:35 -04:00
|
|
|
}
|
|
|
|
|
2015-08-15 21:07:43 -04:00
|
|
|
Ty* find(uint64_t _key)
|
2014-10-08 01:05:35 -04:00
|
|
|
{
|
2015-08-15 21:07:43 -04:00
|
|
|
typename HashMap::iterator it = m_hashMap.find(_key);
|
2014-10-08 01:05:35 -04:00
|
|
|
if (it != m_hashMap.end() )
|
|
|
|
{
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-08-15 21:07:43 -04:00
|
|
|
void invalidate(uint64_t _key)
|
2014-10-08 01:05:35 -04:00
|
|
|
{
|
2015-08-15 21:07:43 -04:00
|
|
|
typename HashMap::iterator it = m_hashMap.find(_key);
|
2014-10-08 01:05:35 -04:00
|
|
|
if (it != m_hashMap.end() )
|
|
|
|
{
|
|
|
|
DX_RELEASE_WARNONLY(it->second, 0);
|
|
|
|
m_hashMap.erase(it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate()
|
|
|
|
{
|
|
|
|
for (typename HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it)
|
|
|
|
{
|
|
|
|
DX_CHECK_REFCOUNT(it->second, 1);
|
|
|
|
it->second->Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_hashMap.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t getCount() const
|
|
|
|
{
|
|
|
|
return uint32_t(m_hashMap.size() );
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
typedef stl::unordered_map<uint64_t, Ty*> HashMap;
|
|
|
|
HashMap m_hashMap;
|
|
|
|
};
|
|
|
|
|
2015-03-06 00:11:44 -05:00
|
|
|
class StateCache
|
|
|
|
{
|
|
|
|
public:
|
2015-08-15 21:07:43 -04:00
|
|
|
void add(uint64_t _key, uint16_t _value)
|
2015-03-06 00:11:44 -05:00
|
|
|
{
|
2015-08-15 21:07:43 -04:00
|
|
|
invalidate(_key);
|
|
|
|
m_hashMap.insert(stl::make_pair(_key, _value) );
|
2015-03-06 00:11:44 -05:00
|
|
|
}
|
|
|
|
|
2015-08-15 21:07:43 -04:00
|
|
|
uint16_t find(uint64_t _key)
|
2015-03-06 00:11:44 -05:00
|
|
|
{
|
2015-08-15 21:07:43 -04:00
|
|
|
HashMap::iterator it = m_hashMap.find(_key);
|
2015-07-16 23:28:43 -04:00
|
|
|
if (it != m_hashMap.end() )
|
2015-03-06 00:11:44 -05:00
|
|
|
{
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
return UINT16_MAX;
|
|
|
|
}
|
|
|
|
|
2015-08-15 21:07:43 -04:00
|
|
|
void invalidate(uint64_t _key)
|
2015-03-06 00:11:44 -05:00
|
|
|
{
|
2015-08-15 21:07:43 -04:00
|
|
|
HashMap::iterator it = m_hashMap.find(_key);
|
2015-07-16 23:28:43 -04:00
|
|
|
if (it != m_hashMap.end() )
|
2015-03-06 00:11:44 -05:00
|
|
|
{
|
|
|
|
m_hashMap.erase(it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate()
|
|
|
|
{
|
|
|
|
m_hashMap.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t getCount() const
|
|
|
|
{
|
2015-07-16 23:28:43 -04:00
|
|
|
return uint32_t(m_hashMap.size() );
|
2015-03-06 00:11:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
typedef stl::unordered_map<uint64_t, uint16_t> HashMap;
|
|
|
|
HashMap m_hashMap;
|
|
|
|
};
|
|
|
|
|
2015-08-17 14:25:27 -04:00
|
|
|
template<typename Ty>
|
|
|
|
inline void release(Ty)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline void release<IUnknown*>(IUnknown* _ptr)
|
|
|
|
{
|
|
|
|
DX_RELEASE(_ptr, 0);
|
|
|
|
}
|
|
|
|
|
2015-08-14 01:56:28 -04:00
|
|
|
template <typename Ty, uint16_t MaxHandleT>
|
|
|
|
class StateCacheLru
|
|
|
|
{
|
|
|
|
public:
|
2015-08-15 21:07:43 -04:00
|
|
|
void add(uint64_t _key, Ty _value, uint16_t _parent)
|
2015-08-14 01:56:28 -04:00
|
|
|
{
|
|
|
|
uint16_t handle = m_alloc.alloc();
|
|
|
|
if (UINT16_MAX == handle)
|
|
|
|
{
|
|
|
|
uint16_t back = m_alloc.getBack();
|
2015-08-15 21:07:43 -04:00
|
|
|
invalidate(back);
|
2015-08-14 01:56:28 -04:00
|
|
|
handle = m_alloc.alloc();
|
|
|
|
}
|
|
|
|
|
|
|
|
BX_CHECK(UINT16_MAX != handle, "Failed to find handle.");
|
|
|
|
|
|
|
|
Data& data = m_data[handle];
|
2015-08-15 21:07:43 -04:00
|
|
|
data.m_hash = _key;
|
|
|
|
data.m_value = _value;
|
|
|
|
data.m_parent = _parent;
|
|
|
|
m_hashMap.insert(stl::make_pair(_key, handle) );
|
2015-08-14 01:56:28 -04:00
|
|
|
}
|
|
|
|
|
2015-08-15 21:07:43 -04:00
|
|
|
Ty* find(uint64_t _key)
|
2015-08-14 01:56:28 -04:00
|
|
|
{
|
2015-08-15 21:07:43 -04:00
|
|
|
HashMap::iterator it = m_hashMap.find(_key);
|
2015-08-14 01:56:28 -04:00
|
|
|
if (it != m_hashMap.end() )
|
|
|
|
{
|
2015-08-14 22:32:36 -04:00
|
|
|
uint16_t handle = it->second;
|
|
|
|
m_alloc.touch(handle);
|
|
|
|
return &m_data[handle].m_value;
|
2015-08-14 01:56:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-08-15 21:07:43 -04:00
|
|
|
void invalidate(uint64_t _key)
|
|
|
|
{
|
|
|
|
HashMap::iterator it = m_hashMap.find(_key);
|
|
|
|
if (it != m_hashMap.end() )
|
|
|
|
{
|
|
|
|
uint16_t handle = it->second;
|
2015-08-17 14:25:27 -04:00
|
|
|
m_alloc.free(handle);
|
2015-08-15 21:07:43 -04:00
|
|
|
m_hashMap.erase(it);
|
|
|
|
release(m_data[handle].m_value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate(uint16_t _handle)
|
|
|
|
{
|
|
|
|
if (m_alloc.isValid(_handle) )
|
|
|
|
{
|
|
|
|
m_alloc.free(_handle);
|
|
|
|
Data& data = m_data[_handle];
|
|
|
|
m_hashMap.erase(m_hashMap.find(data.m_hash) );
|
|
|
|
release(data.m_value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidateWithParent(uint16_t _parent)
|
|
|
|
{
|
2015-08-17 14:25:27 -04:00
|
|
|
for (uint16_t ii = 0; ii < m_alloc.getNumHandles();)
|
2015-08-15 21:07:43 -04:00
|
|
|
{
|
|
|
|
uint16_t handle = m_alloc.getHandleAt(ii);
|
|
|
|
Data& data = m_data[handle];
|
|
|
|
|
|
|
|
if (data.m_parent == _parent)
|
|
|
|
{
|
|
|
|
m_alloc.free(handle);
|
|
|
|
m_hashMap.erase(m_hashMap.find(data.m_hash) );
|
|
|
|
release(data.m_value);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
++ii;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-14 01:56:28 -04:00
|
|
|
void invalidate()
|
|
|
|
{
|
2015-08-17 14:25:27 -04:00
|
|
|
for (uint16_t ii = 0, num = m_alloc.getNumHandles(); ii < num; ++ii)
|
2015-08-15 21:07:43 -04:00
|
|
|
{
|
|
|
|
uint16_t handle = m_alloc.getHandleAt(ii);
|
|
|
|
Data& data = m_data[handle];
|
|
|
|
release(data.m_value);
|
|
|
|
}
|
|
|
|
|
2015-08-14 01:56:28 -04:00
|
|
|
m_hashMap.clear();
|
|
|
|
m_alloc.reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t getCount() const
|
|
|
|
{
|
|
|
|
return uint32_t(m_hashMap.size() );
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
typedef stl::unordered_map<uint64_t, uint16_t> HashMap;
|
|
|
|
HashMap m_hashMap;
|
|
|
|
bx::HandleAllocLruT<MaxHandleT> m_alloc;
|
|
|
|
struct Data
|
|
|
|
{
|
|
|
|
uint64_t m_hash;
|
|
|
|
Ty m_value;
|
2015-08-15 21:07:43 -04:00
|
|
|
uint16_t m_parent;
|
2015-08-14 01:56:28 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
Data m_data[MaxHandleT];
|
|
|
|
};
|
|
|
|
|
2013-02-22 00:07:31 -05:00
|
|
|
} // namespace bgfx
|
|
|
|
|
2013-11-14 00:54:36 -05:00
|
|
|
#endif // BGFX_RENDERER_D3D_H_HEADER_GUARD
|