Skip to content

Instantly share code, notes, and snippets.

@wackoisgod
Created June 22, 2020 03:13
Show Gist options
  • Save wackoisgod/01a747df2312482d31328851fc6cef82 to your computer and use it in GitHub Desktop.
Save wackoisgod/01a747df2312482d31328851fc6cef82 to your computer and use it in GitHub Desktop.
#include <dlfcn.h>
#include <stdlib.h>
#include <iostream>
#include <atomic>
#include <vector>
#include <cassert>
#define CoTaskMemAlloc malloc
#define CoTaskMemFree free
#define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))
#define _countof(a) (sizeof(a) / sizeof(*(a)))
#define MAX_DXCORE_DRIVERSTORE_LIBRAIRIES (16)
#define DXCORE_MAX_PATH 260
typedef unsigned char BYTE;
typedef unsigned char *LPBYTE;
typedef BYTE BOOLEAN;
typedef BOOLEAN *PBOOLEAN;
typedef bool BOOL;
typedef BOOL *LPBOOL;
typedef int INT;
typedef long LONG;
typedef unsigned int UINT;
typedef unsigned long ULONG;
typedef long long LONGLONG;
typedef long long LONG_PTR;
typedef unsigned long long ULONGLONG;
typedef uint16_t WORD;
typedef uint32_t DWORD;
typedef DWORD *LPDWORD;
typedef uint32_t UINT32;
typedef uint64_t UINT64;
typedef signed char INT8, *PINT8;
typedef signed int INT32, *PINT32;
typedef size_t SIZE_T;
typedef const char *LPCSTR;
typedef const char *PCSTR;
typedef int errno_t;
typedef wchar_t WCHAR;
typedef wchar_t *LPWSTR;
typedef wchar_t *PWCHAR;
typedef const wchar_t *LPCWSTR;
typedef const wchar_t *PCWSTR;
typedef WCHAR OLECHAR;
typedef OLECHAR *BSTR;
typedef OLECHAR *LPOLESTR;
typedef char *LPSTR;
typedef void *LPVOID;
typedef const void *LPCVOID;
typedef std::nullptr_t nullptr_t;
typedef signed int HRESULT;
#define S_OK ((HRESULT)0L)
#define S_FALSE ((HRESULT)1L)
#define E_ABORT (HRESULT)0x80004004
#define E_ACCESSDENIED (HRESULT)0x80070005
#define E_BOUNDS (HRESULT)0x8000000B
#define E_FAIL (HRESULT)0x80004005
#define E_HANDLE (HRESULT)0x80070006
#define E_INVALIDARG (HRESULT)0x80070057
#define E_NOINTERFACE (HRESULT)0x80004002
#define E_NOTIMPL (HRESULT)0x80004001
#define E_NOT_VALID_STATE (HRESULT)0x8007139F
#define E_OUTOFMEMORY (HRESULT)0x8007000E
#define E_POINTER (HRESULT)0x80004003
#define E_UNEXPECTED (HRESULT)0x8000FFFF
#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
#define FAILED(hr) (((HRESULT)(hr)) < 0)
#define DXC_FAILED(hr) (((HRESULT)(hr)) < 0)
#define HRESULT_FROM_WIN32(x) \
(HRESULT)(x) <= 0 ? (HRESULT)(x) \
: (HRESULT)(((x)&0x0000FFFF) | (7 << 16) | 0x80000000)
#define SEVERITY_ERROR 1
#define FACILITY_WIN32 7
#define HRESULT_CODE(hr) ((hr)&0xFFFF)
#define MAKE_HRESULT(severity, facility, code) \
((HRESULT)(((unsigned long)(severity) << 31) | \
((unsigned long)(facility) << 16) | ((unsigned long)(code))))
#define _In_
#define _In_z_
#define _In_opt_
#define _In_opt_count_(size)
#define _In_opt_z_
#define _In_reads_(size)
#define _In_reads_bytes_(size)
#define _In_reads_bytes_opt_(size)
#define _In_reads_opt_(size)
#define _In_reads_to_ptr_(ptr)
#define _In_count_(size)
#define _In_range_(lb, ub)
#define _In_bytecount_(size)
#define _In_opt_bytecount_(size)
#define _In_NLS_string_(size)
#define __in_bcount(size)
#define _Out_
#define _Out_bytecap_(nbytes)
#define _Out_writes_to_(a, b)
#define _Out_writes_to_opt_(a, b)
#define _Outptr_
#define _Outptr_opt_
#define _Outptr_opt_result_z_
#define _Out_opt_
#define _Out_writes_(size)
#define _Out_write_bytes_(size)
#define _Out_writes_z_(size)
#define _Out_writes_all_(size)
#define _Out_writes_bytes_(size)
#define _Outref_result_buffer_(size)
#define _Outptr_result_buffer_(size)
#define _Out_cap_(size)
#define _Out_cap_x_(size)
#define _Out_range_(lb, ub)
#define _Outptr_result_z_
#define _Outptr_result_buffer_maybenull_(ptr)
#define _Outptr_result_maybenull_
#define _Outptr_result_nullonfailure_
#define __out_ecount_part(a, b)
#define _Inout_
#define _Inout_z_
#define _Inout_opt_
#define _Inout_cap_(size)
#define _Inout_count_(size)
#define _Inout_count_c_(size)
#define _Inout_opt_count_c_(size)
#define _Inout_bytecount_c_(size)
#define _Inout_opt_bytecount_c_(size)
#define _Ret_maybenull_
#define _Ret_notnull_
#define _Ret_opt_
#define _Use_decl_annotations_
#define __analysis_assume(expr)
#define _Analysis_assume_(expr)
#define _Analysis_assume_nullterminated_(x)
#define _Success_(expr)
#define __inexpressible_readableTo(size)
#define __inexpressible_writableTo(size)
#define _Printf_format_string_
#define _Null_terminated_
#define __fallthrough
#define _Field_size_(size)
#define _Field_size_full_(size)
#define _Field_size_opt_(size)
#define _Post_writable_byte_size_(size)
#define _Post_readable_byte_size_(size)
#define __drv_allocatesMem(mem)
#define _COM_Outptr_
#define _COM_Outptr_opt_
#define _COM_Outptr_result_maybenull_
#define _COM_Outptr_opt_result_maybenull_
#define _Null_
#define _Notnull_
#define _Maybenull_
#define _Outptr_result_bytebuffer_(size)
#define __debugbreak()
#define __declspec(x)
#define uuid(id)
#define STDMETHODCALLTYPE
#define STDAPI extern "C" HRESULT STDAPICALLTYPE
#define STDAPI_(type) extern "C" type STDAPICALLTYPE
#define STDMETHODIMP HRESULT STDMETHODCALLTYPE
#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
/* GUID handling */
typedef struct _GUID {
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint8_t Data4[8];
} GUID;
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
const GUID name = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}}
#define DEFINE_OLEGUID(name, l, w1, w2) DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0);
DEFINE_GUID(IID_IDXCoreAdapterFactory, 0x78ee5945, 0xc36e, 0x4b13, 0xa6, 0x69, 0x00, 0x5d, 0xd1, 0x1c, 0x0f, 0x06);
DEFINE_GUID(IID_IDXCoreAdapterList, 0x526c7776, 0x40e9, 0x459b, 0xb7, 0x11, 0xf3, 0x2a, 0xd7, 0x6d, 0xfc, 0x28);
DEFINE_GUID(IID_IDXCoreAdapter, 0xf0db4c7f, 0xfe5a, 0x42a2, 0xbd, 0x62, 0xf2, 0xa6, 0xcf, 0x6f, 0xc8, 0x3e);
DEFINE_GUID(DXCORE_ADAPTER_ATTRIBUTE_D3D11_GRAPHICS, 0x8c47866b, 0x7583, 0x450d, 0xf0, 0xf0, 0x6b, 0xad, 0xa8, 0x95, 0xaf, 0x4b);
DEFINE_GUID(DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS, 0x0c9ece4d, 0x2f6e, 0x4f01, 0x8c, 0x96, 0xe8, 0x9e, 0x33, 0x1b, 0x47, 0xb1);
DEFINE_GUID(DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE, 0x248e2800, 0xa793, 0x4724, 0xab, 0xaa, 0x23, 0xa6, 0xde, 0x1b, 0xe0, 0x90);
typedef signed int HRESULT;
typedef void *HANDLE;
#define DECLARE_HANDLE(name) \
struct name##__ { \
int unused; \
}; \
typedef struct name##__ *name
DECLARE_HANDLE(HINSTANCE);
typedef void *HMODULE;
typedef GUID CLSID;
typedef const GUID &REFGUID;
typedef const GUID &REFCLSID;
typedef GUID IID;
#define REFIID const IID &
#define IsEqualIID(a, b) a == b
#define IsEqualCLSID(a, b) !memcmp(&a, &b, sizeof(GUID))
size_t UuidStrHash(const char* k) {
long h = 0;
while (*k) {
h = (h << 4) + *(k++);
long g = h & 0xF0000000L;
if (g != 0)
h ^= g >> 24;
h &= ~g;
}
return h;
}
// The following macros are defined to facilitate the lack of 'uuid' on Linux.
#define DECLARE_CROSS_PLATFORM_UUIDOF(T) \
public: \
static REFIID uuidof() { return reinterpret_cast<REFIID>(IID_##T); } \
\
private: \
__attribute__((visibility("default"))) static const size_t T##_ID;
#define DEFINE_CROSS_PLATFORM_UUIDOF(T) \
__attribute__((visibility("default"))) const size_t T::T##_ID = \
UuidStrHash(#T);
#define __uuidof(T) T::uuidof()
#define IID_PPV_ARGS(ppType) \
(**(ppType)).uuidof(), reinterpret_cast<void **>(ppType)
typedef struct _LUID {
DWORD LowPart;
LONG HighPart;
} LUID, *PLUID;
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;
typedef union _LARGE_INTEGER {
struct {
DWORD LowPart;
DWORD HighPart;
} u;
LONGLONG QuadPart;
} LARGE_INTEGER;
typedef LARGE_INTEGER *PLARGE_INTEGER;
typedef union _ULARGE_INTEGER {
struct {
DWORD LowPart;
DWORD HighPart;
} u;
ULONGLONG QuadPart;
} ULARGE_INTEGER;
typedef struct tagSTATSTG {
LPOLESTR pwcsName;
DWORD type;
ULARGE_INTEGER cbSize;
FILETIME mtime;
FILETIME ctime;
FILETIME atime;
DWORD grfMode;
DWORD grfLocksSupported;
CLSID clsid;
DWORD grfStateBits;
DWORD reserved;
} STATSTG;
enum tagSTATFLAG {
STATFLAG_DEFAULT = 0,
STATFLAG_NONAME = 1,
STATFLAG_NOOPEN = 2
};
struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {
virtual HRESULT QueryInterface(REFIID riid, void **ppvObject) = 0;
virtual ULONG AddRef() = 0;
virtual ULONG Release() = 0;
template <class Q> HRESULT QueryInterface(Q **pp) {
return QueryInterface(__uuidof(Q), (void **)pp);
}
DECLARE_CROSS_PLATFORM_UUIDOF(IUnknown)
};
enum class DXCoreAdapterProperty : uint32_t
{
InstanceLuid = 0,
DriverVersion = 1,
DriverDescription = 2,
HardwareID = 3,
KmdModelVersion = 4,
ComputePreemptionGranularity = 5,
GraphicsPreemptionGranularity = 6,
DedicatedAdapterMemory = 7,
DedicatedSystemMemory = 8,
SharedSystemMemory = 9,
AcgCompatible = 10,
IsHardware = 11,
IsIntegrated = 12,
IsDetachable = 13
};
enum class DXCoreAdapterState : uint32_t
{
IsDriverUpdateInProgress = 0,
AdapterMemoryBudget = 1
};
enum class DXCoreSegmentGroup : uint32_t
{
Local = 0,
NonLocal = 1
};
enum class DXCoreNotificationType : uint32_t
{
AdapterListStale = 0,
AdapterNoLongerValid = 1,
AdapterBudgetChange = 2,
AdapterHardwareContentProtectionTeardown = 3
};
enum class DXCoreAdapterPreference : uint32_t
{
Hardware = 0,
MinimumPower = 1,
HighPerformance = 2
};
struct DXCoreHardwareID
{
uint32_t vendorID;
uint32_t deviceID;
uint32_t subSysID;
uint32_t revision;
};
struct DXCoreAdapterMemoryBudgetNodeSegmentGroup
{
uint32_t nodeIndex;
DXCoreSegmentGroup segmentGroup;
};
struct DXCoreAdapterMemoryBudget
{
uint64_t budget;
uint64_t currentUsage;
uint64_t availableForReservation;
uint64_t currentReservation;
};
typedef void (STDMETHODCALLTYPE *PFN_DXCORE_NOTIFICATION_CALLBACK)(
DXCoreNotificationType notificationType,
_In_ IUnknown *object,
_In_opt_ void *context);
struct __declspec(uuid("f0db4c7f-fe5a-42a2-bd62-f2a6cf6fc83e")) IDXCoreAdapter : public IUnknown
{
public:
virtual bool STDMETHODCALLTYPE IsValid() = 0;
virtual bool STDMETHODCALLTYPE IsAttributeSupported(
REFGUID attributeGUID) = 0;
virtual bool STDMETHODCALLTYPE IsPropertySupported(
DXCoreAdapterProperty property) = 0;
virtual HRESULT STDMETHODCALLTYPE GetProperty(
DXCoreAdapterProperty property,
size_t bufferSize,
_Out_writes_bytes_(bufferSize) void *propertyData) = 0;
template <class T>
HRESULT GetProperty(
DXCoreAdapterProperty property,
_Out_writes_bytes_(sizeof(T)) T *propertyData)
{
return GetProperty(property,
sizeof(T),
(void*)propertyData);
}
virtual HRESULT STDMETHODCALLTYPE GetPropertySize(
DXCoreAdapterProperty property,
_Out_ size_t *bufferSize) = 0;
virtual bool STDMETHODCALLTYPE IsQueryStateSupported(
DXCoreAdapterState property) = 0;
virtual HRESULT STDMETHODCALLTYPE QueryState(
DXCoreAdapterState state,
size_t inputStateDetailsSize,
_In_reads_bytes_opt_(inputStateDetailsSize) const void *inputStateDetails,
size_t outputBufferSize,
_Out_writes_bytes_(outputBufferSize) void *outputBuffer) = 0;
template <class T1, class T2>
HRESULT QueryState(
DXCoreAdapterState state,
_In_reads_bytes_opt_(sizeof(T1)) const T1 *inputStateDetails,
_Out_writes_bytes_(sizeof(T2)) T2 *outputBuffer)
{
return QueryState(state,
sizeof(T1),
(const void*)inputStateDetails,
sizeof(T2),
(void*)outputBuffer);
}
template <class T>
HRESULT QueryState(
DXCoreAdapterState state,
_Out_writes_bytes_(sizeof(T)) T *outputBuffer)
{
return QueryState(state,
0,
nullptr,
sizeof(T),
(void*)outputBuffer);
}
virtual bool STDMETHODCALLTYPE IsSetStateSupported(
DXCoreAdapterState property) = 0;
virtual HRESULT STDMETHODCALLTYPE SetState(
DXCoreAdapterState state,
size_t inputStateDetailsSize,
_In_reads_bytes_opt_(inputStateDetailsSize) const void *inputStateDetails,
size_t inputDataSize,
_In_reads_bytes_(inputDataSize) const void *inputData) = 0;
template <class T1, class T2>
HRESULT SetState(
DXCoreAdapterState state,
const T1 *inputStateDetails,
const T2 *inputData)
{
return SetState(state,
sizeof(T1),
(const void*)inputStateDetails,
sizeof(T2),
(const void*)inputData);
}
virtual HRESULT STDMETHODCALLTYPE GetFactory(
REFIID riid,
_COM_Outptr_ void** ppvFactory
) = 0;
template <class T>
HRESULT GetFactory(
_COM_Outptr_ T** ppvFactory
)
{
return GetFactory(IID_PPV_ARGS(ppvFactory));
}
DECLARE_CROSS_PLATFORM_UUIDOF(IDXCoreAdapter)
};
struct __declspec(uuid("526c7776-40e9-459b-b711-f32ad76dfc28")) IDXCoreAdapterList : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetAdapter(
uint32_t index,
REFIID riid,
_COM_Outptr_ void **ppvAdapter) = 0;
virtual uint32_t STDMETHODCALLTYPE GetAdapterCount() = 0;
virtual bool STDMETHODCALLTYPE IsStale() = 0;
virtual HRESULT STDMETHODCALLTYPE GetFactory(
REFIID riid,
_COM_Outptr_ void** ppvFactory
) = 0;
template <class T>
HRESULT GetFactory(
_COM_Outptr_ T** ppvFactory
)
{
return GetFactory(IID_PPV_ARGS(ppvFactory));
}
virtual HRESULT STDMETHODCALLTYPE Sort(
uint32_t numPreferences,
_In_reads_(numPreferences) const DXCoreAdapterPreference* preferences) = 0;
virtual bool STDMETHODCALLTYPE IsAdapterPreferenceSupported(
DXCoreAdapterPreference preference) = 0;
DECLARE_CROSS_PLATFORM_UUIDOF(IDXCoreAdapterList)
};
struct __declspec(uuid("78ee5945-c36e-4b13-a669-005dd11c0f06")) IDXCoreAdapterFactory : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE CreateAdapterList(
uint32_t numAttributes,
_In_reads_(numAttributes) const GUID *filterAttributes,
REFIID riid,
_COM_Outptr_ void **ppvAdapterList) = 0;
template<class T>
HRESULT STDMETHODCALLTYPE CreateAdapterList(
uint32_t numAttributes,
_In_reads_(numAttributes) const GUID *filterAttributes,
_COM_Outptr_ T **ppvAdapterList)
{
return CreateAdapterList(numAttributes,
filterAttributes,
IID_PPV_ARGS(ppvAdapterList));
}
virtual HRESULT STDMETHODCALLTYPE GetAdapterByLuid(
const LUID &adapterLUID,
REFIID riid,
_COM_Outptr_ void **ppvAdapter) = 0;
template<class T>
HRESULT STDMETHODCALLTYPE GetAdapterByLuid(
const LUID &adapterLUID,
_COM_Outptr_ T **ppvAdapter)
{
return GetAdapterByLuid(adapterLUID,
IID_PPV_ARGS(ppvAdapter));
}
virtual bool STDMETHODCALLTYPE IsNotificationTypeSupported(
DXCoreNotificationType notificationType) = 0;
virtual HRESULT STDMETHODCALLTYPE RegisterEventNotification(
_In_ IUnknown *dxCoreObject,
DXCoreNotificationType notificationType,
_In_ PFN_DXCORE_NOTIFICATION_CALLBACK callbackFunction,
_In_opt_ void *callbackContext,
_Out_ uint32_t *eventCookie) = 0;
virtual HRESULT STDMETHODCALLTYPE UnregisterEventNotification(
uint32_t eventCookie) = 0;
DECLARE_CROSS_PLATFORM_UUIDOF(IDXCoreAdapterFactory)
};
struct dxcore_enumAdapters2;
struct dxcore_queryAdapterInfo;
typedef int(*pfnDxcoreEnumAdapters2)(struct dxcore_enumAdapters2* pParams);
typedef int(*pfnDxcoreQueryAdapterInfo)(struct dxcore_queryAdapterInfo* pParams);
typedef HRESULT(*pfnDXCoreCreateAdapterFactory)(REFIID, _COM_Outptr_ void**);
enum dxcore_kmtqueryAdapterInfoType
{
DXCORE_QUERYDRIVERVERSION = 13,
DXCORE_QUERYREGISTRY = 48,
KMTQAITYPE_DISPLAY_UMDRIVERNAME = 71,
};
struct dxcore_context
{
unsigned int adapterCount;
struct dxcore_adapter *adapterList;
int initialized;
};
struct dxcore_adapter
{
unsigned int hAdapter;
unsigned int wddmVersion;
char* pDriverStorePath;
unsigned int driverStoreLibraryCount;
const char* pDriverStoreLibraries[MAX_DXCORE_DRIVERSTORE_LIBRAIRIES];
struct dxcore_context *pContext;
};
struct dxcore_luid
{
unsigned int lowPart;
int highPart;
};
struct dxcore_adapterInfo
{
unsigned int hAdapter;
struct dxcore_luid AdapterLuid;
unsigned int NumOfSources;
unsigned int bPresentMoveRegionsPreferred;
};
struct dxcore_enumAdapters2
{
unsigned int NumAdapters;
struct dxcore_adapterInfo *pAdapters;
};
enum dxcore_queryregistry_type {
DXCORE_QUERYREGISTRY_DRIVERSTOREPATH = 2,
DXCORE_QUERYREGISTRY_DRIVERIMAGEPATH = 3,
};
enum dxcore_queryregistry_status {
DXCORE_QUERYREGISTRY_STATUS_SUCCESS = 0,
DXCORE_QUERYREGISTRY_STATUS_BUFFER_OVERFLOW = 1,
DXCORE_QUERYREGISTRY_STATUS_FAIL = 2,
};
struct dxcore_queryregistry_info {
enum dxcore_queryregistry_type QueryType;
unsigned int QueryFlags;
wchar_t ValueName[DXCORE_MAX_PATH];
unsigned int ValueType;
unsigned int PhysicalAdapterIndex;
unsigned int OutputValueSize;
enum dxcore_queryregistry_status Status;
union {
unsigned long long OutputQword;
wchar_t Output;
};
};
struct dxcore_queryAdapterInfo
{
unsigned int hAdapter;
enum dxcore_kmtqueryAdapterInfoType Type;
void *pPrivateDriverData;
unsigned int PrivateDriverDataSize;
};
class CAllocator {
public:
static void *Reallocate(void *p, size_t nBytes) throw();
static void *Allocate(size_t nBytes) throw();
static void Free(void *p) throw();
};
template <class T> class CComPtrBase {
protected:
CComPtrBase() throw() { p = nullptr; }
CComPtrBase(T *lp) throw() {
p = lp;
if (p != nullptr)
p->AddRef();
}
void Swap(CComPtrBase &other) {
T *pTemp = p;
p = other.p;
other.p = pTemp;
}
public:
~CComPtrBase() throw() {
if (p) {
p->Release();
p = nullptr;
}
}
operator T *() const throw() { return p; }
T &operator*() const { return *p; }
T *operator->() const { return p; }
T **operator&() throw() {
assert(p == nullptr);
return &p;
}
T **put() noexcept
{
return &p;
}
T *Get() const throw()
{
return p;
}
bool operator!() const throw() { return (p == nullptr); }
bool operator<(T *pT) const throw() { return p < pT; }
bool operator!=(T *pT) const { return !operator==(pT); }
bool operator==(T *pT) const throw() { return p == pT; }
// Release the interface and set to nullptr
void Release() throw() {
T *pTemp = p;
if (pTemp) {
p = nullptr;
pTemp->Release();
}
}
// Attach to an existing interface (does not AddRef)
void Attach(T *p2) throw() {
if (p) {
ULONG ref = p->Release();
(void)(ref);
// Attaching to the same object only works if duplicate references are
// being coalesced. Otherwise re-attaching will cause the pointer to be
// released and may cause a crash on a subsequent dereference.
assert(ref != 0 || p2 != p);
}
p = p2;
}
// Detach the interface (does not Release)
T *Detach() throw() {
T *pt = p;
p = nullptr;
return pt;
}
HRESULT CopyTo(T **ppT) throw() {
assert(ppT != nullptr);
if (ppT == nullptr)
return E_POINTER;
*ppT = p;
if (p)
p->AddRef();
return S_OK;
}
template <class Q> HRESULT QueryInterface(Q **pp) const throw() {
assert(pp != nullptr);
return p->QueryInterface(__uuidof(Q), (void **)pp);
}
T *p;
};
template <class T> class CComPtr : public CComPtrBase<T> {
public:
CComPtr() throw() {}
CComPtr(T *lp) throw() : CComPtrBase<T>(lp) {}
CComPtr(const CComPtr<T> &lp) throw() : CComPtrBase<T>(lp.p) {}
T *operator=(T *lp) throw() {
if (*this != lp) {
CComPtr(lp).Swap(*this);
}
return *this;
}
inline bool IsEqualObject(IUnknown *pOther) throw() {
if (this->p == nullptr && pOther == nullptr)
return true; // They are both NULL objects
if (this->p == nullptr || pOther == nullptr)
return false; // One is NULL the other is not
CComPtr<IUnknown> punk1;
CComPtr<IUnknown> punk2;
this->p->QueryInterface(__uuidof(IUnknown), (void **)&punk1);
pOther->QueryInterface(__uuidof(IUnknown), (void **)&punk2);
return punk1 == punk2;
}
void ComPtrAssign(IUnknown **pp, IUnknown *lp, REFIID riid) {
IUnknown *pTemp = *pp; // takes ownership
if (lp == nullptr || FAILED(lp->QueryInterface(riid, (void **)pp)))
*pp = nullptr;
if (pTemp)
pTemp->Release();
}
template <typename Q> T *operator=(const CComPtr<Q> &lp) throw() {
if (!this->IsEqualObject(lp)) {
ComPtrAssign((IUnknown **)&this->p, lp, __uuidof(T));
}
return *this;
}
T *operator=(const CComPtr<T> &lp) throw() {
if (*this != lp) {
CComPtr(lp).Swap(*this);
}
return *this;
}
CComPtr(CComPtr<T> &&lp) throw() : CComPtrBase<T>() { lp.Swap(*this); }
T *operator=(CComPtr<T> &&lp) throw() {
if (*this != lp) {
CComPtr(static_cast<CComPtr &&>(lp)).Swap(*this);
}
return *this;
}
};
template <class T> class CSimpleArray : public std::vector<T> {
public:
bool Add(const T &t) {
this->push_back(t);
return true;
}
int GetSize() { return this->size(); }
T *GetData() { return this->data(); }
void RemoveAll() { this->clear(); }
};
template <class T, class Allocator = CAllocator> class CHeapPtrBase {
protected:
CHeapPtrBase() throw() : m_pData(NULL) {}
CHeapPtrBase(CHeapPtrBase<T, Allocator> &p) throw() {
m_pData = p.Detach(); // Transfer ownership
}
explicit CHeapPtrBase(T *pData) throw() : m_pData(pData) {}
public:
~CHeapPtrBase() throw() { Free(); }
protected:
CHeapPtrBase<T, Allocator> &operator=(CHeapPtrBase<T, Allocator> &p) throw() {
if (m_pData != p.m_pData)
Attach(p.Detach()); // Transfer ownership
return *this;
}
public:
operator T *() const throw() { return m_pData; }
T *operator->() const throw() {
assert(m_pData != NULL);
return m_pData;
}
T **operator&() throw() {
assert(m_pData == NULL);
return &m_pData;
}
// Allocate a buffer with the given number of bytes
bool AllocateBytes(size_t nBytes) throw() {
assert(m_pData == NULL);
m_pData = static_cast<T *>(Allocator::Allocate(nBytes * sizeof(char)));
if (m_pData == NULL)
return false;
return true;
}
// Attach to an existing pointer (takes ownership)
void Attach(T *pData) throw() {
Allocator::Free(m_pData);
m_pData = pData;
}
// Detach the pointer (releases ownership)
T *Detach() throw() {
T *pTemp = m_pData;
m_pData = NULL;
return pTemp;
}
// Free the memory pointed to, and set the pointer to NULL
void Free() throw() {
Allocator::Free(m_pData);
m_pData = NULL;
}
// Reallocate the buffer to hold a given number of bytes
bool ReallocateBytes(size_t nBytes) throw() {
T *pNew;
pNew =
static_cast<T *>(Allocator::Reallocate(m_pData, nBytes * sizeof(char)));
if (pNew == NULL)
return false;
m_pData = pNew;
return true;
}
public:
T *m_pData;
};
template <typename T, class Allocator = CAllocator>
class CHeapPtr : public CHeapPtrBase<T, Allocator> {
public:
CHeapPtr() throw() {}
CHeapPtr(CHeapPtr<T, Allocator> &p) throw() : CHeapPtrBase<T, Allocator>(p) {}
explicit CHeapPtr(T *p) throw() : CHeapPtrBase<T, Allocator>(p) {}
CHeapPtr<T> &operator=(CHeapPtr<T, Allocator> &p) throw() {
CHeapPtrBase<T, Allocator>::operator=(p);
return *this;
}
// Allocate a buffer with the given number of elements
bool Allocate(size_t nElements = 1) throw() {
size_t nBytes = nElements * sizeof(T);
return this->AllocateBytes(nBytes);
}
// Reallocate the buffer to hold a given number of elements
bool Reallocate(size_t nElements) throw() {
size_t nBytes = nElements * sizeof(T);
return this->ReallocateBytes(nBytes);
}
};
#define CComHeapPtr CHeapPtr
DEFINE_CROSS_PLATFORM_UUIDOF(IUnknown)
DEFINE_CROSS_PLATFORM_UUIDOF(IDXCoreAdapterFactory)
void *CAllocator::Reallocate(void *p, size_t nBytes) throw() {
return realloc(p, nBytes);
}
void *CAllocator::Allocate(size_t nBytes) throw() { return malloc(nBytes); }
void CAllocator::Free(void *p) throw() { free(p); }
#define FALSE 0
#define TRUE 1
#define ERROR_SUCCESS 0L
#define ERROR_ARITHMETIC_OVERFLOW EOVERFLOW
#define ERROR_FILE_NOT_FOUND ENOENT
#define ERROR_FUNCTION_NOT_CALLED ENOSYS
#define ERROR_IO_DEVICE EIO
#define ERROR_INSUFFICIENT_BUFFER ENOBUFS
#define ERROR_INVALID_HANDLE EBADF
#define ERROR_INVALID_PARAMETER EINVAL
#define ERROR_OUT_OF_STRUCTURES ENOMEM
#define ERROR_NOT_CAPABLE EPERM
#define ERROR_NOT_FOUND ENOTSUP
#define ERROR_UNHANDLED_EXCEPTION EINTR
#define ERROR_CAN_NOT_COMPLETE 1003
DWORD Win32FromHResult(HRESULT hr)
{
if ((hr & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0))
{
return HRESULT_CODE(hr);
}
if (hr == S_OK)
{
return ERROR_SUCCESS;
}
// Not a Win32 HRESULT so return a generic error code.
return ERROR_CAN_NOT_COMPLETE;
}
#include <link.h>
#define HRESULT_FROM_ERRNO(x) MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_ERRNO,(x))
int main()
{
void *hndl = dlopen("libd3d12.so", RTLD_NOW);
if(hndl == NULL){
std::cerr << dlerror() << std::endl;
exit(-1);
}
void *hndl2 = dlopen("libdxcore.so", RTLD_LAZY);
if(hndl2 == NULL){
std::cerr << dlerror() << std::endl;
exit(-1);
}
auto func = (pfnDXCoreCreateAdapterFactory)dlsym(hndl2, "DXCoreCreateAdapterFactory");
if(func == NULL){
printf("This be broken");
exit(-1);
}
CComPtr<IDXCoreAdapterFactory> adapterFactory;
if (SUCCEEDED(func(IID_PPV_ARGS(adapterFactory.put())))) {
printf("I have loaded all the things\n");
}
CComPtr<IDXCoreAdapterList> d3D12CoreComputeAdapters;
GUID attributes[]{ DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS };
if (SUCCEEDED(adapterFactory->CreateAdapterList(_countof(attributes), attributes, d3D12CoreComputeAdapters.put()))) {
if (d3D12CoreComputeAdapters.Get() == nullptr)
printf("BAAAAD\n");
const uint32_t count{ d3D12CoreComputeAdapters->GetAdapterCount() };
printf("%d\n", d3D12CoreComputeAdapters->IsStale());
}
// struct link_map* linkMap;
// auto x = dlinfo(hndl2, RTLD_DI_LINKMAP,(void*)&linkMap);
// printf("libdxcore.so slide: %llx\n", (long long) linkMap->l_addr);
// IDXCoreAdapterFactory* adapterFactory;
// if (SUCCEEDED(func(__uuidof(IDXCoreAdapterFactory), (void**)&adapterFactory))) {
// printf("I have loaded all the things %p\n", *(void **)adapterFactory);
// }
// IDXCoreAdapterList* d3D12CoreComputeAdapters;
// GUID attributes[]{ DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE };
// if (SUCCEEDED(adapterFactory->CreateAdapterList(_countof(attributes), attributes, &d3D12CoreComputeAdapters))) {
// printf("I have loaded all the things again\n");
// if (d3D12CoreComputeAdapters == nullptr)
// printf("BAAAAD\n");
// const uint32_t count{ d3D12CoreComputeAdapters->GetAdapterCount() };
// printf("%d\n", count);
// }
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment