Przeglądaj źródła

D3D11: Added multidraw indexed via AMD's AGS.

Branimir Karadžić 10 lat temu
rodzic
commit
52c89c8cc8
1 zmienionych plików z 220 dodań i 12 usunięć
  1. 220 12
      src/renderer_d3d11.cpp

+ 220 - 12
src/renderer_d3d11.cpp

@@ -441,6 +441,67 @@ namespace bgfx { namespace d3d11
 		return false;
 	};
 
+	enum AGS_RETURN_CODE
+	{
+		AGS_SUCCESS,
+		AGS_INVALID_ARGS,
+		AGS_OUT_OF_MEMORY,
+		AGS_ERROR_MISSING_DLL,
+		AGS_ERROR_LEGACY_DRIVER,
+		AGS_EXTENSION_NOT_SUPPORTED,
+		AGS_ADL_FAILURE,
+	};
+
+	enum AGS_DRIVER_EXTENSION
+	{
+		AGS_EXTENSION_QUADLIST          = 1 << 0,
+		AGS_EXTENSION_UAV_OVERLAP       = 1 << 1,
+		AGS_EXTENSION_DEPTH_BOUNDS_TEST = 1 << 2,
+		AGS_EXTENSION_MULTIDRAWINDIRECT = 1 << 3,
+	};
+
+	struct AGSDriverVersionInfo
+	{
+		char strDriverVersion[256];
+		char strCatalystVersion[256];
+		char strCatalystWebLink[256];
+	};
+
+	struct AGSContext;
+
+	typedef AGS_RETURN_CODE (__cdecl* PFN_AGS_INIT)(AGSContext**);
+	typedef AGS_RETURN_CODE (__cdecl* PFN_AGS_DEINIT)(AGSContext*);
+	typedef AGS_RETURN_CODE (__cdecl* PFN_AGS_GET_CROSSFIRE_GPU_COUNT)(AGSContext*, int32_t*);
+	typedef AGS_RETURN_CODE (__cdecl* PFN_AGS_GET_TOTAL_GPU_COUNT)(AGSContext*, int32_t*);
+	typedef AGS_RETURN_CODE (__cdecl* PFN_AGS_GET_GPU_MEMORY_SIZE)(AGSContext*, int32_t, int64_t*);
+	typedef AGS_RETURN_CODE (__cdecl* PFN_AGS_GET_DRIVER_VERSION_INFO)(AGSContext*, AGSDriverVersionInfo*);
+	typedef AGS_RETURN_CODE (__cdecl* PFN_AGS_DRIVER_EXTENSIONS_INIT)(AGSContext*, ID3D11Device*, uint32_t*);
+	typedef AGS_RETURN_CODE (__cdecl* PFN_AGS_DRIVER_EXTENSIONS_DEINIT)(AGSContext*);
+	typedef AGS_RETURN_CODE (__cdecl* PFN_AGS_DRIVER_EXTENSIONS_MULTIDRAW_INSTANCED_INDIRECT)(AGSContext*, uint32_t, ID3D11Buffer*, uint32_t, uint32_t);
+	typedef AGS_RETURN_CODE (__cdecl* PFN_AGS_DRIVER_EXTENSIONS_MULTIDRAW_INDEXED_INSTANCED_INDIRECT)(AGSContext*, uint32_t, ID3D11Buffer*, uint32_t, uint32_t);
+
+	static PFN_AGS_INIT   agsInit;
+	static PFN_AGS_DEINIT agsDeInit;
+	static PFN_AGS_GET_CROSSFIRE_GPU_COUNT  agsGetCrossfireGPUCount;
+	static PFN_AGS_GET_TOTAL_GPU_COUNT      agsGetTotalGPUCount;
+	static PFN_AGS_GET_GPU_MEMORY_SIZE      agsGetGPUMemorySize;
+	static PFN_AGS_GET_DRIVER_VERSION_INFO  agsGetDriverVersionInfo;
+	static PFN_AGS_DRIVER_EXTENSIONS_INIT   agsDriverExtensions_Init;
+	static PFN_AGS_DRIVER_EXTENSIONS_DEINIT agsDriverExtensions_DeInit;
+	static PFN_AGS_DRIVER_EXTENSIONS_MULTIDRAW_INSTANCED_INDIRECT         agsDriverExtensions_MultiDrawInstancedIndirect;
+	static PFN_AGS_DRIVER_EXTENSIONS_MULTIDRAW_INDEXED_INSTANCED_INDIRECT agsDriverExtensions_MultiDrawIndexedInstancedIndirect;
+
+	typedef void (* MultiDrawIndirectFn)(uint32_t _numDrawIndirect, ID3D11Buffer* _ptr, uint32_t _offset, uint32_t _stride);
+
+	void stubMultiDrawInstancedIndirect(uint32_t _numDrawIndirect, ID3D11Buffer* _ptr, uint32_t _offset, uint32_t _stride);
+	void stubMultiDrawIndexedInstancedIndirect(uint32_t _numDrawIndirect, ID3D11Buffer* _ptr, uint32_t _offset, uint32_t _stride);
+
+	void amdAgsMultiDrawInstancedIndirect(uint32_t _numDrawIndirect, ID3D11Buffer* _ptr, uint32_t _offset, uint32_t _stride);
+	void amdAgsMultiDrawIndexedInstancedIndirect(uint32_t _numDrawIndirect, ID3D11Buffer* _ptr, uint32_t _offset, uint32_t _stride);
+
+	static MultiDrawIndirectFn multiDrawInstancedIndirect;
+	static MultiDrawIndirectFn multiDrawIndexedInstancedIndirect;
+
 #if USE_D3D11_DYNAMIC_LIB
 	static PFN_D3D11_CREATE_DEVICE  D3D11CreateDevice;
 	static PFN_CREATE_DXGI_FACTORY  CreateDXGIFactory;
@@ -459,6 +520,8 @@ namespace bgfx { namespace d3d11
 			, m_dxgidll(NULL)
 			, m_dxgidebugdll(NULL)
 			, m_renderdocdll(NULL)
+			, m_agsdll(NULL)
+			, m_ags(NULL)
 			, m_driverType(D3D_DRIVER_TYPE_NULL)
 			, m_featureLevel(D3D_FEATURE_LEVEL(0) )
 			, m_adapter(NULL)
@@ -522,6 +585,88 @@ namespace bgfx { namespace d3d11
 			memset(m_uniforms, 0, sizeof(m_uniforms) );
 			memset(&m_resolution, 0, sizeof(m_resolution) );
 
+			m_ags = NULL;
+			m_agsdll = bx::dlopen(
+#if BX_ARCH_32BIT
+						"amd_ags_x86.dll"
+#else
+						"amd_ags_x64.dll"
+#endif // BX_ARCH_32BIT
+						);
+			if (NULL != m_agsdll)
+			{
+				agsInit   = (PFN_AGS_INIT  )bx::dlsym(m_agsdll, "agsInit");
+				agsDeInit = (PFN_AGS_DEINIT)bx::dlsym(m_agsdll, "agsDeInit");
+				agsGetCrossfireGPUCount    = (PFN_AGS_GET_CROSSFIRE_GPU_COUNT )bx::dlsym(m_agsdll, "agsGetCrossfireGPUCount");
+				agsGetTotalGPUCount        = (PFN_AGS_GET_TOTAL_GPU_COUNT     )bx::dlsym(m_agsdll, "agsGetTotalGPUCount");
+				agsGetGPUMemorySize        = (PFN_AGS_GET_GPU_MEMORY_SIZE     )bx::dlsym(m_agsdll, "agsGetGPUMemorySize");
+				agsGetDriverVersionInfo    = (PFN_AGS_GET_DRIVER_VERSION_INFO )bx::dlsym(m_agsdll, "agsGetDriverVersionInfo");
+				agsDriverExtensions_Init   = (PFN_AGS_DRIVER_EXTENSIONS_INIT  )bx::dlsym(m_agsdll, "agsDriverExtensions_Init");
+				agsDriverExtensions_DeInit = (PFN_AGS_DRIVER_EXTENSIONS_DEINIT)bx::dlsym(m_agsdll, "agsDriverExtensions_DeInit");
+				agsDriverExtensions_MultiDrawInstancedIndirect        = (PFN_AGS_DRIVER_EXTENSIONS_MULTIDRAW_INSTANCED_INDIRECT        )bx::dlsym(m_agsdll, "agsDriverExtensions_MultiDrawInstancedIndirect");
+				agsDriverExtensions_MultiDrawIndexedInstancedIndirect = (PFN_AGS_DRIVER_EXTENSIONS_MULTIDRAW_INDEXED_INSTANCED_INDIRECT)bx::dlsym(m_agsdll, "agsDriverExtensions_MultiDrawIndexedInstancedIndirect");
+
+				bool agsSupported = true
+					&& NULL != agsInit
+					&& NULL != agsDeInit
+					&& NULL != agsGetCrossfireGPUCount
+					&& NULL != agsGetTotalGPUCount
+					&& NULL != agsGetGPUMemorySize
+					&& NULL != agsGetDriverVersionInfo
+					&& NULL != agsDriverExtensions_Init
+					&& NULL != agsDriverExtensions_DeInit
+					&& NULL != agsDriverExtensions_MultiDrawInstancedIndirect
+					&& NULL != agsDriverExtensions_MultiDrawIndexedInstancedIndirect
+					;
+				if (agsSupported)
+				{
+					AGS_RETURN_CODE result = agsInit(&m_ags);
+					agsSupported = AGS_SUCCESS == result;
+					if (agsSupported)
+					{
+						AGS_RETURN_CODE result;
+
+						AGSDriverVersionInfo vi;
+						result = agsGetDriverVersionInfo(m_ags, &vi);
+						BX_TRACE("      Driver version: %s", vi.strDriverVersion);
+						BX_TRACE("    Catalyst version: %s", vi.strCatalystVersion);
+
+						int32_t numCrossfireGPUs = 0;
+						result = agsGetCrossfireGPUCount(m_ags, &numCrossfireGPUs);
+						BX_TRACE("  Num crossfire GPUs: %d", numCrossfireGPUs);
+
+						int32_t numGPUs = 0;
+						result = agsGetTotalGPUCount(m_ags, &numGPUs);
+						BX_TRACE("            Num GPUs: %d", numGPUs);
+
+						for (int32_t ii = 0; ii < numGPUs; ++ii)
+						{
+							long long memSize;
+							result = agsGetGPUMemorySize(m_ags, ii, &memSize);
+							char memSizeStr[16];
+							bx::prettify(memSizeStr, BX_COUNTOF(memSizeStr), memSize);
+							BX_TRACE("     GPU #%d mem size: %s", ii, memSizeStr);
+						}
+					}
+				}
+
+				if (!agsSupported)
+				{
+					if (NULL != m_ags)
+					{
+						agsDeInit(m_ags);
+						m_ags = NULL;
+					}
+
+					bx::dlclose(m_agsdll);
+					m_agsdll = NULL;
+				}
+				else
+				{
+					BX_TRACE("AMD/AGS supported.");
+				}
+			}
+
 #if USE_D3D11_DYNAMIC_LIB
 			m_d3d11dll = bx::dlopen("d3d11.dll");
 			BX_WARN(NULL != m_d3d11dll, "Failed to load d3d11.dll.");
@@ -760,6 +905,32 @@ namespace bgfx { namespace d3d11
 				}
 			}
 
+			multiDrawInstancedIndirect        = stubMultiDrawInstancedIndirect;
+			multiDrawIndexedInstancedIndirect = stubMultiDrawIndexedInstancedIndirect;
+			if (NULL != m_ags)
+			{
+				uint32_t flags;
+				AGS_RETURN_CODE result = agsDriverExtensions_Init(m_ags, m_device, &flags);
+				bool hasExtensions = AGS_SUCCESS == result;
+
+				if (hasExtensions
+				&&  0 != (flags & AGS_EXTENSION_MULTIDRAWINDIRECT) )
+				{
+					multiDrawInstancedIndirect        = amdAgsMultiDrawInstancedIndirect;
+					multiDrawIndexedInstancedIndirect = amdAgsMultiDrawIndexedInstancedIndirect;
+				}
+				else
+				{
+					if (hasExtensions)
+					{
+						agsDriverExtensions_DeInit(m_ags);
+					}
+
+					agsDeInit(m_ags);
+					m_ags = NULL;
+				}
+			}
+
 			{
 				IDXGIDevice*  device = NULL;
 				IDXGIAdapter* adapter = NULL;
@@ -1212,6 +1383,12 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 #endif // USE_D3D11_DYNAMIC_LIB
 
 			case ErrorState::Default:
+				if (NULL != m_ags)
+				{
+					agsDeInit(m_ags);
+				}
+				bx::dlclose(m_agsdll);
+				m_agsdll = NULL;
 				unloadRenderDoc(m_renderdocdll);
 				m_ovr.shutdown();
 				break;
@@ -2875,6 +3052,9 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 		void* m_dxgidebugdll;
 
 		void* m_renderdocdll;
+		void* m_agsdll;
+		AGSContext* m_ags;
+
 
 		D3D_DRIVER_TYPE   m_driverType;
 		D3D_FEATURE_LEVEL m_featureLevel;
@@ -2977,6 +3157,36 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 		s_renderD3D11 = NULL;
 	}
 
+	void stubMultiDrawInstancedIndirect(uint32_t _numDrawIndirect, ID3D11Buffer* _ptr, uint32_t _offset, uint32_t _stride)
+	{
+		ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
+		for (uint32_t ii = 0; ii < _numDrawIndirect; ++ii)
+		{
+			deviceCtx->DrawInstancedIndirect(_ptr, _offset);
+			_offset += _stride;
+		}
+	}
+
+	void stubMultiDrawIndexedInstancedIndirect(uint32_t _numDrawIndirect, ID3D11Buffer* _ptr, uint32_t _offset, uint32_t _stride)
+	{
+		ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
+		for (uint32_t ii = 0; ii < _numDrawIndirect; ++ii)
+		{
+			deviceCtx->DrawIndexedInstancedIndirect(_ptr, _offset);
+			_offset += _stride;
+		}
+	}
+
+	void amdAgsMultiDrawInstancedIndirect(uint32_t _numDrawIndirect, ID3D11Buffer* _ptr, uint32_t _offset, uint32_t _stride)
+	{
+		agsDriverExtensions_MultiDrawInstancedIndirect(s_renderD3D11->m_ags, _numDrawIndirect, _ptr, _offset, _stride);
+	}
+
+	void amdAgsMultiDrawIndexedInstancedIndirect(uint32_t _numDrawIndirect, ID3D11Buffer* _ptr, uint32_t _offset, uint32_t _stride)
+	{
+		agsDriverExtensions_MultiDrawIndexedInstancedIndirect(s_renderD3D11->m_ags, _numDrawIndirect, _ptr, _offset, _stride);
+	}
+
 	struct UavFormat
 	{
 		DXGI_FORMAT format[3];
@@ -4567,12 +4777,11 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 								: draw.m_numIndirect
 								;
 
-							uint32_t args = draw.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE;
-							for (uint32_t ii = 0; ii < numDrawIndirect; ++ii)
-							{
-								deviceCtx->DrawIndexedInstancedIndirect(ptr, args);
-								args += BGFX_CONFIG_DRAW_INDIRECT_STRIDE;
-							}
+							multiDrawIndexedInstancedIndirect(numDrawIndirect
+								, ptr
+								, draw.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE
+								, BGFX_CONFIG_DRAW_INDIRECT_STRIDE
+								);
 						}
 						else
 						{
@@ -4581,12 +4790,11 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 								: draw.m_numIndirect
 								;
 
-							uint32_t args = draw.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE;
-							for (uint32_t ii = 0; ii < numDrawIndirect; ++ii)
-							{
-								deviceCtx->DrawInstancedIndirect(ptr, args);
-								args += BGFX_CONFIG_DRAW_INDIRECT_STRIDE;
-							}
+							multiDrawInstancedIndirect(numDrawIndirect
+								, ptr
+								, draw.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE
+								, BGFX_CONFIG_DRAW_INDIRECT_STRIDE
+								);
 						}
 					}
 					else