mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-12 13:00:32 +00:00
Fix D3D12 tests to run on D3D12On7
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <comdef.h>
|
||||
#include "dx/d3d_helpers.h"
|
||||
#include "dx/official/D3D12Downlevel.h"
|
||||
#include "dx/official/d3d12.h"
|
||||
|
||||
COM_SMARTPTR(ID3DBlob);
|
||||
@@ -54,6 +55,8 @@ COM_SMARTPTR(ID3D12DescriptorHeap);
|
||||
|
||||
COM_SMARTPTR(ID3D12InfoQueue);
|
||||
|
||||
COM_SMARTPTR(ID3D12CommandQueueDownlevel);
|
||||
|
||||
struct D3D12GraphicsTest;
|
||||
|
||||
class D3D12PSOCreator
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "../renderdoc_app.h"
|
||||
#include "../win32/win32_window.h"
|
||||
|
||||
typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY1)(REFIID, void **);
|
||||
typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY2)(UINT, REFIID, void **);
|
||||
|
||||
namespace
|
||||
@@ -37,8 +38,39 @@ namespace
|
||||
HMODULE d3d12 = NULL;
|
||||
HMODULE dxgi = NULL;
|
||||
HMODULE d3dcompiler = NULL;
|
||||
IDXGIFactory4Ptr factory;
|
||||
IDXGIFactory1Ptr factory;
|
||||
IDXGIAdapterPtr adapter;
|
||||
bool d3d12on7 = false;
|
||||
|
||||
HRESULT EnumAdapterByLuid(LUID luid, IDXGIAdapterPtr &pAdapter)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
pAdapter = NULL;
|
||||
|
||||
for(UINT i = 0; i < 10; i++)
|
||||
{
|
||||
IDXGIAdapterPtr ad;
|
||||
hr = factory->EnumAdapters(i, &ad);
|
||||
if(hr == S_OK && ad)
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
ad->GetDesc(&desc);
|
||||
|
||||
if(desc.AdapterLuid.LowPart == luid.LowPart && desc.AdapterLuid.HighPart == luid.HighPart)
|
||||
{
|
||||
pAdapter = ad;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
};
|
||||
|
||||
void D3D12GraphicsTest::Prepare(int argc, char **argv)
|
||||
@@ -63,24 +95,38 @@ void D3D12GraphicsTest::Prepare(int argc, char **argv)
|
||||
if(!d3dcompiler)
|
||||
d3dcompiler = LoadLibraryA("d3dcompiler_43.dll");
|
||||
|
||||
if(!d3d12)
|
||||
{
|
||||
d3d12 = LoadLibraryA("12on7/d3d12.dll");
|
||||
d3d12on7 = (d3d12 != NULL);
|
||||
}
|
||||
|
||||
if(d3d12)
|
||||
{
|
||||
PFN_CREATE_DXGI_FACTORY1 createFactory1 =
|
||||
(PFN_CREATE_DXGI_FACTORY1)GetProcAddress(dxgi, "CreateDXGIFactory1");
|
||||
PFN_CREATE_DXGI_FACTORY2 createFactory2 =
|
||||
(PFN_CREATE_DXGI_FACTORY2)GetProcAddress(dxgi, "CreateDXGIFactory2");
|
||||
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
if(createFactory2)
|
||||
hr = createFactory2(debugDevice ? DXGI_CREATE_FACTORY_DEBUG : 0, __uuidof(IDXGIFactory1),
|
||||
(void **)&factory);
|
||||
else if(createFactory1)
|
||||
hr = createFactory1(__uuidof(IDXGIFactory1), (void **)&factory);
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
HRESULT hr = createFactory2(debugDevice ? DXGI_CREATE_FACTORY_DEBUG : 0,
|
||||
__uuidof(IDXGIFactory4), (void **)&factory);
|
||||
bool warp = false;
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
adapter = ChooseD3DAdapter(factory, argc, argv, warp);
|
||||
|
||||
if(warp && d3d12on7)
|
||||
{
|
||||
bool warp = false;
|
||||
|
||||
adapter = ChooseD3DAdapter(factory, argc, argv, warp);
|
||||
|
||||
if(warp)
|
||||
factory->EnumWarpAdapter(__uuidof(IDXGIAdapter), (void **)&adapter);
|
||||
IDXGIFactory4Ptr factory4 = factory;
|
||||
if(factory4)
|
||||
factory4->EnumWarpAdapter(__uuidof(IDXGIAdapter), (void **)&adapter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,7 +211,7 @@ bool D3D12GraphicsTest::Init()
|
||||
LUID luid = dev->GetAdapterLuid();
|
||||
|
||||
IDXGIAdapterPtr pDXGIAdapter;
|
||||
HRESULT hr = m_Factory->EnumAdapterByLuid(luid, __uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
|
||||
HRESULT hr = EnumAdapterByLuid(dev->GetAdapterLuid(), pDXGIAdapter);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
@@ -207,10 +253,44 @@ bool D3D12GraphicsTest::Init()
|
||||
swapDesc.Stereo = FALSE;
|
||||
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
|
||||
CHECK_HR(m_Factory->CreateSwapChainForHwnd(queue, win->wnd, &swapDesc, NULL, NULL, &swap));
|
||||
if(!d3d12on7)
|
||||
{
|
||||
IDXGIFactory4Ptr factory4 = m_Factory;
|
||||
|
||||
CHECK_HR(swap->GetBuffer(0, __uuidof(ID3D12Resource), (void **)&bbTex[0]));
|
||||
CHECK_HR(swap->GetBuffer(1, __uuidof(ID3D12Resource), (void **)&bbTex[1]));
|
||||
CHECK_HR(factory4->CreateSwapChainForHwnd(queue, win->wnd, &swapDesc, NULL, NULL, &swap));
|
||||
|
||||
CHECK_HR(swap->GetBuffer(0, __uuidof(ID3D12Resource), (void **)&bbTex[0]));
|
||||
CHECK_HR(swap->GetBuffer(1, __uuidof(ID3D12Resource), (void **)&bbTex[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D12_RESOURCE_DESC bbDesc;
|
||||
bbDesc.Alignment = 0;
|
||||
bbDesc.DepthOrArraySize = 1;
|
||||
bbDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
bbDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||
bbDesc.Format = backbufferFmt;
|
||||
bbDesc.Height = screenHeight;
|
||||
bbDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
bbDesc.MipLevels = 1;
|
||||
bbDesc.SampleDesc.Count = 1;
|
||||
bbDesc.SampleDesc.Quality = 0;
|
||||
bbDesc.Width = screenWidth;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProps;
|
||||
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProps.CreationNodeMask = 1;
|
||||
heapProps.VisibleNodeMask = 1;
|
||||
|
||||
CHECK_HR(dev->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &bbDesc,
|
||||
D3D12_RESOURCE_STATE_PRESENT, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&bbTex[0]));
|
||||
CHECK_HR(dev->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &bbDesc,
|
||||
D3D12_RESOURCE_STATE_PRESENT, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&bbTex[1]));
|
||||
}
|
||||
}
|
||||
|
||||
dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void **)&m_GPUSyncFence);
|
||||
@@ -421,7 +501,25 @@ void D3D12GraphicsTest::GPUSync()
|
||||
|
||||
void D3D12GraphicsTest::Present()
|
||||
{
|
||||
swap->Present(0, 0);
|
||||
if(swap)
|
||||
{
|
||||
swap->Present(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ID3D12CommandQueueDownlevelPtr downlevel = queue;
|
||||
|
||||
ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer();
|
||||
Reset(cmd);
|
||||
|
||||
downlevel->Present(cmd, bbTex[1 - texIdx], ((Win32Window *)mainWindow)->wnd,
|
||||
D3D12_DOWNLEVEL_PRESENT_FLAG_NONE);
|
||||
|
||||
m_GPUSyncCounter++;
|
||||
queue->Signal(m_GPUSyncFence, m_GPUSyncCounter);
|
||||
|
||||
pendingCommandBuffers.push_back(std::make_pair(cmd, m_GPUSyncFence));
|
||||
}
|
||||
|
||||
for(auto it = pendingCommandBuffers.begin(); it != pendingCommandBuffers.end();)
|
||||
{
|
||||
|
||||
@@ -181,7 +181,7 @@ struct D3D12GraphicsTest : public GraphicsTest
|
||||
ID3D12ResourcePtr bbTex[2];
|
||||
uint32_t texIdx = 0;
|
||||
|
||||
IDXGIFactory4Ptr m_Factory;
|
||||
IDXGIFactory1Ptr m_Factory;
|
||||
|
||||
ID3D12DebugPtr d3d12Debug;
|
||||
ID3D12InfoQueuePtr infoqueue;
|
||||
|
||||
@@ -37,6 +37,7 @@ extern std::string D3DDefaultPixel;
|
||||
COM_SMARTPTR(IDXGISwapChain);
|
||||
COM_SMARTPTR(IDXGISwapChain1);
|
||||
COM_SMARTPTR(IDXGIFactory);
|
||||
COM_SMARTPTR(IDXGIFactory1);
|
||||
COM_SMARTPTR(IDXGIFactory4);
|
||||
COM_SMARTPTR(IDXGIAdapter);
|
||||
COM_SMARTPTR(IDXGISurface);
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
/*-------------------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation
|
||||
*
|
||||
*-------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
|
||||
|
||||
|
||||
/* verify that the <rpcndr.h> version is high enough to compile this file*/
|
||||
#ifndef __REQUIRED_RPCNDR_H_VERSION__
|
||||
#define __REQUIRED_RPCNDR_H_VERSION__ 500
|
||||
#endif
|
||||
|
||||
/* verify that the <rpcsal.h> version is high enough to compile this file*/
|
||||
#ifndef __REQUIRED_RPCSAL_H_VERSION__
|
||||
#define __REQUIRED_RPCSAL_H_VERSION__ 100
|
||||
#endif
|
||||
|
||||
#include "rpc.h"
|
||||
#include "rpcndr.h"
|
||||
|
||||
#ifndef __RPCNDR_H_VERSION__
|
||||
#error this stub requires an updated version of <rpcndr.h>
|
||||
#endif /* __RPCNDR_H_VERSION__ */
|
||||
|
||||
#ifndef COM_NO_WINDOWS_H
|
||||
#include "windows.h"
|
||||
#include "ole2.h"
|
||||
#endif /*COM_NO_WINDOWS_H*/
|
||||
|
||||
#ifndef __d3d12downlevel_h__
|
||||
#define __d3d12downlevel_h__
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/* Forward Declarations */
|
||||
|
||||
#ifndef __ID3D12CommandQueueDownlevel_FWD_DEFINED__
|
||||
#define __ID3D12CommandQueueDownlevel_FWD_DEFINED__
|
||||
typedef interface ID3D12CommandQueueDownlevel ID3D12CommandQueueDownlevel;
|
||||
|
||||
#endif /* __ID3D12CommandQueueDownlevel_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D12DeviceDownlevel_FWD_DEFINED__
|
||||
#define __ID3D12DeviceDownlevel_FWD_DEFINED__
|
||||
typedef interface ID3D12DeviceDownlevel ID3D12DeviceDownlevel;
|
||||
|
||||
#endif /* __ID3D12DeviceDownlevel_FWD_DEFINED__ */
|
||||
|
||||
|
||||
/* header files for imported files */
|
||||
#include "oaidl.h"
|
||||
#include "ocidl.h"
|
||||
#include "d3d12.h"
|
||||
#include "dxgi1_4.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12downlevel_0000_0000 */
|
||||
/* [local] */
|
||||
|
||||
#include "winapifamily.h"
|
||||
#pragma region Desktop Family
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
typedef
|
||||
enum D3D12_DOWNLEVEL_PRESENT_FLAGS
|
||||
{
|
||||
D3D12_DOWNLEVEL_PRESENT_FLAG_NONE = 0,
|
||||
D3D12_DOWNLEVEL_PRESENT_FLAG_WAIT_FOR_VBLANK = ( D3D12_DOWNLEVEL_PRESENT_FLAG_NONE + 1 )
|
||||
} D3D12_DOWNLEVEL_PRESENT_FLAGS;
|
||||
|
||||
DEFINE_ENUM_FLAG_OPERATORS( D3D12_DOWNLEVEL_PRESENT_FLAGS );
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12downlevel_0000_0000_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12downlevel_0000_0000_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __ID3D12CommandQueueDownlevel_INTERFACE_DEFINED__
|
||||
#define __ID3D12CommandQueueDownlevel_INTERFACE_DEFINED__
|
||||
|
||||
/* interface ID3D12CommandQueueDownlevel */
|
||||
/* [unique][local][object][uuid] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_ID3D12CommandQueueDownlevel;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("38a8c5ef-7ccb-4e81-914f-a6e9d072c494")
|
||||
ID3D12CommandQueueDownlevel : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE Present(
|
||||
_In_ ID3D12GraphicsCommandList *pOpenCommandList,
|
||||
_In_ ID3D12Resource *pSourceTex2D,
|
||||
_In_ HWND hWindow,
|
||||
D3D12_DOWNLEVEL_PRESENT_FLAGS Flags) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct ID3D12CommandQueueDownlevelVtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
ID3D12CommandQueueDownlevel * This,
|
||||
REFIID riid,
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
ID3D12CommandQueueDownlevel * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
ID3D12CommandQueueDownlevel * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *Present )(
|
||||
ID3D12CommandQueueDownlevel * This,
|
||||
_In_ ID3D12GraphicsCommandList *pOpenCommandList,
|
||||
_In_ ID3D12Resource *pSourceTex2D,
|
||||
_In_ HWND hWindow,
|
||||
D3D12_DOWNLEVEL_PRESENT_FLAGS Flags);
|
||||
|
||||
END_INTERFACE
|
||||
} ID3D12CommandQueueDownlevelVtbl;
|
||||
|
||||
interface ID3D12CommandQueueDownlevel
|
||||
{
|
||||
CONST_VTBL struct ID3D12CommandQueueDownlevelVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define ID3D12CommandQueueDownlevel_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define ID3D12CommandQueueDownlevel_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define ID3D12CommandQueueDownlevel_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define ID3D12CommandQueueDownlevel_Present(This,pOpenCommandList,pSourceTex2D,hWindow,Flags) \
|
||||
( (This)->lpVtbl -> Present(This,pOpenCommandList,pSourceTex2D,hWindow,Flags) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __ID3D12CommandQueueDownlevel_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D12DeviceDownlevel_INTERFACE_DEFINED__
|
||||
#define __ID3D12DeviceDownlevel_INTERFACE_DEFINED__
|
||||
|
||||
/* interface ID3D12DeviceDownlevel */
|
||||
/* [unique][local][object][uuid] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_ID3D12DeviceDownlevel;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("74eaee3f-2f4b-476d-82ba-2b85cb49e310")
|
||||
ID3D12DeviceDownlevel : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryVideoMemoryInfo(
|
||||
UINT NodeIndex,
|
||||
DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup,
|
||||
_Out_ DXGI_QUERY_VIDEO_MEMORY_INFO *pVideoMemoryInfo) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct ID3D12DeviceDownlevelVtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
ID3D12DeviceDownlevel * This,
|
||||
REFIID riid,
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
ID3D12DeviceDownlevel * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
ID3D12DeviceDownlevel * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryVideoMemoryInfo )(
|
||||
ID3D12DeviceDownlevel * This,
|
||||
UINT NodeIndex,
|
||||
DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup,
|
||||
_Out_ DXGI_QUERY_VIDEO_MEMORY_INFO *pVideoMemoryInfo);
|
||||
|
||||
END_INTERFACE
|
||||
} ID3D12DeviceDownlevelVtbl;
|
||||
|
||||
interface ID3D12DeviceDownlevel
|
||||
{
|
||||
CONST_VTBL struct ID3D12DeviceDownlevelVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define ID3D12DeviceDownlevel_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define ID3D12DeviceDownlevel_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define ID3D12DeviceDownlevel_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define ID3D12DeviceDownlevel_QueryVideoMemoryInfo(This,NodeIndex,MemorySegmentGroup,pVideoMemoryInfo) \
|
||||
( (This)->lpVtbl -> QueryVideoMemoryInfo(This,NodeIndex,MemorySegmentGroup,pVideoMemoryInfo) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __ID3D12DeviceDownlevel_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12downlevel_0000_0002 */
|
||||
/* [local] */
|
||||
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
|
||||
#pragma endregion
|
||||
DEFINE_GUID(IID_ID3D12CommandQueueDownlevel,0x38a8c5ef,0x7ccb,0x4e81,0x91,0x4f,0xa6,0xe9,0xd0,0x72,0xc4,0x94);
|
||||
DEFINE_GUID(IID_ID3D12DeviceDownlevel,0x74eaee3f,0x2f4b,0x476d,0x82,0xba,0x2b,0x85,0xcb,0x49,0xe3,0x10);
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12downlevel_0000_0002_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12downlevel_0000_0002_v0_0_s_ifspec;
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
/* end of Additional Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user