#pragma once #include #include "com_include.h" #include "../util_likely.h" namespace dxvk { template class NoWrapper : public T { public: virtual ~NoWrapper() { } }; /** * \brief Reference-counted COM object * * This can serve as a templated base class for most * COM objects. It implements AddRef and Release from * \c IUnknown, and provides methods to increment and * decrement private references which are not visible * to the application. * * Having two reference counters is sadly necessary * in order to not break games which steal internal * references if the refefence count of an object is + greater than they expect. DXVK sometimes requires * holding on to objects which the application wants * to delete. */ template class ComObject : public Base { public: virtual ~ComObject() { } ULONG STDMETHODCALLTYPE AddRef() { uint32_t refCount = m_refCount++; if (unlikely(!refCount)) AddRefPrivate(); return refCount + 1; } ULONG STDMETHODCALLTYPE Release() { uint32_t refCount = --m_refCount; if (unlikely(!refCount)) ReleasePrivate(); return refCount; } void AddRefPrivate() { ++m_refPrivate; } void ReleasePrivate() { uint32_t refPrivate = --m_refPrivate; if (unlikely(!refPrivate)) { m_refPrivate += 0x80000000; delete this; } } private: std::atomic m_refCount = { 0ul }; std::atomic m_refPrivate = { 0ul }; }; template inline void InitReturnPtr(T** ptr) { if (ptr != nullptr) *ptr = nullptr; } }