BsVulkanRenderAPI.cpp 24 KB

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