BsVulkanRenderAPI.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanRenderAPI.h"
  4. #include "BsCoreThread.h"
  5. #include "BsRenderStats.h"
  6. #include "BsGpuParamDesc.h"
  7. #include "BsVulkanDevice.h"
  8. #include "BsVulkanTextureManager.h"
  9. #include "BsVulkanRenderWindowManager.h"
  10. #include "BsVulkanHardwareBufferManager.h"
  11. #include "BsVulkanRenderStateManager.h"
  12. #include "BsGpuProgramManager.h"
  13. #include "BsVulkanQueryManager.h"
  14. #include "BsVulkanGLSLProgramFactory.h"
  15. #include "BsVulkanCommandBufferManager.h"
  16. #include "BsVulkanCommandBuffer.h"
  17. #include "BsVulkanGpuParams.h"
  18. #include "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("glsl");
  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. // Get required extension functions
  182. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfaceSupportKHR);
  183. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfaceFormatsKHR);
  184. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
  185. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfacePresentModesKHR);
  186. VkDevice presentDevice = _getPresentDevice()->getLogical();
  187. GET_DEVICE_PROC_ADDR(presentDevice, CreateSwapchainKHR);
  188. GET_DEVICE_PROC_ADDR(presentDevice, DestroySwapchainKHR);
  189. GET_DEVICE_PROC_ADDR(presentDevice, GetSwapchainImagesKHR);
  190. GET_DEVICE_PROC_ADDR(presentDevice, AcquireNextImageKHR);
  191. GET_DEVICE_PROC_ADDR(presentDevice, QueuePresentKHR);
  192. // Create command buffer manager
  193. CommandBufferManager::startUp<VulkanCommandBufferManager>(*this);
  194. // Create main command buffer
  195. mMainCommandBuffer = std::static_pointer_cast<VulkanCommandBuffer>(CommandBuffer::create(GQT_GRAPHICS));
  196. // Create the texture manager for use by others
  197. bs::TextureManager::startUp<bs::VulkanTextureManager>();
  198. TextureManager::startUp<VulkanTextureManager>();
  199. // Create hardware buffer manager
  200. bs::HardwareBufferManager::startUp();
  201. HardwareBufferManager::startUp<VulkanHardwareBufferManager>();
  202. // Create render window manager
  203. bs::RenderWindowManager::startUp<bs::VulkanRenderWindowManager>();
  204. RenderWindowManager::startUp<VulkanRenderWindowManager>(*this);
  205. // Create query manager
  206. QueryManager::startUp<VulkanQueryManager>(*this);
  207. // Create vertex input manager
  208. VulkanVertexInputManager::startUp();
  209. // Create & register HLSL factory
  210. mGLSLFactory = bs_new<VulkanGLSLProgramFactory>();
  211. // Create render state manager
  212. RenderStateManager::startUp<VulkanRenderStateManager>();
  213. GpuProgramManager::instance().addFactory(mGLSLFactory);
  214. initCapabilites();
  215. RenderAPI::initialize();
  216. }
  217. void VulkanRenderAPI::destroyCore()
  218. {
  219. THROW_IF_NOT_CORE_THREAD;
  220. if (mGLSLFactory != nullptr)
  221. {
  222. bs_delete(mGLSLFactory);
  223. mGLSLFactory = nullptr;
  224. }
  225. VulkanVertexInputManager::shutDown();
  226. QueryManager::shutDown();
  227. RenderStateManager::shutDown();
  228. RenderWindowManager::shutDown();
  229. bs::RenderWindowManager::shutDown();
  230. HardwareBufferManager::shutDown();
  231. bs::HardwareBufferManager::shutDown();
  232. TextureManager::shutDown();
  233. bs::TextureManager::shutDown();
  234. mMainCommandBuffer = nullptr;
  235. // Make sure everything finishes and all resources get freed
  236. VulkanCommandBufferManager& cmdBufManager = static_cast<VulkanCommandBufferManager&>(CommandBufferManager::instance());
  237. for (UINT32 i = 0; i < (UINT32)mDevices.size(); i++)
  238. {
  239. mDevices[i]->waitIdle();
  240. cmdBufManager.refreshStates(i);
  241. }
  242. CommandBufferManager::shutDown();
  243. mPrimaryDevices.clear();
  244. mDevices.clear();
  245. #if BS_DEBUG_MODE
  246. if (mDebugCallback != nullptr)
  247. vkDestroyDebugReportCallbackEXT(mInstance, mDebugCallback, gVulkanAllocator);
  248. #endif
  249. vkDestroyInstance(mInstance, gVulkanAllocator);
  250. RenderAPI::destroyCore();
  251. }
  252. void VulkanRenderAPI::setGraphicsPipeline(const SPtr<GraphicsPipelineState>& pipelineState,
  253. const SPtr<CommandBuffer>& commandBuffer)
  254. {
  255. VulkanCommandBuffer* cb = getCB(commandBuffer);
  256. VulkanCmdBuffer* vkCB = cb->getInternal();
  257. vkCB->setPipelineState(pipelineState);
  258. BS_INC_RENDER_STAT(NumPipelineStateChanges);
  259. }
  260. void VulkanRenderAPI::setComputePipeline(const SPtr<ComputePipelineState>& pipelineState,
  261. const SPtr<CommandBuffer>& commandBuffer)
  262. {
  263. VulkanCommandBuffer* cb = getCB(commandBuffer);
  264. VulkanCmdBuffer* vkCB = cb->getInternal();
  265. vkCB->setPipelineState(pipelineState);
  266. BS_INC_RENDER_STAT(NumPipelineStateChanges);
  267. }
  268. void VulkanRenderAPI::setGpuParams(const SPtr<GpuParams>& gpuParams, const SPtr<CommandBuffer>& commandBuffer)
  269. {
  270. VulkanCommandBuffer* cb = getCB(commandBuffer);
  271. VulkanCmdBuffer* vkCB = cb->getInternal();
  272. UINT32 globalQueueIdx = CommandSyncMask::getGlobalQueueIdx(cb->getType(), cb->getQueueIdx());
  273. for (UINT32 i = 0; i < GPT_COUNT; i++)
  274. {
  275. SPtr<GpuParamDesc> paramDesc = gpuParams->getParamDesc((GpuProgramType)i);
  276. if (paramDesc == nullptr)
  277. continue;
  278. // Flush all param block buffers
  279. for (auto iter = paramDesc->paramBlocks.begin(); iter != paramDesc->paramBlocks.end(); ++iter)
  280. {
  281. SPtr<GpuParamBlockBuffer> buffer = gpuParams->getParamBlockBuffer(iter->second.set, iter->second.slot);
  282. if (buffer != nullptr)
  283. buffer->flushToGPU(globalQueueIdx);
  284. }
  285. }
  286. vkCB->setGpuParams(gpuParams);
  287. BS_INC_RENDER_STAT(NumGpuParamBinds);
  288. }
  289. void VulkanRenderAPI::setViewport(const Rect2& vp, const SPtr<CommandBuffer>& commandBuffer)
  290. {
  291. VulkanCommandBuffer* cb = getCB(commandBuffer);
  292. VulkanCmdBuffer* vkCB = cb->getInternal();
  293. vkCB->setViewport(vp);
  294. }
  295. void VulkanRenderAPI::setVertexBuffers(UINT32 index, SPtr<VertexBuffer>* buffers, UINT32 numBuffers,
  296. const SPtr<CommandBuffer>& commandBuffer)
  297. {
  298. VulkanCommandBuffer* cb = getCB(commandBuffer);
  299. VulkanCmdBuffer* vkCB = cb->getInternal();
  300. vkCB->setVertexBuffers(index, buffers, numBuffers);
  301. BS_INC_RENDER_STAT(NumVertexBufferBinds);
  302. }
  303. void VulkanRenderAPI::setIndexBuffer(const SPtr<IndexBuffer>& buffer, const SPtr<CommandBuffer>& commandBuffer)
  304. {
  305. VulkanCommandBuffer* cb = getCB(commandBuffer);
  306. VulkanCmdBuffer* vkCB = cb->getInternal();
  307. vkCB->setIndexBuffer(buffer);
  308. BS_INC_RENDER_STAT(NumIndexBufferBinds);
  309. }
  310. void VulkanRenderAPI::setVertexDeclaration(const SPtr<VertexDeclaration>& vertexDeclaration,
  311. const SPtr<CommandBuffer>& commandBuffer)
  312. {
  313. VulkanCommandBuffer* cb = getCB(commandBuffer);
  314. VulkanCmdBuffer* vkCB = cb->getInternal();
  315. vkCB->setVertexDeclaration(vertexDeclaration);
  316. }
  317. void VulkanRenderAPI::setDrawOperation(DrawOperationType op, const SPtr<CommandBuffer>& commandBuffer)
  318. {
  319. VulkanCommandBuffer* cb = getCB(commandBuffer);
  320. VulkanCmdBuffer* vkCB = cb->getInternal();
  321. vkCB->setDrawOp(op);
  322. }
  323. void VulkanRenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount,
  324. const SPtr<CommandBuffer>& commandBuffer)
  325. {
  326. UINT32 primCount = 0;
  327. VulkanCommandBuffer* cb = getCB(commandBuffer);
  328. VulkanCmdBuffer* vkCB = cb->getInternal();
  329. vkCB->draw(vertexOffset, vertexCount, instanceCount);
  330. BS_INC_RENDER_STAT(NumDrawCalls);
  331. BS_ADD_RENDER_STAT(NumVertices, vertexCount);
  332. BS_ADD_RENDER_STAT(NumPrimitives, primCount);
  333. }
  334. void VulkanRenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount,
  335. UINT32 instanceCount, const SPtr<CommandBuffer>& commandBuffer)
  336. {
  337. UINT32 primCount = 0;
  338. VulkanCommandBuffer* cb = getCB(commandBuffer);
  339. VulkanCmdBuffer* vkCB = cb->getInternal();
  340. vkCB->drawIndexed(startIndex, indexCount, vertexOffset, instanceCount);
  341. BS_INC_RENDER_STAT(NumDrawCalls);
  342. BS_ADD_RENDER_STAT(NumVertices, vertexCount);
  343. BS_ADD_RENDER_STAT(NumPrimitives, primCount);
  344. }
  345. void VulkanRenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ,
  346. const SPtr<CommandBuffer>& commandBuffer)
  347. {
  348. VulkanCommandBuffer* cb = getCB(commandBuffer);
  349. VulkanCmdBuffer* vkCB = cb->getInternal();
  350. vkCB->dispatch(numGroupsX, numGroupsY, numGroupsZ);
  351. BS_INC_RENDER_STAT(NumComputeCalls);
  352. }
  353. void VulkanRenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom,
  354. const SPtr<CommandBuffer>& commandBuffer)
  355. {
  356. VulkanCommandBuffer* cb = getCB(commandBuffer);
  357. VulkanCmdBuffer* vkCB = cb->getInternal();
  358. Rect2I area(left, top, right - left, bottom - top);
  359. vkCB->setScissorRect(area);
  360. }
  361. void VulkanRenderAPI::setStencilRef(UINT32 value, const SPtr<CommandBuffer>& commandBuffer)
  362. {
  363. VulkanCommandBuffer* cb = getCB(commandBuffer);
  364. VulkanCmdBuffer* vkCB = cb->getInternal();
  365. vkCB->setStencilRef(value);
  366. }
  367. void VulkanRenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask,
  368. const SPtr<CommandBuffer>& commandBuffer)
  369. {
  370. VulkanCommandBuffer* cb = getCB(commandBuffer);
  371. VulkanCmdBuffer* vkCB = cb->getInternal();
  372. vkCB->clearViewport(buffers, color, depth, stencil, targetMask);
  373. BS_INC_RENDER_STAT(NumClears);
  374. }
  375. void VulkanRenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil,
  376. UINT8 targetMask, const SPtr<CommandBuffer>& commandBuffer)
  377. {
  378. VulkanCommandBuffer* cb = getCB(commandBuffer);
  379. VulkanCmdBuffer* vkCB = cb->getInternal();
  380. vkCB->clearRenderTarget(buffers, color, depth, stencil, targetMask);
  381. BS_INC_RENDER_STAT(NumClears);
  382. }
  383. void VulkanRenderAPI::setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil,
  384. RenderSurfaceMask loadMask, const SPtr<CommandBuffer>& commandBuffer)
  385. {
  386. VulkanCommandBuffer* cb = getCB(commandBuffer);
  387. VulkanCmdBuffer* vkCB = cb->getInternal();
  388. vkCB->setRenderTarget(target, readOnlyDepthStencil, loadMask);
  389. BS_INC_RENDER_STAT(NumRenderTargetChanges);
  390. }
  391. void VulkanRenderAPI::swapBuffers(const SPtr<RenderTarget>& target, UINT32 syncMask)
  392. {
  393. THROW_IF_NOT_CORE_THREAD;
  394. submitCommandBuffer(mMainCommandBuffer, syncMask);
  395. target->swapBuffers(syncMask);
  396. // See if any command buffers finished executing
  397. VulkanCommandBufferManager& cbm = static_cast<VulkanCommandBufferManager&>(CommandBufferManager::instance());
  398. for (UINT32 i = 0; i < (UINT32)mDevices.size(); i++)
  399. cbm.refreshStates(i);
  400. BS_INC_RENDER_STAT(NumPresents);
  401. }
  402. void VulkanRenderAPI::addCommands(const SPtr<CommandBuffer>& commandBuffer, const SPtr<CommandBuffer>& secondary)
  403. {
  404. BS_EXCEPT(NotImplementedException, "Secondary command buffers not implemented");
  405. }
  406. void VulkanRenderAPI::submitCommandBuffer(const SPtr<CommandBuffer>& commandBuffer, UINT32 syncMask)
  407. {
  408. THROW_IF_NOT_CORE_THREAD;
  409. VulkanCommandBuffer* cmdBuffer = getCB(commandBuffer);
  410. // Submit all transfer buffers first
  411. VulkanCommandBufferManager& cbm = static_cast<VulkanCommandBufferManager&>(CommandBufferManager::instance());
  412. cbm.flushTransferBuffers(cmdBuffer->getDeviceIdx());
  413. cmdBuffer->submit(syncMask);
  414. }
  415. void VulkanRenderAPI::convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest)
  416. {
  417. dest = matrix;
  418. // Flip Y axis
  419. dest[1][1] = -dest[1][1];
  420. // Convert depth range from [-1,1] to [0,1]
  421. dest[2][0] = (dest[2][0] + dest[3][0]) / 2;
  422. dest[2][1] = (dest[2][1] + dest[3][1]) / 2;
  423. dest[2][2] = (dest[2][2] + dest[3][2]) / 2;
  424. dest[2][3] = (dest[2][3] + dest[3][3]) / 2;
  425. }
  426. const RenderAPIInfo& VulkanRenderAPI::getAPIInfo() const
  427. {
  428. static RenderAPIInfo info(0.0f, 0.0f, 0.0f, 1.0f, VET_COLOR_ABGR,
  429. RenderAPIFeatureFlag::NDCYAxisDown |
  430. RenderAPIFeatureFlag::ColumnMajorMatrices |
  431. RenderAPIFeatureFlag::MultiThreadedCB |
  432. RenderAPIFeatureFlag::MSAAImageStores);
  433. return info;
  434. }
  435. GpuParamBlockDesc VulkanRenderAPI::generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params)
  436. {
  437. GpuParamBlockDesc block;
  438. block.blockSize = 0;
  439. block.isShareable = true;
  440. block.name = name;
  441. block.slot = 0;
  442. block.set = 0;
  443. for (auto& param : params)
  444. {
  445. const GpuParamDataTypeInfo& typeInfo = bs::GpuParams::PARAM_SIZES.lookup[param.type];
  446. UINT32 size = typeInfo.size / 4;
  447. UINT32 alignment = typeInfo.alignment / 4;
  448. // Fix alignment if needed
  449. UINT32 alignOffset = block.blockSize % alignment;
  450. if (alignOffset != 0)
  451. {
  452. UINT32 padding = (alignment - alignOffset);
  453. block.blockSize += padding;
  454. }
  455. if (param.arraySize > 1)
  456. {
  457. // Array elements are always padded and aligned to vec4
  458. alignOffset = size % typeInfo.baseTypeSize;
  459. if (alignOffset != 0)
  460. {
  461. UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
  462. size += padding;
  463. }
  464. alignOffset = block.blockSize % typeInfo.baseTypeSize;
  465. if (alignOffset != 0)
  466. {
  467. UINT32 padding = (typeInfo.baseTypeSize - alignOffset);
  468. block.blockSize += padding;
  469. }
  470. param.elementSize = size;
  471. param.arrayElementStride = size;
  472. param.cpuMemOffset = block.blockSize;
  473. param.gpuMemOffset = 0;
  474. block.blockSize += size * param.arraySize;
  475. }
  476. else
  477. {
  478. param.elementSize = size;
  479. param.arrayElementStride = size;
  480. param.cpuMemOffset = block.blockSize;
  481. param.gpuMemOffset = 0;
  482. block.blockSize += size;
  483. }
  484. param.paramBlockSlot = 0;
  485. param.paramBlockSet = 0;
  486. }
  487. // Constant buffer size must always be a multiple of 16
  488. if (block.blockSize % 4 != 0)
  489. block.blockSize += (4 - (block.blockSize % 4));
  490. return block;
  491. }
  492. void VulkanRenderAPI::initCapabilites()
  493. {
  494. mNumDevices = (UINT32)mDevices.size();
  495. mCurrentCapabilities = bs_newN<RenderAPICapabilities>(mNumDevices);
  496. UINT32 deviceIdx = 0;
  497. for (auto& device : mDevices)
  498. {
  499. RenderAPICapabilities& caps = mCurrentCapabilities[deviceIdx];
  500. const VkPhysicalDeviceProperties& deviceProps = device->getDeviceProperties();
  501. const VkPhysicalDeviceFeatures& deviceFeatures = device->getDeviceFeatures();
  502. const VkPhysicalDeviceLimits& deviceLimits = deviceProps.limits;
  503. DriverVersion driverVersion;
  504. driverVersion.major = ((uint32_t)(deviceProps.apiVersion) >> 22);
  505. driverVersion.minor = ((uint32_t)(deviceProps.apiVersion) >> 12) & 0x3ff;
  506. driverVersion.release = (uint32_t)(deviceProps.apiVersion) & 0xfff;
  507. driverVersion.build = 0;
  508. caps.setDriverVersion(driverVersion);
  509. caps.setDeviceName(deviceProps.deviceName);
  510. // Determine vendor
  511. switch (deviceProps.vendorID)
  512. {
  513. case 0x10DE:
  514. caps.setVendor(GPU_NVIDIA);
  515. break;
  516. case 0x1002:
  517. caps.setVendor(GPU_AMD);
  518. break;
  519. case 0x163C:
  520. case 0x8086:
  521. caps.setVendor(GPU_INTEL);
  522. break;
  523. default:
  524. caps.setVendor(GPU_UNKNOWN);
  525. break;
  526. };
  527. caps.setRenderAPIName(getName());
  528. if(deviceFeatures.textureCompressionBC)
  529. caps.setCapability(RSC_TEXTURE_COMPRESSION_BC);
  530. if (deviceFeatures.textureCompressionETC2)
  531. caps.setCapability(RSC_TEXTURE_COMPRESSION_ETC2);
  532. if (deviceFeatures.textureCompressionASTC_LDR)
  533. caps.setCapability(RSC_TEXTURE_COMPRESSION_ASTC);
  534. caps.setMaxBoundVertexBuffers(deviceLimits.maxVertexInputBindings);
  535. caps.setNumMultiRenderTargets(deviceLimits.maxColorAttachments);
  536. caps.setCapability(RSC_COMPUTE_PROGRAM);
  537. caps.setNumTextureUnits(GPT_FRAGMENT_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  538. caps.setNumTextureUnits(GPT_VERTEX_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  539. caps.setNumTextureUnits(GPT_COMPUTE_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  540. caps.setNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  541. caps.setNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  542. caps.setNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  543. caps.setNumLoadStoreTextureUnits(GPT_FRAGMENT_PROGRAM, deviceLimits.maxPerStageDescriptorStorageImages);
  544. caps.setNumLoadStoreTextureUnits(GPT_COMPUTE_PROGRAM, deviceLimits.maxPerStageDescriptorStorageImages);
  545. if(deviceFeatures.geometryShader)
  546. {
  547. caps.setCapability(RSC_GEOMETRY_PROGRAM);
  548. caps.addShaderProfile("gs_5_0");
  549. caps.setNumTextureUnits(GPT_GEOMETRY_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  550. caps.setNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  551. caps.setGeometryProgramNumOutputVertices(deviceLimits.maxGeometryOutputVertices);
  552. }
  553. if (deviceFeatures.tessellationShader)
  554. {
  555. caps.setCapability(RSC_TESSELLATION_PROGRAM);
  556. caps.setNumTextureUnits(GPT_HULL_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  557. caps.setNumTextureUnits(GPT_DOMAIN_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  558. caps.setNumGpuParamBlockBuffers(GPT_HULL_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  559. caps.setNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  560. }
  561. caps.setNumCombinedTextureUnits(caps.getNumTextureUnits(GPT_FRAGMENT_PROGRAM)
  562. + caps.getNumTextureUnits(GPT_VERTEX_PROGRAM) + caps.getNumTextureUnits(GPT_GEOMETRY_PROGRAM)
  563. + caps.getNumTextureUnits(GPT_HULL_PROGRAM) + caps.getNumTextureUnits(GPT_DOMAIN_PROGRAM)
  564. + caps.getNumTextureUnits(GPT_COMPUTE_PROGRAM));
  565. caps.setNumCombinedGpuParamBlockBuffers(caps.getNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM)
  566. + caps.getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM) + caps.getNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM)
  567. + caps.getNumGpuParamBlockBuffers(GPT_HULL_PROGRAM) + caps.getNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM)
  568. + caps.getNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM));
  569. caps.setNumCombinedLoadStoreTextureUnits(caps.getNumLoadStoreTextureUnits(GPT_FRAGMENT_PROGRAM)
  570. + caps.getNumLoadStoreTextureUnits(GPT_COMPUTE_PROGRAM));
  571. caps.addShaderProfile("glsl");
  572. deviceIdx++;
  573. }
  574. }
  575. VulkanCommandBuffer* VulkanRenderAPI::getCB(const SPtr<CommandBuffer>& buffer)
  576. {
  577. if (buffer != nullptr)
  578. return static_cast<VulkanCommandBuffer*>(buffer.get());
  579. return static_cast<VulkanCommandBuffer*>(mMainCommandBuffer.get());
  580. }
  581. VulkanRenderAPI& gVulkanRenderAPI()
  582. {
  583. return static_cast<VulkanRenderAPI&>(RenderAPI::instance());
  584. }
  585. }}