BsVulkanUtility.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanUtility.h"
  4. #include "BsVulkanRenderAPI.h"
  5. #include "BsVulkanDevice.h"
  6. #include "BsException.h"
  7. namespace bs { namespace ct
  8. {
  9. PixelFormat VulkanUtility::getClosestSupportedPixelFormat(VulkanDevice& device, PixelFormat format, TextureType texType,
  10. int usage, bool optimalTiling, bool hwGamma)
  11. {
  12. // Check for any obvious issues first
  13. PixelUtil::checkFormat(format, texType, usage);
  14. // Check actual device for format support
  15. VkFormatFeatureFlags wantedFeatureFlags = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
  16. if ((usage & TU_RENDERTARGET) != 0)
  17. wantedFeatureFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
  18. if ((usage & TU_DEPTHSTENCIL) != 0)
  19. wantedFeatureFlags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
  20. if ((usage & TU_LOADSTORE) != 0)
  21. wantedFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
  22. VkFormatProperties props;
  23. auto isSupported = [&](VkFormat vkFmt)
  24. {
  25. vkGetPhysicalDeviceFormatProperties(device.getPhysical(), vkFmt, &props);
  26. VkFormatFeatureFlags featureFlags = optimalTiling ? props.optimalTilingFeatures : props.linearTilingFeatures;
  27. return (featureFlags & wantedFeatureFlags) != 0;
  28. };
  29. VkFormat vkFormat = getPixelFormat(format, hwGamma);
  30. if(!isSupported(vkFormat))
  31. {
  32. if ((usage & TU_DEPTHSTENCIL) != 0)
  33. {
  34. bool hasStencil = format == PF_D24S8 || format == PF_D32_S8X24;
  35. // Spec guarantees at least one depth-only, and one depth-stencil format to be supported
  36. if(hasStencil)
  37. {
  38. if (isSupported(VK_FORMAT_D32_SFLOAT_S8_UINT))
  39. format = PF_D32_S8X24;
  40. else
  41. format = PF_D24S8;
  42. // We ignore 8-bit stencil-only, and 16/8 depth/stencil combo buffers as engine doesn't expose them,
  43. // and spec guarantees one of the above must be implemented.
  44. }
  45. else
  46. {
  47. // The only format that could have failed is 32-bit depth, so we must use the alternative 16-bit.
  48. // Spec guarantees it is always supported.
  49. format = PF_D16;
  50. }
  51. }
  52. else
  53. {
  54. int bitDepths[4];
  55. PixelUtil::getBitDepths(format, bitDepths);
  56. if (bitDepths[0] == 16) // 16-bit format, fall back to 4-channel 16-bit, guaranteed to be supported
  57. format = PF_FLOAT16_RGBA;
  58. else if(format == PF_BC6H) // Fall back to uncompressed alternative
  59. format = PF_FLOAT16_RGBA;
  60. else // Must be 8-bit per channel format, compressed format or some uneven format
  61. format = PF_R8G8B8A8;
  62. }
  63. }
  64. return format;
  65. }
  66. VkFormat VulkanUtility::getPixelFormat(PixelFormat format, bool sRGB)
  67. {
  68. switch (format)
  69. {
  70. case PF_R8:
  71. if(sRGB)
  72. return VK_FORMAT_R8_SRGB;
  73. return VK_FORMAT_R8_UNORM;
  74. case PF_R8G8:
  75. if (sRGB)
  76. return VK_FORMAT_R8G8_SRGB;
  77. return VK_FORMAT_R8G8_UNORM;
  78. case PF_R8G8B8:
  79. if (sRGB)
  80. return VK_FORMAT_R8G8B8_SRGB;
  81. return VK_FORMAT_R8G8B8_UNORM;
  82. case PF_R8G8B8A8:
  83. if (sRGB)
  84. return VK_FORMAT_R8G8B8A8_SRGB;
  85. return VK_FORMAT_R8G8B8A8_UNORM;
  86. case PF_B8G8R8A8:
  87. if (sRGB)
  88. return VK_FORMAT_B8G8R8A8_SRGB;
  89. return VK_FORMAT_B8G8R8A8_UNORM;
  90. case PF_FLOAT16_R:
  91. return VK_FORMAT_R16_SFLOAT;
  92. case PF_FLOAT16_RG:
  93. return VK_FORMAT_R16G16_SFLOAT;
  94. case PF_FLOAT16_RGB:
  95. return VK_FORMAT_R16G16B16_SFLOAT;
  96. case PF_FLOAT16_RGBA:
  97. return VK_FORMAT_R16G16B16A16_SFLOAT;
  98. case PF_FLOAT32_R:
  99. return VK_FORMAT_R32_SFLOAT;
  100. case PF_FLOAT32_RG:
  101. return VK_FORMAT_R32G32_SFLOAT;
  102. case PF_FLOAT32_RGB:
  103. return VK_FORMAT_R32G32B32_SFLOAT;
  104. case PF_FLOAT32_RGBA:
  105. return VK_FORMAT_R32G32B32A32_SFLOAT;
  106. case PF_BC1:
  107. case PF_BC1a:
  108. if (sRGB)
  109. return VK_FORMAT_BC1_RGB_SRGB_BLOCK;
  110. return VK_FORMAT_BC1_RGB_UNORM_BLOCK;
  111. case PF_BC2:
  112. if (sRGB)
  113. return VK_FORMAT_BC2_SRGB_BLOCK;
  114. return VK_FORMAT_BC2_UNORM_BLOCK;
  115. case PF_BC3:
  116. if (sRGB)
  117. return VK_FORMAT_BC3_SRGB_BLOCK;
  118. return VK_FORMAT_BC3_UNORM_BLOCK;
  119. case PF_BC4:
  120. return VK_FORMAT_BC4_SNORM_BLOCK;
  121. case PF_BC5:
  122. return VK_FORMAT_BC5_UNORM_BLOCK;
  123. case PF_BC6H:
  124. return VK_FORMAT_BC6H_SFLOAT_BLOCK;
  125. case PF_BC7:
  126. if (sRGB)
  127. return VK_FORMAT_BC7_SRGB_BLOCK;
  128. return VK_FORMAT_BC7_UNORM_BLOCK;
  129. case PF_D32_S8X24:
  130. return VK_FORMAT_D32_SFLOAT_S8_UINT;
  131. case PF_D24S8:
  132. return VK_FORMAT_D24_UNORM_S8_UINT;
  133. case PF_D32:
  134. return VK_FORMAT_D32_SFLOAT;
  135. case PF_D16:
  136. return VK_FORMAT_D16_UNORM;
  137. case PF_FLOAT_R11G11B10:
  138. return VK_FORMAT_B10G11R11_UFLOAT_PACK32;
  139. case PF_UNORM_R10G10B10A2:
  140. return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
  141. case PF_UNKNOWN:
  142. default:
  143. return VK_FORMAT_UNDEFINED;
  144. }
  145. }
  146. VkFormat VulkanUtility::getBufferFormat(GpuBufferFormat format)
  147. {
  148. static bool lookupInitialized = false;
  149. static VkFormat lookup[BF_COUNT];
  150. if (!lookupInitialized)
  151. {
  152. lookup[BF_16X1F] = VK_FORMAT_R16_SFLOAT;
  153. lookup[BF_16X2F] = VK_FORMAT_R16G16_SFLOAT;
  154. lookup[BF_16X4F] = VK_FORMAT_R16G16B16A16_SFLOAT;
  155. lookup[BF_32X1F] = VK_FORMAT_R32_SFLOAT;
  156. lookup[BF_32X2F] = VK_FORMAT_R32G32_SFLOAT;
  157. lookup[BF_32X3F] = VK_FORMAT_R32G32B32_SFLOAT;
  158. lookup[BF_32X4F] = VK_FORMAT_R32G32B32A32_SFLOAT;
  159. lookup[BF_8X1] = VK_FORMAT_R8_UNORM;
  160. lookup[BF_8X2] = VK_FORMAT_R8G8_UNORM;
  161. lookup[BF_8X4] = VK_FORMAT_R8G8B8A8_UNORM;
  162. lookup[BF_16X1] = VK_FORMAT_R16_UNORM;
  163. lookup[BF_16X2] = VK_FORMAT_R16G16_UNORM;
  164. lookup[BF_16X4] = VK_FORMAT_R16G16B16A16_UNORM;
  165. lookup[BF_8X1S] = VK_FORMAT_R8_SINT;
  166. lookup[BF_8X2S] = VK_FORMAT_R8G8_SINT;
  167. lookup[BF_8X4S] = VK_FORMAT_R8G8B8A8_SINT;
  168. lookup[BF_16X1S] = VK_FORMAT_R16_SINT;
  169. lookup[BF_16X2S] = VK_FORMAT_R16G16_SINT;
  170. lookup[BF_16X4S] = VK_FORMAT_R16G16B16A16_SINT;
  171. lookup[BF_32X1S] = VK_FORMAT_R32_SINT;
  172. lookup[BF_32X2S] = VK_FORMAT_R32G32_SINT;
  173. lookup[BF_32X3S] = VK_FORMAT_R32G32B32_SINT;
  174. lookup[BF_32X4S] = VK_FORMAT_R32G32B32A32_SINT;
  175. lookup[BF_8X1U] = VK_FORMAT_R8_UINT;
  176. lookup[BF_8X2U] = VK_FORMAT_R8G8_UINT;
  177. lookup[BF_8X4U] = VK_FORMAT_R8G8B8A8_UINT;
  178. lookup[BF_16X1U] = VK_FORMAT_R16_UINT;
  179. lookup[BF_16X2U] = VK_FORMAT_R16G16_UINT;
  180. lookup[BF_16X4U] = VK_FORMAT_R16G16B16A16_UINT;
  181. lookup[BF_32X1U] = VK_FORMAT_R32_UINT;
  182. lookup[BF_32X2U] = VK_FORMAT_R32G32_UINT;
  183. lookup[BF_32X3U] = VK_FORMAT_R32G32B32_UINT;
  184. lookup[BF_32X4U] = VK_FORMAT_R32G32B32A32_UINT;
  185. lookupInitialized = true;
  186. }
  187. if (format >= BF_COUNT)
  188. return VK_FORMAT_UNDEFINED;
  189. return lookup[(UINT32)format];
  190. }
  191. VkFormat VulkanUtility::getVertexType(VertexElementType type)
  192. {
  193. static bool lookupInitialized = false;
  194. static VkFormat lookup[VET_COUNT];
  195. if (!lookupInitialized)
  196. {
  197. lookup[VET_COLOR] = VK_FORMAT_R8G8B8A8_UNORM;
  198. lookup[VET_COLOR_ABGR] = VK_FORMAT_R8G8B8A8_UNORM;
  199. lookup[VET_COLOR_ARGB] = VK_FORMAT_R8G8B8A8_UNORM;
  200. lookup[VET_UBYTE4_NORM] = VK_FORMAT_R8G8B8A8_UNORM;
  201. lookup[VET_FLOAT1] = VK_FORMAT_R32_SFLOAT;
  202. lookup[VET_FLOAT2] = VK_FORMAT_R32G32_SFLOAT;
  203. lookup[VET_FLOAT3] = VK_FORMAT_R32G32B32_SFLOAT;
  204. lookup[VET_FLOAT4] = VK_FORMAT_R32G32B32A32_SFLOAT;
  205. lookup[VET_USHORT1] = VK_FORMAT_R16_UINT;
  206. lookup[VET_USHORT2] = VK_FORMAT_R16G16_UINT;
  207. lookup[VET_USHORT4] = VK_FORMAT_R16G16B16A16_UINT;
  208. lookup[VET_SHORT1] = VK_FORMAT_R16_SINT;
  209. lookup[VET_SHORT2] = VK_FORMAT_R16G16_SINT;
  210. lookup[VET_SHORT4] = VK_FORMAT_R16G16B16A16_SINT;
  211. lookup[VET_UINT1] = VK_FORMAT_R32_UINT;
  212. lookup[VET_UINT2] = VK_FORMAT_R32G32_UINT;
  213. lookup[VET_UINT3] = VK_FORMAT_R32G32B32_UINT;
  214. lookup[VET_UINT4] = VK_FORMAT_R32G32B32A32_UINT;
  215. lookup[VET_INT1] = VK_FORMAT_R32_SINT;
  216. lookup[VET_INT2] = VK_FORMAT_R32G32_SINT;
  217. lookup[VET_INT3] = VK_FORMAT_R32G32B32_SINT;
  218. lookup[VET_INT4] = VK_FORMAT_R32G32B32A32_SINT;
  219. lookup[VET_UBYTE4] = VK_FORMAT_R8G8B8A8_UINT;
  220. lookupInitialized = true;
  221. }
  222. if (type >= VET_COUNT)
  223. return VK_FORMAT_UNDEFINED;
  224. return lookup[(UINT32)type];
  225. }
  226. VkSampleCountFlagBits VulkanUtility::getSampleFlags(UINT32 numSamples)
  227. {
  228. switch(numSamples)
  229. {
  230. case 0:
  231. case 1:
  232. return VK_SAMPLE_COUNT_1_BIT;
  233. case 2:
  234. return VK_SAMPLE_COUNT_2_BIT;
  235. case 4:
  236. return VK_SAMPLE_COUNT_4_BIT;
  237. case 8:
  238. return VK_SAMPLE_COUNT_8_BIT;
  239. case 16:
  240. return VK_SAMPLE_COUNT_16_BIT;
  241. case 32:
  242. return VK_SAMPLE_COUNT_32_BIT;
  243. case 64:
  244. return VK_SAMPLE_COUNT_64_BIT;
  245. }
  246. return VK_SAMPLE_COUNT_1_BIT;
  247. }
  248. VkShaderStageFlagBits VulkanUtility::getShaderStage(GpuProgramType type)
  249. {
  250. switch(type)
  251. {
  252. case GPT_FRAGMENT_PROGRAM:
  253. return VK_SHADER_STAGE_FRAGMENT_BIT;
  254. case GPT_HULL_PROGRAM:
  255. return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
  256. case GPT_DOMAIN_PROGRAM:
  257. return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
  258. case GPT_GEOMETRY_PROGRAM:
  259. return VK_SHADER_STAGE_GEOMETRY_BIT;
  260. case GPT_VERTEX_PROGRAM:
  261. return VK_SHADER_STAGE_VERTEX_BIT;
  262. case GPT_COMPUTE_PROGRAM:
  263. return VK_SHADER_STAGE_COMPUTE_BIT;
  264. }
  265. // Unsupported type
  266. return VK_SHADER_STAGE_VERTEX_BIT;
  267. }
  268. VkSamplerAddressMode VulkanUtility::getAddressingMode(TextureAddressingMode mode)
  269. {
  270. switch (mode)
  271. {
  272. case TAM_WRAP:
  273. return VK_SAMPLER_ADDRESS_MODE_REPEAT;
  274. case TAM_MIRROR:
  275. return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
  276. case TAM_CLAMP:
  277. return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
  278. case TAM_BORDER:
  279. return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
  280. }
  281. return VK_SAMPLER_ADDRESS_MODE_REPEAT;
  282. }
  283. VkBlendFactor VulkanUtility::getBlendFactor(BlendFactor factor)
  284. {
  285. switch (factor)
  286. {
  287. case BF_ONE:
  288. return VK_BLEND_FACTOR_ONE;
  289. case BF_ZERO:
  290. return VK_BLEND_FACTOR_ZERO;
  291. case BF_DEST_COLOR:
  292. return VK_BLEND_FACTOR_DST_COLOR;
  293. case BF_SOURCE_COLOR:
  294. return VK_BLEND_FACTOR_SRC_COLOR;
  295. case BF_INV_DEST_COLOR:
  296. return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
  297. case BF_INV_SOURCE_COLOR:
  298. return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
  299. case BF_DEST_ALPHA:
  300. return VK_BLEND_FACTOR_DST_ALPHA;
  301. case BF_SOURCE_ALPHA:
  302. return VK_BLEND_FACTOR_SRC_ALPHA;
  303. case BF_INV_DEST_ALPHA:
  304. return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
  305. case BF_INV_SOURCE_ALPHA:
  306. return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
  307. }
  308. // Unsupported type
  309. return VK_BLEND_FACTOR_ZERO;
  310. }
  311. VkBlendOp VulkanUtility::getBlendOp(BlendOperation op)
  312. {
  313. switch (op)
  314. {
  315. case BO_ADD:
  316. return VK_BLEND_OP_ADD;
  317. case BO_SUBTRACT:
  318. return VK_BLEND_OP_SUBTRACT;
  319. case BO_REVERSE_SUBTRACT:
  320. return VK_BLEND_OP_REVERSE_SUBTRACT;
  321. case BO_MIN:
  322. return VK_BLEND_OP_MIN;
  323. case BO_MAX:
  324. return VK_BLEND_OP_MAX;
  325. }
  326. // Unsupported type
  327. return VK_BLEND_OP_ADD;
  328. }
  329. VkCompareOp VulkanUtility::getCompareOp(CompareFunction op)
  330. {
  331. switch (op)
  332. {
  333. case CMPF_ALWAYS_FAIL:
  334. return VK_COMPARE_OP_NEVER;
  335. case CMPF_ALWAYS_PASS:
  336. return VK_COMPARE_OP_ALWAYS;
  337. case CMPF_LESS:
  338. return VK_COMPARE_OP_LESS;
  339. case CMPF_LESS_EQUAL:
  340. return VK_COMPARE_OP_LESS_OR_EQUAL;
  341. case CMPF_EQUAL:
  342. return VK_COMPARE_OP_EQUAL;
  343. case CMPF_NOT_EQUAL:
  344. return VK_COMPARE_OP_NOT_EQUAL;
  345. case CMPF_GREATER_EQUAL:
  346. return VK_COMPARE_OP_GREATER_OR_EQUAL;
  347. case CMPF_GREATER:
  348. return VK_COMPARE_OP_GREATER;
  349. };
  350. // Unsupported type
  351. return VK_COMPARE_OP_ALWAYS;
  352. }
  353. VkCullModeFlagBits VulkanUtility::getCullMode(CullingMode mode)
  354. {
  355. switch (mode)
  356. {
  357. case CULL_NONE:
  358. return VK_CULL_MODE_NONE;
  359. case CULL_CLOCKWISE:
  360. return VK_CULL_MODE_FRONT_BIT;
  361. case CULL_COUNTERCLOCKWISE:
  362. return VK_CULL_MODE_BACK_BIT;
  363. }
  364. // Unsupported type
  365. return VK_CULL_MODE_NONE;
  366. }
  367. VkPolygonMode VulkanUtility::getPolygonMode(PolygonMode mode)
  368. {
  369. switch (mode)
  370. {
  371. case PM_WIREFRAME:
  372. return VK_POLYGON_MODE_LINE;
  373. case PM_SOLID:
  374. return VK_POLYGON_MODE_FILL;
  375. }
  376. return VK_POLYGON_MODE_FILL;
  377. }
  378. VkStencilOp VulkanUtility::getStencilOp(StencilOperation op)
  379. {
  380. switch (op)
  381. {
  382. case SOP_KEEP:
  383. return VK_STENCIL_OP_KEEP;
  384. case SOP_ZERO:
  385. return VK_STENCIL_OP_ZERO;
  386. case SOP_REPLACE:
  387. return VK_STENCIL_OP_REPLACE;
  388. case SOP_INCREMENT:
  389. return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
  390. case SOP_DECREMENT:
  391. return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
  392. case SOP_INCREMENT_WRAP:
  393. return VK_STENCIL_OP_INCREMENT_AND_WRAP;
  394. case SOP_DECREMENT_WRAP:
  395. return VK_STENCIL_OP_DECREMENT_AND_WRAP;
  396. case SOP_INVERT:
  397. return VK_STENCIL_OP_INVERT;
  398. }
  399. // Unsupported type
  400. return VK_STENCIL_OP_KEEP;
  401. }
  402. VkIndexType VulkanUtility::getIndexType(IndexType op)
  403. {
  404. switch(op)
  405. {
  406. case IT_16BIT:
  407. return VK_INDEX_TYPE_UINT16;
  408. case IT_32BIT:
  409. return VK_INDEX_TYPE_UINT32;
  410. }
  411. // Unsupported type
  412. return VK_INDEX_TYPE_UINT32;
  413. }
  414. VkPrimitiveTopology VulkanUtility::getDrawOp(DrawOperationType op)
  415. {
  416. switch (op)
  417. {
  418. case DOT_POINT_LIST:
  419. return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
  420. case DOT_LINE_LIST:
  421. return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
  422. case DOT_LINE_STRIP:
  423. return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
  424. case DOT_TRIANGLE_LIST:
  425. return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
  426. case DOT_TRIANGLE_STRIP:
  427. return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
  428. case DOT_TRIANGLE_FAN:
  429. return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
  430. }
  431. // Unsupported type
  432. return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
  433. }
  434. VkFilter VulkanUtility::getFilter(FilterOptions filter)
  435. {
  436. switch(filter)
  437. {
  438. case FO_LINEAR:
  439. case FO_ANISOTROPIC:
  440. return VK_FILTER_LINEAR;
  441. case FO_POINT:
  442. case FO_NONE:
  443. return VK_FILTER_NEAREST;
  444. }
  445. // Unsupported type
  446. return VK_FILTER_LINEAR;
  447. }
  448. VkSamplerMipmapMode VulkanUtility::getMipFilter(FilterOptions filter)
  449. {
  450. switch (filter)
  451. {
  452. case FO_LINEAR:
  453. case FO_ANISOTROPIC:
  454. return VK_SAMPLER_MIPMAP_MODE_LINEAR;
  455. case FO_POINT:
  456. case FO_NONE:
  457. return VK_SAMPLER_MIPMAP_MODE_NEAREST;
  458. }
  459. // Unsupported type
  460. return VK_SAMPLER_MIPMAP_MODE_LINEAR;
  461. }
  462. void VulkanUtility::getDevices(const VulkanRenderAPI& rapi, GpuDeviceFlags flags, VulkanDevice*(&devices)[BS_MAX_DEVICES])
  463. {
  464. UINT32 numDevices = rapi._getNumDevices();
  465. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  466. {
  467. if(i >= numDevices)
  468. {
  469. devices[i] = nullptr;
  470. continue;
  471. }
  472. VulkanDevice* device = rapi._getDevice(i).get();
  473. if (isDeviceIdxSet(rapi, i, flags))
  474. devices[i] = device;
  475. else
  476. devices[i] = nullptr;
  477. }
  478. }
  479. bool VulkanUtility::isDeviceIdxSet(const VulkanRenderAPI& rapi, UINT32 idx, GpuDeviceFlags flags)
  480. {
  481. VulkanDevice* device = rapi._getDevice(idx).get();
  482. return ((flags & (1 << idx)) != 0 || (flags == GDF_DEFAULT && device->isPrimary()));
  483. }
  484. void cutHorizontal(const VkImageSubresourceRange& toCut, const VkImageSubresourceRange& cutWith,
  485. VkImageSubresourceRange* output, UINT32& numAreas)
  486. {
  487. numAreas = 0;
  488. INT32 leftCut = cutWith.baseArrayLayer - toCut.baseArrayLayer;
  489. INT32 rightCut = (cutWith.baseArrayLayer + cutWith.layerCount) - toCut.baseArrayLayer;
  490. if (leftCut > 0 && leftCut < (INT32)(toCut.baseArrayLayer + toCut.layerCount))
  491. {
  492. output[numAreas] = toCut;
  493. VkImageSubresourceRange& range = output[numAreas];
  494. range.baseArrayLayer = toCut.baseArrayLayer;
  495. range.layerCount = leftCut;
  496. numAreas++;
  497. }
  498. if (rightCut > 0 && rightCut < (INT32)toCut.layerCount)
  499. {
  500. output[numAreas] = toCut;
  501. VkImageSubresourceRange& range = output[numAreas];
  502. range.baseArrayLayer = toCut.baseArrayLayer + rightCut;
  503. range.layerCount = toCut.layerCount - rightCut;
  504. numAreas++;
  505. }
  506. // If we made both left and right cuts, this means we need a middle one as well
  507. if (numAreas == 2)
  508. {
  509. output[numAreas] = toCut;
  510. VkImageSubresourceRange& range = output[numAreas];
  511. range.baseArrayLayer = toCut.baseArrayLayer + leftCut;
  512. range.layerCount = toCut.layerCount - (toCut.layerCount - rightCut) - leftCut;
  513. numAreas++;
  514. }
  515. // Nothing to cut
  516. if (numAreas == 0)
  517. {
  518. output[numAreas] = toCut;
  519. numAreas++;
  520. }
  521. }
  522. void cutVertical(const VkImageSubresourceRange& toCut, const VkImageSubresourceRange& cutWith,
  523. VkImageSubresourceRange* output, UINT32& numAreas)
  524. {
  525. numAreas = 0;
  526. INT32 topCut = cutWith.baseMipLevel - toCut.baseMipLevel;
  527. INT32 bottomCut = (cutWith.baseMipLevel + cutWith.levelCount) - toCut.baseMipLevel;
  528. if (topCut > 0 && topCut < (INT32)(toCut.baseMipLevel + toCut.levelCount))
  529. {
  530. output[numAreas] = toCut;
  531. VkImageSubresourceRange& range = output[numAreas];
  532. range.baseMipLevel = toCut.baseMipLevel;
  533. range.levelCount = topCut;
  534. numAreas++;
  535. }
  536. if (bottomCut > 0 && bottomCut < (INT32)toCut.levelCount)
  537. {
  538. output[numAreas] = toCut;
  539. VkImageSubresourceRange& range = output[numAreas];
  540. range.baseMipLevel = toCut.baseMipLevel + bottomCut;
  541. range.levelCount = toCut.levelCount - bottomCut;
  542. numAreas++;
  543. }
  544. // If we made both top and bottom cuts, this means we need a middle one as well
  545. if (numAreas == 2)
  546. {
  547. output[numAreas] = toCut;
  548. VkImageSubresourceRange& range = output[numAreas];
  549. range.baseMipLevel = toCut.baseMipLevel + topCut;
  550. range.levelCount = toCut.levelCount - (toCut.levelCount - bottomCut) - topCut;
  551. numAreas++;
  552. }
  553. // Nothing to cut
  554. if (numAreas == 0)
  555. {
  556. output[numAreas] = toCut;
  557. numAreas++;
  558. }
  559. }
  560. void VulkanUtility::cutRange(const VkImageSubresourceRange& toCut, const VkImageSubresourceRange& cutWith,
  561. std::array<VkImageSubresourceRange, 5>& output, UINT32& numAreas)
  562. {
  563. numAreas = 0;
  564. // Cut horizontally
  565. UINT32 numHorzCuts = 0;
  566. std::array<VkImageSubresourceRange, 3> horzCuts;
  567. cutHorizontal(toCut, cutWith, horzCuts.data(), numHorzCuts);
  568. // Cut vertically
  569. for (UINT32 i = 0; i < numHorzCuts; i++)
  570. {
  571. VkImageSubresourceRange& range = horzCuts[i];
  572. if (range.baseArrayLayer >= cutWith.baseArrayLayer &&
  573. (range.baseArrayLayer + range.layerCount) <= (cutWith.baseArrayLayer + cutWith.layerCount))
  574. {
  575. UINT32 numVertCuts = 0;
  576. cutVertical(range, cutWith, output.data() + numAreas, numVertCuts);
  577. numAreas += numVertCuts;
  578. }
  579. else
  580. {
  581. output[numAreas] = range;
  582. numAreas++;
  583. }
  584. }
  585. assert(numAreas <= 5);
  586. }
  587. bool VulkanUtility::rangeOverlaps(const VkImageSubresourceRange& a, const VkImageSubresourceRange& b)
  588. {
  589. INT32 aRight = a.baseArrayLayer + (INT32)a.layerCount;
  590. INT32 bRight = b.baseArrayLayer + (INT32)b.layerCount;
  591. INT32 aBottom = a.baseMipLevel + (INT32)a.levelCount;
  592. INT32 bBottom = b.baseMipLevel + (INT32)b.levelCount;
  593. if ((INT32)a.baseArrayLayer < bRight && aRight >(INT32)b.baseArrayLayer &&
  594. (INT32)a.baseMipLevel < bBottom && aBottom >(INT32)b.baseMipLevel)
  595. return true;
  596. return false;
  597. }
  598. }}