BsVulkanRenderAPI.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  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 "BsVulkanVertexInputManager.h"
  17. #include "Win32/BsWin32VideoModeInfo.h"
  18. namespace BansheeEngine
  19. {
  20. PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = nullptr;
  21. PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = nullptr;
  22. PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = nullptr;
  23. PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR = nullptr;
  24. PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr;
  25. PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR = nullptr;
  26. PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = nullptr;
  27. PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = nullptr;
  28. PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = nullptr;
  29. PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR = nullptr;
  30. PFN_vkQueuePresentKHR vkQueuePresentKHR = nullptr;
  31. VkBool32 debugMsgCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
  32. size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void* pUserData)
  33. {
  34. StringStream message;
  35. // Determine prefix
  36. if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
  37. message << "ERROR";
  38. if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT)
  39. message << "WARNING";
  40. if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
  41. message << "PERFORMANCE";
  42. if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)
  43. message << "INFO";
  44. if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT)
  45. message << "DEBUG";
  46. message << ": [" << pLayerPrefix << "] Code " << msgCode << ": " << pMsg << std::endl;
  47. if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
  48. BS_EXCEPT(RenderingAPIException, message.str())
  49. else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT || flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
  50. LOGWRN(message.str())
  51. else
  52. LOGDBG(message.str())
  53. // Don't abort calls that caused a validation message
  54. return VK_FALSE;
  55. }
  56. VulkanRenderAPI::VulkanRenderAPI()
  57. :mInstance(nullptr), mDebugCallback(nullptr)
  58. { }
  59. VulkanRenderAPI::~VulkanRenderAPI()
  60. {
  61. }
  62. const StringID& VulkanRenderAPI::getName() const
  63. {
  64. static StringID strName("VulkanRenderAPI");
  65. return strName;
  66. }
  67. const String& VulkanRenderAPI::getShadingLanguageName() const
  68. {
  69. static String strName("glsl");
  70. return strName;
  71. }
  72. void VulkanRenderAPI::initialize()
  73. {
  74. THROW_IF_NOT_CORE_THREAD;
  75. // Create instance
  76. VkApplicationInfo appInfo;
  77. appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  78. appInfo.pNext = nullptr;
  79. appInfo.pApplicationName = "Banshee3D App";
  80. appInfo.applicationVersion = 1;
  81. appInfo.pEngineName = "Banshee3D";
  82. appInfo.engineVersion = (0 << 24) | (4 << 16) | 0;
  83. appInfo.apiVersion = VK_API_VERSION_1_0;
  84. #if BS_DEBUG_MODE
  85. const char* layers[] =
  86. {
  87. "VK_LAYER_LUNARG_standard_validation"
  88. };
  89. const char* extensions[] =
  90. {
  91. nullptr, /** Surface extension */
  92. nullptr, /** OS specific surface extension */
  93. VK_EXT_DEBUG_REPORT_EXTENSION_NAME
  94. };
  95. #else
  96. const char** layers = nullptr;
  97. const char* extensions[] =
  98. {
  99. nullptr, /** Surface extension */
  100. nullptr, /** OS specific surface extension */
  101. };
  102. #endif
  103. extensions[0] = VK_KHR_SURFACE_EXTENSION_NAME;
  104. #if BS_PLATFORM == BS_PLATFORM_WIN32
  105. extensions[1] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
  106. #elif BS_PLATFORM == BS_PLATFORM_ANDROID
  107. extensions[1] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
  108. #else
  109. extensions[1] = VK_KHR_XCB_SURFACE_EXTENSION_NAME;
  110. #endif
  111. uint32_t numLayers = sizeof(layers) / sizeof(layers[0]);
  112. uint32_t numExtensions = sizeof(extensions) / sizeof(extensions[0]);
  113. VkInstanceCreateInfo instanceInfo;
  114. instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  115. instanceInfo.pNext = nullptr;
  116. instanceInfo.flags = 0;
  117. instanceInfo.pApplicationInfo = &appInfo;
  118. instanceInfo.enabledLayerCount = numLayers;
  119. instanceInfo.ppEnabledLayerNames = layers;
  120. instanceInfo.enabledExtensionCount = numExtensions;
  121. instanceInfo.ppEnabledExtensionNames = extensions;
  122. VkResult result = vkCreateInstance(&instanceInfo, gVulkanAllocator, &mInstance);
  123. assert(result == VK_SUCCESS);
  124. // Set up debugging
  125. #if BS_DEBUG_MODE
  126. VkDebugReportFlagsEXT debugFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT |
  127. VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
  128. GET_INSTANCE_PROC_ADDR(mInstance, CreateDebugReportCallbackEXT);
  129. GET_INSTANCE_PROC_ADDR(mInstance, DestroyDebugReportCallbackEXT);
  130. VkDebugReportCallbackCreateInfoEXT debugInfo;
  131. debugInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
  132. debugInfo.pNext = nullptr;
  133. debugInfo.flags = 0;
  134. debugInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT)debugMsgCallback;
  135. debugInfo.flags = debugFlags;
  136. result = vkCreateDebugReportCallbackEXT(mInstance, &debugInfo, nullptr, &mDebugCallback);
  137. assert(result == VK_SUCCESS);
  138. #endif
  139. // Enumerate all devices
  140. uint32_t numDevices;
  141. result = vkEnumeratePhysicalDevices(mInstance, &numDevices, nullptr);
  142. assert(result == VK_SUCCESS);
  143. Vector<VkPhysicalDevice> physicalDevices(numDevices);
  144. result = vkEnumeratePhysicalDevices(mInstance, &numDevices, physicalDevices.data());
  145. assert(result == VK_SUCCESS);
  146. mDevices.resize(numDevices);
  147. for(uint32_t i = 0; i < numDevices; i++)
  148. mDevices[i] = bs_shared_ptr_new<VulkanDevice>(physicalDevices[i]);
  149. // Find primary device
  150. // Note: MULTIGPU - Detect multiple similar devices here if supporting multi-GPU
  151. for (uint32_t i = 0; i < numDevices; i++)
  152. {
  153. if (mDevices[i]->getDeviceProperties().deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
  154. {
  155. mPrimaryDevices.push_back(mDevices[i]);
  156. break;
  157. }
  158. }
  159. if (mPrimaryDevices.size() == 0)
  160. mPrimaryDevices.push_back(mDevices[0]);
  161. #if BS_PLATFORM == BS_PLATFORM_WIN32
  162. mVideoModeInfo = bs_shared_ptr_new<Win32VideoModeInfo>();
  163. #else
  164. static_assert(false, "mVideoModeInfo needs to be created.")
  165. #endif
  166. // Get required extension functions
  167. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfaceSupportKHR);
  168. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfaceFormatsKHR);
  169. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
  170. GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfacePresentModesKHR);
  171. VkDevice presentDevice = _getPresentDevice()->getLogical();
  172. GET_DEVICE_PROC_ADDR(presentDevice, CreateSwapchainKHR);
  173. GET_DEVICE_PROC_ADDR(presentDevice, DestroySwapchainKHR);
  174. GET_DEVICE_PROC_ADDR(presentDevice, GetSwapchainImagesKHR);
  175. GET_DEVICE_PROC_ADDR(presentDevice, AcquireNextImageKHR);
  176. GET_DEVICE_PROC_ADDR(presentDevice, QueuePresentKHR);
  177. // Create command buffer manager
  178. CommandBufferManager::startUp<VulkanCommandBufferManager>(*this);
  179. // Create the texture manager for use by others
  180. TextureManager::startUp<VulkanTextureManager>();
  181. TextureCoreManager::startUp<VulkanTextureCoreManager>();
  182. // Create hardware buffer manager
  183. HardwareBufferManager::startUp();
  184. HardwareBufferCoreManager::startUp<VulkanHardwareBufferCoreManager>();
  185. // Create render window manager
  186. RenderWindowManager::startUp<VulkanRenderWindowManager>();
  187. RenderWindowCoreManager::startUp<VulkanRenderWindowCoreManager>(*this);
  188. // Create query manager
  189. QueryManager::startUp<VulkanQueryManager>();
  190. // Create vertex input manager
  191. VulkanVertexInputManager::startUp();
  192. // Create & register HLSL factory
  193. mGLSLFactory = bs_new<VulkanGLSLProgramFactory>();
  194. // Create render state manager
  195. RenderStateCoreManager::startUp<VulkanRenderStateCoreManager>();
  196. GpuProgramCoreManager::instance().addFactory(mGLSLFactory);
  197. initCapabilites();
  198. RenderAPICore::initialize();
  199. }
  200. void VulkanRenderAPI::destroyCore()
  201. {
  202. THROW_IF_NOT_CORE_THREAD;
  203. if (mGLSLFactory != nullptr)
  204. {
  205. bs_delete(mGLSLFactory);
  206. mGLSLFactory = nullptr;
  207. }
  208. VulkanVertexInputManager::shutDown();
  209. QueryManager::shutDown();
  210. RenderStateCoreManager::shutDown();
  211. RenderWindowCoreManager::shutDown();
  212. RenderWindowManager::shutDown();
  213. HardwareBufferCoreManager::shutDown();
  214. HardwareBufferManager::shutDown();
  215. TextureCoreManager::shutDown();
  216. TextureManager::shutDown();
  217. CommandBufferManager::shutDown();
  218. mPrimaryDevices.clear();
  219. mDevices.clear();
  220. #if BS_DEBUG_MODE
  221. if (mDebugCallback != nullptr)
  222. vkDestroyDebugReportCallbackEXT(mInstance, mDebugCallback, gVulkanAllocator);
  223. #endif
  224. vkDestroyInstance(mInstance, gVulkanAllocator);
  225. RenderAPICore::destroyCore();
  226. }
  227. void VulkanRenderAPI::setGraphicsPipeline(const SPtr<GpuPipelineStateCore>& pipelineState,
  228. const SPtr<CommandBuffer>& commandBuffer)
  229. {
  230. BS_INC_RENDER_STAT(NumPipelineStateChanges);
  231. }
  232. void VulkanRenderAPI::setComputePipeline(const SPtr<GpuProgramCore>& computeProgram,
  233. const SPtr<CommandBuffer>& commandBuffer)
  234. {
  235. BS_INC_RENDER_STAT(NumPipelineStateChanges);
  236. }
  237. void VulkanRenderAPI::setGpuParams(const SPtr<GpuParamsCore>& gpuParams, const SPtr<CommandBuffer>& commandBuffer)
  238. {
  239. BS_INC_RENDER_STAT(NumGpuParamBinds);
  240. }
  241. void VulkanRenderAPI::beginFrame(const SPtr<CommandBuffer>& commandBuffer)
  242. {
  243. }
  244. void VulkanRenderAPI::endFrame(const SPtr<CommandBuffer>& commandBuffer)
  245. {
  246. }
  247. void VulkanRenderAPI::setViewport(const Rect2& vp, const SPtr<CommandBuffer>& commandBuffer)
  248. {
  249. }
  250. void VulkanRenderAPI::setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers,
  251. const SPtr<CommandBuffer>& commandBuffer)
  252. {
  253. BS_INC_RENDER_STAT(NumVertexBufferBinds);
  254. }
  255. void VulkanRenderAPI::setIndexBuffer(const SPtr<IndexBufferCore>& buffer, const SPtr<CommandBuffer>& commandBuffer)
  256. {
  257. BS_INC_RENDER_STAT(NumIndexBufferBinds);
  258. }
  259. void VulkanRenderAPI::setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration,
  260. const SPtr<CommandBuffer>& commandBuffer)
  261. {
  262. }
  263. void VulkanRenderAPI::setDrawOperation(DrawOperationType op, const SPtr<CommandBuffer>& commandBuffer)
  264. {
  265. }
  266. void VulkanRenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount,
  267. const SPtr<CommandBuffer>& commandBuffer)
  268. {
  269. UINT32 primCount = 0;
  270. BS_INC_RENDER_STAT(NumDrawCalls);
  271. BS_ADD_RENDER_STAT(NumVertices, vertexCount);
  272. BS_ADD_RENDER_STAT(NumPrimitives, primCount);
  273. }
  274. void VulkanRenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount,
  275. UINT32 instanceCount, const SPtr<CommandBuffer>& commandBuffer)
  276. {
  277. UINT32 primCount = 0;
  278. BS_INC_RENDER_STAT(NumDrawCalls);
  279. BS_ADD_RENDER_STAT(NumVertices, vertexCount);
  280. BS_ADD_RENDER_STAT(NumPrimitives, primCount);
  281. }
  282. void VulkanRenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ,
  283. const SPtr<CommandBuffer>& commandBuffer)
  284. {
  285. BS_INC_RENDER_STAT(NumComputeCalls);
  286. }
  287. void VulkanRenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom,
  288. const SPtr<CommandBuffer>& commandBuffer)
  289. {
  290. }
  291. void VulkanRenderAPI::setStencilRef(UINT32 value, const SPtr<CommandBuffer>& commandBuffer)
  292. {
  293. }
  294. void VulkanRenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask,
  295. const SPtr<CommandBuffer>& commandBuffer)
  296. {
  297. BS_INC_RENDER_STAT(NumClears);
  298. }
  299. void VulkanRenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil,
  300. UINT8 targetMask, const SPtr<CommandBuffer>& commandBuffer)
  301. {
  302. BS_INC_RENDER_STAT(NumClears);
  303. }
  304. void VulkanRenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil,
  305. const SPtr<CommandBuffer>& commandBuffer)
  306. {
  307. BS_INC_RENDER_STAT(NumRenderTargetChanges);
  308. }
  309. void VulkanRenderAPI::swapBuffers(const SPtr<RenderTargetCore>& target, const SPtr<CommandBuffer>& commandBuffer)
  310. {
  311. BS_INC_RENDER_STAT(NumPresents);
  312. }
  313. void VulkanRenderAPI::addCommands(const SPtr<CommandBuffer>& commandBuffer, const SPtr<CommandBuffer>& secondary)
  314. {
  315. }
  316. void VulkanRenderAPI::executeCommands(const SPtr<CommandBuffer>& commandBuffer, UINT32 syncMask)
  317. {
  318. }
  319. void VulkanRenderAPI::convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest)
  320. {
  321. }
  322. const RenderAPIInfo& VulkanRenderAPI::getAPIInfo() const
  323. {
  324. static RenderAPIInfo info(0.0f, 0.0f, 0.0f, 1.0f, VET_COLOR_ABGR, false, true, false, false);
  325. return info;
  326. }
  327. GpuParamBlockDesc VulkanRenderAPI::generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params)
  328. {
  329. GpuParamBlockDesc block;
  330. return block;
  331. }
  332. void VulkanRenderAPI::initCapabilites()
  333. {
  334. mNumDevices = (UINT32)mDevices.size();
  335. mCurrentCapabilities = bs_newN<RenderAPICapabilities>(mNumDevices);
  336. UINT32 deviceIdx = 0;
  337. for (auto& device : mDevices)
  338. {
  339. RenderAPICapabilities& caps = mCurrentCapabilities[deviceIdx];
  340. const VkPhysicalDeviceProperties& deviceProps = device->getDeviceProperties();
  341. const VkPhysicalDeviceFeatures& deviceFeatures = device->getDeviceFeatures();
  342. const VkPhysicalDeviceLimits& deviceLimits = deviceProps.limits;
  343. DriverVersion driverVersion;
  344. driverVersion.major = ((uint32_t)(deviceProps.apiVersion) >> 22);
  345. driverVersion.minor = ((uint32_t)(deviceProps.apiVersion) >> 12) & 0x3ff;
  346. driverVersion.release = (uint32_t)(deviceProps.apiVersion) & 0xfff;
  347. driverVersion.build = 0;
  348. caps.setDriverVersion(driverVersion);
  349. caps.setDeviceName(deviceProps.deviceName);
  350. // Determine vendor
  351. switch (deviceProps.vendorID)
  352. {
  353. case 0x10DE:
  354. caps.setVendor(GPU_NVIDIA);
  355. break;
  356. case 0x1002:
  357. caps.setVendor(GPU_AMD);
  358. break;
  359. case 0x163C:
  360. case 0x8086:
  361. caps.setVendor(GPU_INTEL);
  362. break;
  363. default:
  364. caps.setVendor(GPU_UNKNOWN);
  365. break;
  366. };
  367. caps.setRenderAPIName(getName());
  368. if(deviceFeatures.textureCompressionBC)
  369. caps.setCapability(RSC_TEXTURE_COMPRESSION_BC);
  370. if (deviceFeatures.textureCompressionETC2)
  371. caps.setCapability(RSC_TEXTURE_COMPRESSION_ETC2);
  372. if (deviceFeatures.textureCompressionASTC_LDR)
  373. caps.setCapability(RSC_TEXTURE_COMPRESSION_ASTC);
  374. caps.setMaxBoundVertexBuffers(deviceLimits.maxVertexInputBindings);
  375. caps.setNumMultiRenderTargets(deviceLimits.maxColorAttachments);
  376. caps.setCapability(RSC_COMPUTE_PROGRAM);
  377. caps.addShaderProfile("ps_5_0");
  378. caps.addShaderProfile("vs_5_0");
  379. caps.addShaderProfile("cs_5_0");
  380. caps.addGpuProgramProfile(GPP_FS_5_0, "ps_5_0");
  381. caps.addGpuProgramProfile(GPP_VS_5_0, "vs_5_0");
  382. caps.addGpuProgramProfile(GPP_CS_5_0, "cs_5_0");
  383. caps.setNumTextureUnits(GPT_FRAGMENT_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  384. caps.setNumTextureUnits(GPT_VERTEX_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  385. caps.setNumTextureUnits(GPT_COMPUTE_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  386. caps.setNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  387. caps.setNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  388. caps.setNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  389. caps.setNumLoadStoreTextureUnits(GPT_FRAGMENT_PROGRAM, deviceLimits.maxPerStageDescriptorStorageImages);
  390. caps.setNumLoadStoreTextureUnits(GPT_COMPUTE_PROGRAM, deviceLimits.maxPerStageDescriptorStorageImages);
  391. if(deviceFeatures.geometryShader)
  392. {
  393. caps.setCapability(RSC_GEOMETRY_PROGRAM);
  394. caps.addShaderProfile("gs_5_0");
  395. caps.addGpuProgramProfile(GPP_GS_5_0, "gs_5_0");
  396. caps.setNumTextureUnits(GPT_GEOMETRY_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  397. caps.setNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  398. caps.setGeometryProgramNumOutputVertices(deviceLimits.maxGeometryOutputVertices);
  399. }
  400. if (deviceFeatures.tessellationShader)
  401. {
  402. caps.setCapability(RSC_TESSELLATION_PROGRAM);
  403. caps.addShaderProfile("hs_5_0");
  404. caps.addShaderProfile("ds_5_0");
  405. caps.addGpuProgramProfile(GPP_HS_5_0, "hs_5_0");
  406. caps.addGpuProgramProfile(GPP_DS_5_0, "ds_5_0");
  407. caps.setNumTextureUnits(GPT_HULL_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  408. caps.setNumTextureUnits(GPT_DOMAIN_PROGRAM, deviceLimits.maxPerStageDescriptorSampledImages);
  409. caps.setNumGpuParamBlockBuffers(GPT_HULL_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  410. caps.setNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM, deviceLimits.maxPerStageDescriptorUniformBuffers);
  411. }
  412. caps.setNumCombinedTextureUnits(caps.getNumTextureUnits(GPT_FRAGMENT_PROGRAM)
  413. + caps.getNumTextureUnits(GPT_VERTEX_PROGRAM) + caps.getNumTextureUnits(GPT_GEOMETRY_PROGRAM)
  414. + caps.getNumTextureUnits(GPT_HULL_PROGRAM) + caps.getNumTextureUnits(GPT_DOMAIN_PROGRAM)
  415. + caps.getNumTextureUnits(GPT_COMPUTE_PROGRAM));
  416. caps.setNumCombinedGpuParamBlockBuffers(caps.getNumGpuParamBlockBuffers(GPT_FRAGMENT_PROGRAM)
  417. + caps.getNumGpuParamBlockBuffers(GPT_VERTEX_PROGRAM) + caps.getNumGpuParamBlockBuffers(GPT_GEOMETRY_PROGRAM)
  418. + caps.getNumGpuParamBlockBuffers(GPT_HULL_PROGRAM) + caps.getNumGpuParamBlockBuffers(GPT_DOMAIN_PROGRAM)
  419. + caps.getNumGpuParamBlockBuffers(GPT_COMPUTE_PROGRAM));
  420. caps.setNumCombinedLoadStoreTextureUnits(caps.getNumLoadStoreTextureUnits(GPT_FRAGMENT_PROGRAM)
  421. + caps.getNumLoadStoreTextureUnits(GPT_COMPUTE_PROGRAM));
  422. caps.addShaderProfile("glsl");
  423. deviceIdx++;
  424. }
  425. }
  426. }