BsVulkanRenderAPI.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanRenderAPI.h"
  4. #include "Corethread/BsCoreThread.h"
  5. #include "Profiling/BsRenderStats.h"
  6. #include "Renderapi/BsGpuParamDesc.h"
  7. #include "BsVulkanDevice.h"
  8. #include "Managers/BsVulkanTextureManager.h"
  9. #include "Managers/BsVulkanRenderWindowManager.h"
  10. #include "Managers/BsVulkanHardwareBufferManager.h"
  11. #include "Managers/BsVulkanRenderStateManager.h"
  12. #include "Managers/BsGpuProgramManager.h"
  13. #include "Managers/BsVulkanQueryManager.h"
  14. #include "Managers/BsVulkanGLSLProgramFactory.h"
  15. #include "Managers/BsVulkanCommandBufferManager.h"
  16. #include "BsVulkanCommandBuffer.h"
  17. #include "BsVulkanGpuParams.h"
  18. #include "Managers/BsVulkanVertexInputManager.h"
  19. #include "BsVulkanGpuParamBlockBuffer.h"
  20. #if BS_PLATFORM == BS_PLATFORM_WIN32
  21. #include "Win32/BsWin32VideoModeInfo.h"
  22. #else
  23. static_assert(false, "Other platform includes go here.");
  24. #endif
  25. #define USE_VALIDATION_LAYERS 1
  26. namespace bs { namespace ct
  27. {
  28. VkAllocationCallbacks* gVulkanAllocator = nullptr;
  29. PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = nullptr;
  30. PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = nullptr;
  31. PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = nullptr;
  32. PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR = nullptr;
  33. PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr;
  34. PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR = nullptr;
  35. PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = nullptr;
  36. PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = nullptr;
  37. PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = nullptr;
  38. PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR = nullptr;
  39. PFN_vkQueuePresentKHR vkQueuePresentKHR = nullptr;
  40. VkBool32 debugMsgCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
  41. size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void* pUserData)
  42. {
  43. StringStream message;
  44. // Determine prefix
  45. if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
  46. message << "ERROR";
  47. if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT)
  48. message << "WARNING";
  49. if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
  50. message << "PERFORMANCE";
  51. if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)
  52. message << "INFO";
  53. if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT)
  54. message << "DEBUG";
  55. message << ": [" << pLayerPrefix << "] Code " << msgCode << ": " << pMsg << std::endl;
  56. if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
  57. BS_EXCEPT(RenderingAPIException, message.str())
  58. else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT || flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
  59. LOGWRN(message.str())
  60. else
  61. LOGDBG(message.str())
  62. // Don't abort calls that caused a validation message
  63. return VK_FALSE;
  64. }
  65. VulkanRenderAPI::VulkanRenderAPI()
  66. :mInstance(nullptr)
  67. {
  68. #if BS_DEBUG_MODE
  69. mDebugCallback = nullptr;
  70. #endif
  71. }
  72. VulkanRenderAPI::~VulkanRenderAPI()
  73. {
  74. }
  75. const StringID& VulkanRenderAPI::getName() const
  76. {
  77. static StringID strName("VulkanRenderAPI");
  78. return strName;
  79. }
  80. const String& VulkanRenderAPI::getShadingLanguageName() const
  81. {
  82. static String strName("vksl");
  83. return strName;
  84. }
  85. void VulkanRenderAPI::initialize()
  86. {
  87. THROW_IF_NOT_CORE_THREAD;
  88. // Create instance
  89. VkApplicationInfo appInfo;
  90. appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  91. appInfo.pNext = nullptr;
  92. appInfo.pApplicationName = "Banshee3D App";
  93. appInfo.applicationVersion = 1;
  94. appInfo.pEngineName = "Banshee3D";
  95. appInfo.engineVersion = (0 << 24) | (4 << 16) | 0;
  96. appInfo.apiVersion = VK_API_VERSION_1_0;
  97. #if BS_DEBUG_MODE && USE_VALIDATION_LAYERS
  98. const char* layers[] =
  99. {
  100. "VK_LAYER_LUNARG_standard_validation"
  101. };
  102. const char* extensions[] =
  103. {
  104. nullptr, /** Surface extension */
  105. nullptr, /** OS specific surface extension */
  106. VK_EXT_DEBUG_REPORT_EXTENSION_NAME
  107. };
  108. uint32_t numLayers = sizeof(layers) / sizeof(layers[0]);
  109. #else
  110. const char** layers = nullptr;
  111. const char* extensions[] =
  112. {
  113. nullptr, /** Surface extension */
  114. nullptr, /** OS specific surface extension */
  115. };
  116. uint32_t numLayers = 0;
  117. #endif
  118. extensions[0] = VK_KHR_SURFACE_EXTENSION_NAME;
  119. #if BS_PLATFORM == BS_PLATFORM_WIN32
  120. extensions[1] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
  121. #elif BS_PLATFORM == BS_PLATFORM_ANDROID
  122. extensions[1] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
  123. #else
  124. extensions[1] = VK_KHR_XCB_SURFACE_EXTENSION_NAME;
  125. #endif
  126. uint32_t numExtensions = sizeof(extensions) / sizeof(extensions[0]);
  127. VkInstanceCreateInfo instanceInfo;
  128. instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  129. instanceInfo.pNext = nullptr;
  130. instanceInfo.flags = 0;
  131. instanceInfo.pApplicationInfo = &appInfo;
  132. instanceInfo.enabledLayerCount = numLayers;
  133. instanceInfo.ppEnabledLayerNames = layers;
  134. instanceInfo.enabledExtensionCount = numExtensions;
  135. instanceInfo.ppEnabledExtensionNames = extensions;
  136. VkResult result = vkCreateInstance(&instanceInfo, gVulkanAllocator, &mInstance);
  137. assert(result == VK_SUCCESS);
  138. // Set up debugging
  139. #if BS_DEBUG_MODE && USE_VALIDATION_LAYERS
  140. VkDebugReportFlagsEXT debugFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT |
  141. VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
  142. GET_INSTANCE_PROC_ADDR(mInstance, CreateDebugReportCallbackEXT);
  143. GET_INSTANCE_PROC_ADDR(mInstance, DestroyDebugReportCallbackEXT);
  144. VkDebugReportCallbackCreateInfoEXT debugInfo;
  145. debugInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
  146. debugInfo.pNext = nullptr;
  147. debugInfo.flags = 0;
  148. debugInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT)debugMsgCallback;
  149. debugInfo.flags = debugFlags;
  150. result = vkCreateDebugReportCallbackEXT(mInstance, &debugInfo, nullptr, &mDebugCallback);
  151. assert(result == VK_SUCCESS);
  152. #endif
  153. // Enumerate all devices
  154. result = vkEnumeratePhysicalDevices(mInstance, &mNumDevices, nullptr);
  155. assert(result == VK_SUCCESS);
  156. Vector<VkPhysicalDevice> physicalDevices(mNumDevices);
  157. result = vkEnumeratePhysicalDevices(mInstance, &mNumDevices, physicalDevices.data());
  158. assert(result == VK_SUCCESS);
  159. mDevices.resize(mNumDevices);
  160. for(uint32_t i = 0; i < mNumDevices; i++)
  161. mDevices[i] = bs_shared_ptr_new<VulkanDevice>(physicalDevices[i], i);
  162. // Find primary device
  163. // Note: MULTIGPU - Detect multiple similar devices here if supporting multi-GPU
  164. for (uint32_t i = 0; i < mNumDevices; i++)
  165. {
  166. bool isPrimary = mDevices[i]->getDeviceProperties().deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
  167. if (isPrimary)
  168. {
  169. mDevices[i]->setIsPrimary();
  170. mPrimaryDevices.push_back(mDevices[i]);
  171. break;
  172. }
  173. }
  174. if (mPrimaryDevices.size() == 0)
  175. mPrimaryDevices.push_back(mDevices[0]);
  176. #if BS_PLATFORM == BS_PLATFORM_WIN32
  177. mVideoModeInfo = bs_shared_ptr_new<Win32VideoModeInfo>();
  178. #else
  179. static_assert(false, "mVideoModeInfo needs to be created.")
  180. #endif
  181. GPUInfo gpuInfo;
  182. gpuInfo.numGPUs = std::min(5U, mNumDevices);
  183. for(UINT32 i = 0; i < gpuInfo.numGPUs; i++)
  184. gpuInfo.names[i] = mDevices[i]->getDeviceProperties().deviceName;
  185. PlatformUtility::_setGPUInfo(gpuInfo);
  186. // Get required extension functions
  187. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfaceSupportKHR);
  188. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfaceFormatsKHR);
  189. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
  190. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfacePresentModesKHR);
  191. VkDevice presentDevice = _getPresentDevice()->getLogical();
  192. GET_DEVICE_PROC_ADDR(presentDevice, CreateSwapchainKHR);
  193. GET_DEVICE_PROC_ADDR(presentDevice, DestroySwapchainKHR);
  194. GET_DEVICE_PROC_ADDR(presentDevice, GetSwapchainImagesKHR);
  195. GET_DEVICE_PROC_ADDR(presentDevice, AcquireNextImageKHR);
  196. GET_DEVICE_PROC_ADDR(presentDevice, QueuePresentKHR);
  197. // Create command buffer manager
  198. CommandBufferManager::startUp<VulkanCommandBufferManager>(*this);
  199. // Create main command buffer
  200. mMainCommandBuffer = std::static_pointer_cast<VulkanCommandBuffer>(CommandBuffer::create(GQT_GRAPHICS));
  201. // Create the texture manager for use by others
  202. bs::TextureManager::startUp<bs::VulkanTextureManager>();
  203. TextureManager::startUp<VulkanTextureManager>();
  204. // Create hardware buffer manager
  205. bs::HardwareBufferManager::startUp();
  206. HardwareBufferManager::startUp<VulkanHardwareBufferManager>();
  207. // Create render window manager
  208. bs::RenderWindowManager::startUp<bs::VulkanRenderWindowManager>();
  209. RenderWindowManager::startUp<VulkanRenderWindowManager>(*this);
  210. // Create query manager
  211. QueryManager::startUp<VulkanQueryManager>(*this);
  212. // Create vertex input manager
  213. VulkanVertexInputManager::startUp();
  214. // Create & register HLSL factory
  215. mGLSLFactory = bs_new<VulkanGLSLProgramFactory>();
  216. // Create render state manager
  217. RenderStateManager::startUp<VulkanRenderStateManager>();
  218. GpuProgramManager::instance().addFactory(mGLSLFactory);
  219. initCapabilites();
  220. RenderAPI::initialize();
  221. }
  222. void VulkanRenderAPI::destroyCore()
  223. {
  224. THROW_IF_NOT_CORE_THREAD;
  225. if (mGLSLFactory != nullptr)
  226. {
  227. bs_delete(mGLSLFactory);
  228. mGLSLFactory = nullptr;
  229. }
  230. VulkanVertexInputManager::shutDown();
  231. QueryManager::shutDown();
  232. RenderStateManager::shutDown();
  233. RenderWindowManager::shutDown();
  234. bs::RenderWindowManager::shutDown();
  235. HardwareBufferManager::shutDown();
  236. bs::HardwareBufferManager::shutDown();
  237. TextureManager::shutDown();
  238. bs::TextureManager::shutDown();
  239. mMainCommandBuffer = nullptr;
  240. // Make sure everything finishes and all resources get freed
  241. VulkanCommandBufferManager& cmdBufManager = static_cast<VulkanCommandBufferManager&>(CommandBufferManager::instance());
  242. for (UINT32 i = 0; i < (UINT32)mDevices.size(); i++)
  243. {
  244. mDevices[i]->waitIdle();
  245. cmdBufManager.refreshStates(i);
  246. }
  247. CommandBufferManager::shutDown();
  248. mPrimaryDevices.clear();
  249. mDevices.clear();
  250. #if BS_DEBUG_MODE
  251. if (mDebugCallback != nullptr)
  252. vkDestroyDebugReportCallbackEXT(mInstance, mDebugCallback, gVulkanAllocator);
  253. #endif
  254. vkDestroyInstance(mInstance, gVulkanAllocator);
  255. RenderAPI::destroyCore();
  256. }
  257. void VulkanRenderAPI::setGraphicsPipeline(const SPtr<GraphicsPipelineState>& pipelineState,
  258. const SPtr<CommandBuffer>& commandBuffer)
  259. {
  260. VulkanCommandBuffer* cb = getCB(commandBuffer);
  261. VulkanCmdBuffer* vkCB = cb->getInternal();
  262. vkCB->setPipelineState(pipelineState);
  263. BS_INC_RENDER_STAT(NumPipelineStateChanges);
  264. }
  265. void VulkanRenderAPI::setComputePipeline(const SPtr<ComputePipelineState>& pipelineState,
  266. const SPtr<CommandBuffer>& commandBuffer)
  267. {
  268. VulkanCommandBuffer* cb = getCB(commandBuffer);
  269. VulkanCmdBuffer* vkCB = cb->getInternal();
  270. vkCB->setPipelineState(pipelineState);
  271. BS_INC_RENDER_STAT(NumPipelineStateChanges);
  272. }
  273. void VulkanRenderAPI::setGpuParams(const SPtr<GpuParams>& gpuParams, const SPtr<CommandBuffer>& commandBuffer)
  274. {
  275. VulkanCommandBuffer* cb = getCB(commandBuffer);
  276. VulkanCmdBuffer* vkCB = cb->getInternal();
  277. UINT32 globalQueueIdx = CommandSyncMask::getGlobalQueueIdx(cb->getType(), cb->getQueueIdx());
  278. for (UINT32 i = 0; i < GPT_COUNT; i++)
  279. {
  280. SPtr<GpuParamDesc> paramDesc = gpuParams->getParamDesc((GpuProgramType)i);
  281. if (paramDesc == nullptr)
  282. continue;
  283. // Flush all param block buffers
  284. for (auto iter = paramDesc->paramBlocks.begin(); iter != paramDesc->paramBlocks.end(); ++iter)
  285. {
  286. SPtr<GpuParamBlockBuffer> buffer = gpuParams->getParamBlockBuffer(iter->second.set, iter->second.slot);
  287. if (buffer != nullptr)
  288. buffer->flushToGPU(globalQueueIdx);
  289. }
  290. }
  291. vkCB->setGpuParams(gpuParams);
  292. BS_INC_RENDER_STAT(NumGpuParamBinds);
  293. }
  294. void VulkanRenderAPI::setViewport(const Rect2& vp, const SPtr<CommandBuffer>& commandBuffer)
  295. {
  296. VulkanCommandBuffer* cb = getCB(commandBuffer);
  297. VulkanCmdBuffer* vkCB = cb->getInternal();
  298. vkCB->setViewport(vp);
  299. }
  300. void VulkanRenderAPI::setVertexBuffers(UINT32 index, SPtr<VertexBuffer>* buffers, UINT32 numBuffers,
  301. const SPtr<CommandBuffer>& commandBuffer)
  302. {
  303. VulkanCommandBuffer* cb = getCB(commandBuffer);
  304. VulkanCmdBuffer* vkCB = cb->getInternal();
  305. vkCB->setVertexBuffers(index, buffers, numBuffers);
  306. BS_INC_RENDER_STAT(NumVertexBufferBinds);
  307. }
  308. void VulkanRenderAPI::setIndexBuffer(const SPtr<IndexBuffer>& buffer, const SPtr<CommandBuffer>& commandBuffer)
  309. {
  310. VulkanCommandBuffer* cb = getCB(commandBuffer);
  311. VulkanCmdBuffer* vkCB = cb->getInternal();
  312. vkCB->setIndexBuffer(buffer);
  313. BS_INC_RENDER_STAT(NumIndexBufferBinds);
  314. }
  315. void VulkanRenderAPI::setVertexDeclaration(const SPtr<VertexDeclaration>& vertexDeclaration,
  316. const SPtr<CommandBuffer>& commandBuffer)
  317. {
  318. VulkanCommandBuffer* cb = getCB(commandBuffer);
  319. VulkanCmdBuffer* vkCB = cb->getInternal();
  320. vkCB->setVertexDeclaration(vertexDeclaration);
  321. }
  322. void VulkanRenderAPI::setDrawOperation(DrawOperationType op, const SPtr<CommandBuffer>& commandBuffer)
  323. {
  324. VulkanCommandBuffer* cb = getCB(commandBuffer);
  325. VulkanCmdBuffer* vkCB = cb->getInternal();
  326. vkCB->setDrawOp(op);
  327. }
  328. void VulkanRenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount,
  329. const SPtr<CommandBuffer>& commandBuffer)
  330. {
  331. UINT32 primCount = 0;
  332. VulkanCommandBuffer* cb = getCB(commandBuffer);
  333. VulkanCmdBuffer* vkCB = cb->getInternal();
  334. vkCB->draw(vertexOffset, vertexCount, instanceCount);
  335. BS_INC_RENDER_STAT(NumDrawCalls);
  336. BS_ADD_RENDER_STAT(NumVertices, vertexCount);
  337. BS_ADD_RENDER_STAT(NumPrimitives, primCount);
  338. }
  339. void VulkanRenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount,
  340. UINT32 instanceCount, const SPtr<CommandBuffer>& commandBuffer)
  341. {
  342. UINT32 primCount = 0;
  343. VulkanCommandBuffer* cb = getCB(commandBuffer);
  344. VulkanCmdBuffer* vkCB = cb->getInternal();
  345. vkCB->drawIndexed(startIndex, indexCount, vertexOffset, instanceCount);
  346. BS_INC_RENDER_STAT(NumDrawCalls);
  347. BS_ADD_RENDER_STAT(NumVertices, vertexCount);
  348. BS_ADD_RENDER_STAT(NumPrimitives, primCount);
  349. }
  350. void VulkanRenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ,
  351. const SPtr<CommandBuffer>& commandBuffer)
  352. {
  353. VulkanCommandBuffer* cb = getCB(commandBuffer);
  354. VulkanCmdBuffer* vkCB = cb->getInternal();
  355. vkCB->dispatch(numGroupsX, numGroupsY, numGroupsZ);
  356. BS_INC_RENDER_STAT(NumComputeCalls);
  357. }
  358. void VulkanRenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom,
  359. const SPtr<CommandBuffer>& commandBuffer)
  360. {
  361. VulkanCommandBuffer* cb = getCB(commandBuffer);
  362. VulkanCmdBuffer* vkCB = cb->getInternal();
  363. Rect2I area(left, top, right - left, bottom - top);
  364. vkCB->setScissorRect(area);
  365. }
  366. void VulkanRenderAPI::setStencilRef(UINT32 value, const SPtr<CommandBuffer>& commandBuffer)
  367. {
  368. VulkanCommandBuffer* cb = getCB(commandBuffer);
  369. VulkanCmdBuffer* vkCB = cb->getInternal();
  370. vkCB->setStencilRef(value);
  371. }
  372. void VulkanRenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask,
  373. const SPtr<CommandBuffer>& commandBuffer)
  374. {
  375. VulkanCommandBuffer* cb = getCB(commandBuffer);
  376. VulkanCmdBuffer* vkCB = cb->getInternal();
  377. vkCB->clearViewport(buffers, color, depth, stencil, targetMask);
  378. BS_INC_RENDER_STAT(NumClears);
  379. }
  380. void VulkanRenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil,
  381. UINT8 targetMask, const SPtr<CommandBuffer>& commandBuffer)
  382. {
  383. VulkanCommandBuffer* cb = getCB(commandBuffer);
  384. VulkanCmdBuffer* vkCB = cb->getInternal();
  385. vkCB->clearRenderTarget(buffers, color, depth, stencil, targetMask);
  386. BS_INC_RENDER_STAT(NumClears);
  387. }
  388. void VulkanRenderAPI::setRenderTarget(const SPtr<RenderTarget>& target, UINT32 readOnlyFlags,
  389. RenderSurfaceMask loadMask, const SPtr<CommandBuffer>& commandBuffer)
  390. {
  391. VulkanCommandBuffer* cb = getCB(commandBuffer);
  392. VulkanCmdBuffer* vkCB = cb->getInternal();
  393. vkCB->setRenderTarget(target, readOnlyFlags, loadMask);
  394. BS_INC_RENDER_STAT(NumRenderTargetChanges);
  395. }
  396. void VulkanRenderAPI::swapBuffers(const SPtr<RenderTarget>& target, UINT32 syncMask)
  397. {
  398. THROW_IF_NOT_CORE_THREAD;
  399. submitCommandBuffer(mMainCommandBuffer, syncMask);
  400. target->swapBuffers(syncMask);
  401. // See if any command buffers finished executing
  402. VulkanCommandBufferManager& cbm = static_cast<VulkanCommandBufferManager&>(CommandBufferManager::instance());
  403. for (UINT32 i = 0; i < (UINT32)mDevices.size(); i++)
  404. cbm.refreshStates(i);
  405. BS_INC_RENDER_STAT(NumPresents);
  406. }
  407. void VulkanRenderAPI::addCommands(const SPtr<CommandBuffer>& commandBuffer, const SPtr<CommandBuffer>& secondary)
  408. {
  409. BS_EXCEPT(NotImplementedException, "Secondary command buffers not implemented");
  410. }
  411. void VulkanRenderAPI::submitCommandBuffer(const SPtr<CommandBuffer>& commandBuffer, UINT32 syncMask)
  412. {
  413. THROW_IF_NOT_CORE_THREAD;
  414. VulkanCommandBuffer* cmdBuffer = getCB(commandBuffer);
  415. // Submit all transfer buffers first
  416. VulkanCommandBufferManager& cbm = static_cast<VulkanCommandBufferManager&>(CommandBufferManager::instance());
  417. cbm.flushTransferBuffers(cmdBuffer->getDeviceIdx());
  418. cmdBuffer->submit(syncMask);
  419. }
  420. void VulkanRenderAPI::convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest)
  421. {
  422. dest = matrix;
  423. // Flip Y axis
  424. dest[1][1] = -dest[1][1];
  425. // Convert depth range from [-1,1] to [0,1]
  426. dest[2][0] = (dest[2][0] + dest[3][0]) / 2;
  427. dest[2][1] = (dest[2][1] + dest[3][1]) / 2;
  428. dest[2][2] = (dest[2][2] + dest[3][2]) / 2;
  429. dest[2][3] = (dest[2][3] + dest[3][3]) / 2;
  430. }
  431. const RenderAPIInfo& VulkanRenderAPI::getAPIInfo() const
  432. {
  433. static RenderAPIInfo info(0.0f, 0.0f, 0.0f, 1.0f, VET_COLOR_ABGR,
  434. RenderAPIFeatureFlag::NDCYAxisDown |
  435. RenderAPIFeatureFlag::ColumnMajorMatrices |
  436. RenderAPIFeatureFlag::MultiThreadedCB |
  437. RenderAPIFeatureFlag::MSAAImageStores);
  438. return info;
  439. }
  440. GpuParamBlockDesc VulkanRenderAPI::generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params)
  441. {
  442. GpuParamBlockDesc block;
  443. block.blockSize = 0;
  444. block.isShareable = true;
  445. block.name = name;
  446. block.slot = 0;
  447. block.set = 0;
  448. for (auto& param : params)
  449. {
  450. const GpuParamDataTypeInfo& typeInfo = bs::GpuParams::PARAM_SIZES.lookup[param.type];
  451. UINT32 size = typeInfo.size / 4;
  452. UINT32 alignment = typeInfo.alignment / 4;
  453. // Fix alignment if needed
  454. UINT32 alignOffset = block.blockSize % alignment;
  455. if (alignOffset != 0)
  456. {
  457. UINT32 padding = (alignment - alignOffset);
  458. block.blockSize += padding;
  459. }
  460. if (param.arraySize > 1)
  461. {
  462. // Array elements are always padded and aligned to vec4
  463. alignOffset = size % typeInfo.baseTypeSize;
  464. if (alignOffset != 0)
  465. {
  466. UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
  467. size += padding;
  468. }
  469. alignOffset = block.blockSize % typeInfo.baseTypeSize;
  470. if (alignOffset != 0)
  471. {
  472. UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
  473. block.blockSize += padding;
  474. }
  475. param.elementSize = size;
  476. param.arrayElementStride = size;
  477. param.cpuMemOffset = block.blockSize;
  478. param.gpuMemOffset = 0;
  479. block.blockSize += size * param.arraySize;
  480. }
  481. else
  482. {
  483. param.elementSize = size;
  484. param.arrayElementStride = size;
  485. param.cpuMemOffset = block.blockSize;
  486. param.gpuMemOffset = 0;
  487. block.blockSize += size;
  488. }
  489. param.paramBlockSlot = 0;
  490. param.paramBlockSet = 0;
  491. }
  492. // Constant buffer size must always be a multiple of 16
  493. if (block.blockSize % 4 != 0)
  494. block.blockSize += (4 - (block.blockSize % 4));
  495. return block;
  496. }
  497. void VulkanRenderAPI::initCapabilites()
  498. {
  499. mNumDevices = (UINT32)mDevices.size();
  500. mCurrentCapabilities = bs_newN<RenderAPICapabilities>(mNumDevices);
  501. UINT32 deviceIdx = 0;
  502. for (auto& device : mDevices)
  503. {
  504. RenderAPICapabilities& caps = mCurrentCapabilities[deviceIdx];
  505. const VkPhysicalDeviceProperties& deviceProps = device->getDeviceProperties();
  506. const VkPhysicalDeviceFeatures& deviceFeatures = device->getDeviceFeatures();
  507. const VkPhysicalDeviceLimits& deviceLimits = deviceProps.limits;
  508. DriverVersion driverVersion;
  509. driverVersion.major = ((uint32_t)(deviceProps.apiVersion) >> 22);
  510. driverVersion.minor = ((uint32_t)(deviceProps.apiVersion) >> 12) & 0x3ff;
  511. driverVersion.release = (uint32_t)(deviceProps.apiVersion) & 0xfff;
  512. driverVersion.build = 0;
  513. caps.setDriverVersion(driverVersion);
  514. caps.setDeviceName(deviceProps.deviceName);
  515. // Determine vendor
  516. switch (deviceProps.vendorID)
  517. {
  518. case 0x10DE:
  519. caps.setVendor(GPU_NVIDIA);
  520. break;
  521. case 0x1002:
  522. caps.setVendor(GPU_AMD);
  523. break;
  524. case 0x163C:
  525. case 0x8086:
  526. caps.setVendor(GPU_INTEL);
  527. break;
  528. default:
  529. caps.setVendor(GPU_UNKNOWN);
  530. break;
  531. };
  532. caps.setRenderAPIName(getName());
  533. if(deviceFeatures.textureCompressionBC)
  534. caps.setCapability(RSC_TEXTURE_COMPRESSION_BC);
  535. if (deviceFeatures.textureCompressionETC2)
  536. caps.setCapability(RSC_TEXTURE_COMPRESSION_ETC2);
  537. if (deviceFeatures.textureCompressionASTC_LDR)
  538. caps.setCapability(RSC_TEXTURE_COMPRESSION_ASTC);
  539. caps.setMaxBoundVertexBuffers(deviceLimits.maxVertexInputBindings);
  540. caps.setNumMultiRenderTargets(deviceLimits.maxColorAttachments);
  541. caps.setCapability(RSC_COMPUTE_PROGRAM);
  542. caps.setNumTextureUnits(GPT_FRAGMENT_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  543. caps.setNumTextureUnits(GPT_VERTEX_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  544. caps.setNumTextureUnits(GPT_COMPUTE_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  545. caps.setNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  546. caps.setNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  547. caps.setNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  548. caps.setNumLoadStoreTextureUnits(GPT_FRAGMENT_PROGRAM, deviceLimits.maxPerStageDescriptorStorageImages);
  549. caps.setNumLoadStoreTextureUnits(GPT_COMPUTE_PROGRAM, deviceLimits.maxPerStageDescriptorStorageImages);
  550. if(deviceFeatures.geometryShader)
  551. {
  552. caps.setCapability(RSC_GEOMETRY_PROGRAM);
  553. caps.addShaderProfile("gs_5_0");
  554. caps.setNumTextureUnits(GPT_GEOMETRY_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  555. caps.setNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  556. caps.setGeometryProgramNumOutputVertices(deviceLimits.maxGeometryOutputVertices);
  557. }
  558. if (deviceFeatures.tessellationShader)
  559. {
  560. caps.setCapability(RSC_TESSELLATION_PROGRAM);
  561. caps.setNumTextureUnits(GPT_HULL_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  562. caps.setNumTextureUnits(GPT_DOMAIN_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  563. caps.setNumGpuParamBlockBuffers(GPT_HULL_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  564. caps.setNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  565. }
  566. caps.setNumCombinedTextureUnits(caps.getNumTextureUnits(GPT_FRAGMENT_PROGRAM)
  567. + caps.getNumTextureUnits(GPT_VERTEX_PROGRAM) + caps.getNumTextureUnits(GPT_GEOMETRY_PROGRAM)
  568. + caps.getNumTextureUnits(GPT_HULL_PROGRAM) + caps.getNumTextureUnits(GPT_DOMAIN_PROGRAM)
  569. + caps.getNumTextureUnits(GPT_COMPUTE_PROGRAM));
  570. caps.setNumCombinedGpuParamBlockBuffers(caps.getNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM)
  571. + caps.getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM) + caps.getNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM)
  572. + caps.getNumGpuParamBlockBuffers(GPT_HULL_PROGRAM) + caps.getNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM)
  573. + caps.getNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM));
  574. caps.setNumCombinedLoadStoreTextureUnits(caps.getNumLoadStoreTextureUnits(GPT_FRAGMENT_PROGRAM)
  575. + caps.getNumLoadStoreTextureUnits(GPT_COMPUTE_PROGRAM));
  576. caps.addShaderProfile("glsl");
  577. deviceIdx++;
  578. }
  579. }
  580. VulkanCommandBuffer* VulkanRenderAPI::getCB(const SPtr<CommandBuffer>& buffer)
  581. {
  582. if (buffer != nullptr)
  583. return static_cast<VulkanCommandBuffer*>(buffer.get());
  584. return static_cast<VulkanCommandBuffer*>(mMainCommandBuffer.get());
  585. }
  586. VulkanRenderAPI& gVulkanRenderAPI()
  587. {
  588. return static_cast<VulkanRenderAPI&>(RenderAPI::instance());
  589. }
  590. }}