diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index d6f164c76..a46cdc307 100644 --- a/src/renderer_d3d11.cpp +++ b/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