BsVulkanRenderAPI.cpp 24 KB

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