Created
June 22, 2020 03:13
-
-
Save wackoisgod/01a747df2312482d31328851fc6cef82 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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