TextureImpl.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. // Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Gr/Vulkan/TextureImpl.h>
  6. #include <AnKi/Gr/Sampler.h>
  7. #include <AnKi/Gr/GrManager.h>
  8. #include <AnKi/Gr/Vulkan/GrManagerImpl.h>
  9. #include <AnKi/Gr/CommandBuffer.h>
  10. #include <AnKi/Gr/Vulkan/CommandBufferImpl.h>
  11. #include <AnKi/Gr/Utils/Functions.h>
  12. namespace anki {
  13. static Bool isAstcLdrFormat(const VkFormat format)
  14. {
  15. return format >= VK_FORMAT_ASTC_4x4_UNORM_BLOCK && format <= VK_FORMAT_ASTC_12x12_SRGB_BLOCK;
  16. }
  17. static Bool isAstcSrgbFormat(const VkFormat format)
  18. {
  19. switch(format)
  20. {
  21. case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
  22. case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
  23. case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
  24. case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
  25. case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
  26. case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
  27. case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
  28. case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
  29. case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
  30. case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
  31. case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
  32. case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
  33. case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
  34. case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
  35. return true;
  36. default:
  37. return false;
  38. }
  39. }
  40. U32 MicroImageView::getOrCreateBindlessIndex(GrManagerImpl& gr) const
  41. {
  42. LockGuard<SpinLock> lock(m_bindlessIndexLock);
  43. U32 outIdx;
  44. if(m_bindlessIndex != kMaxU32)
  45. {
  46. outIdx = m_bindlessIndex;
  47. }
  48. else
  49. {
  50. // Needs binding to the bindless descriptor set
  51. outIdx = gr.getDescriptorSetFactory().bindBindlessTexture(m_handle, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
  52. m_bindlessIndex = outIdx;
  53. }
  54. return outIdx;
  55. }
  56. TextureImpl::~TextureImpl()
  57. {
  58. #if ANKI_ASSERTIONS_ENABLED
  59. if(m_usage != m_usedFor)
  60. {
  61. ANKI_VK_LOGW("Texture %s hasn't been used in all types of usages", getName().cstr());
  62. }
  63. #endif
  64. TextureGarbage* garbage = anki::newInstance<TextureGarbage>(GrMemoryPool::getSingleton());
  65. for(MicroImageView& it : m_viewsMap)
  66. {
  67. garbage->m_viewHandles.emplaceBack(it.m_handle);
  68. it.m_handle = VK_NULL_HANDLE;
  69. if(it.m_bindlessIndex != kMaxU32)
  70. {
  71. garbage->m_bindlessIndices.emplaceBack(it.m_bindlessIndex);
  72. it.m_bindlessIndex = kMaxU32;
  73. }
  74. }
  75. m_viewsMap.destroy();
  76. if(m_singleSurfaceImageView.m_handle != VK_NULL_HANDLE)
  77. {
  78. garbage->m_viewHandles.emplaceBack(m_singleSurfaceImageView.m_handle);
  79. m_singleSurfaceImageView.m_handle = VK_NULL_HANDLE;
  80. if(m_singleSurfaceImageView.m_bindlessIndex != kMaxU32)
  81. {
  82. garbage->m_bindlessIndices.emplaceBack(m_singleSurfaceImageView.m_bindlessIndex);
  83. m_singleSurfaceImageView.m_bindlessIndex = kMaxU32;
  84. }
  85. }
  86. if(m_imageHandle && !(m_usage & TextureUsageBit::kPresent))
  87. {
  88. garbage->m_imageHandle = m_imageHandle;
  89. }
  90. garbage->m_memoryHandle = m_memHandle;
  91. getGrManagerImpl().getFrameGarbageCollector().newTextureGarbage(garbage);
  92. }
  93. Error TextureImpl::initInternal(VkImage externalImage, const TextureInitInfo& init_)
  94. {
  95. TextureInitInfo init = init_;
  96. ANKI_ASSERT(init.isValid());
  97. if(externalImage)
  98. {
  99. ANKI_ASSERT(!!(init.m_usage & TextureUsageBit::kPresent));
  100. }
  101. ANKI_ASSERT(getGrManagerImpl().getDeviceCapabilities().m_vrs || !(init.m_usage & TextureUsageBit::kFramebufferShadingRate));
  102. // Set some stuff
  103. m_width = init.m_width;
  104. m_height = init.m_height;
  105. m_depth = init.m_depth;
  106. m_texType = init.m_type;
  107. if(m_texType == TextureType::k3D)
  108. {
  109. m_mipCount = min<U32>(init.m_mipmapCount, computeMaxMipmapCount3d(m_width, m_height, m_depth));
  110. }
  111. else
  112. {
  113. m_mipCount = min<U32>(init.m_mipmapCount, computeMaxMipmapCount2d(m_width, m_height));
  114. }
  115. init.m_mipmapCount = U8(m_mipCount);
  116. m_layerCount = init.m_layerCount;
  117. m_format = init.m_format;
  118. m_vkFormat = convertFormat(m_format);
  119. m_aspect = getImageAspectFromFormat(m_format);
  120. m_usage = init.m_usage;
  121. if(externalImage)
  122. {
  123. m_imageHandle = externalImage;
  124. }
  125. else
  126. {
  127. ANKI_CHECK(initImage(init));
  128. }
  129. // Init the template
  130. zeroMemory(m_viewCreateInfoTemplate); // zero it, it will be used for hashing
  131. m_viewCreateInfoTemplate.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  132. m_viewCreateInfoTemplate.image = m_imageHandle;
  133. m_viewCreateInfoTemplate.viewType = convertTextureViewType(init.m_type);
  134. m_viewCreateInfoTemplate.format = m_vkFormat;
  135. m_viewCreateInfoTemplate.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  136. m_viewCreateInfoTemplate.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  137. m_viewCreateInfoTemplate.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  138. m_viewCreateInfoTemplate.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  139. m_viewCreateInfoTemplate.subresourceRange.aspectMask = convertImageAspect(m_aspect);
  140. m_viewCreateInfoTemplate.subresourceRange.baseArrayLayer = 0;
  141. m_viewCreateInfoTemplate.subresourceRange.baseMipLevel = 0;
  142. m_viewCreateInfoTemplate.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
  143. m_viewCreateInfoTemplate.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
  144. if(!!(getGrManagerImpl().getExtensions() & VulkanExtensions::kEXT_astc_decode_mode) && isAstcLdrFormat(m_vkFormat)
  145. && !isAstcSrgbFormat(m_vkFormat))
  146. {
  147. m_astcDecodeMode = {};
  148. m_astcDecodeMode.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT;
  149. m_astcDecodeMode.decodeMode = VK_FORMAT_R8G8B8A8_UNORM;
  150. m_viewCreateInfoTemplate.pNext = &m_astcDecodeMode;
  151. }
  152. // Create a view if the texture is a single surface
  153. if(m_texType == TextureType::k2D && m_mipCount == 1 && m_aspect == DepthStencilAspectBit::kNone)
  154. {
  155. VkImageViewCreateInfo viewCi;
  156. TextureSubresourceInfo subresource;
  157. computeVkImageViewCreateInfo(subresource, viewCi, m_singleSurfaceImageView.m_derivedTextureType);
  158. ANKI_ASSERT(m_singleSurfaceImageView.m_derivedTextureType == m_texType);
  159. ANKI_VK_CHECKF(vkCreateImageView(getVkDevice(), &viewCi, nullptr, &m_singleSurfaceImageView.m_handle));
  160. getGrManagerImpl().trySetVulkanHandleName(getName(), VK_OBJECT_TYPE_IMAGE_VIEW, ptrToNumber(m_singleSurfaceImageView.m_handle));
  161. }
  162. return Error::kNone;
  163. }
  164. VkImageCreateFlags TextureImpl::calcCreateFlags(const TextureInitInfo& init)
  165. {
  166. VkImageCreateFlags flags = 0;
  167. if(init.m_type == TextureType::kCube || init.m_type == TextureType::kCubeArray)
  168. {
  169. flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
  170. }
  171. return flags;
  172. }
  173. Bool TextureImpl::imageSupported(const TextureInitInfo& init)
  174. {
  175. VkImageFormatProperties props = {};
  176. const VkResult res = vkGetPhysicalDeviceImageFormatProperties(getGrManagerImpl().getPhysicalDevice(), m_vkFormat, convertTextureType(init.m_type),
  177. VK_IMAGE_TILING_OPTIMAL, convertTextureUsage(init.m_usage, init.m_format),
  178. calcCreateFlags(init), &props);
  179. if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
  180. {
  181. return false;
  182. }
  183. else
  184. {
  185. ANKI_ASSERT(res == VK_SUCCESS);
  186. return true;
  187. }
  188. }
  189. Error TextureImpl::initImage(const TextureInitInfo& init)
  190. {
  191. // Check if format is supported
  192. if(!imageSupported(init))
  193. {
  194. ANKI_VK_LOGE("TextureInitInfo contains a combination of parameters that it's not supported by the device. "
  195. "Texture format is %s",
  196. getFormatInfo(init.m_format).m_name);
  197. return Error::kFunctionFailed;
  198. }
  199. // Contunue with the creation
  200. VkImageCreateInfo ci = {};
  201. ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  202. ci.flags = calcCreateFlags(init);
  203. ci.imageType = convertTextureType(m_texType);
  204. ci.format = m_vkFormat;
  205. ci.extent.width = init.m_width;
  206. ci.extent.height = init.m_height;
  207. switch(m_texType)
  208. {
  209. case TextureType::k1D:
  210. case TextureType::k2D:
  211. ci.extent.depth = 1;
  212. ci.arrayLayers = 1;
  213. break;
  214. case TextureType::k2DArray:
  215. ci.extent.depth = 1;
  216. ci.arrayLayers = init.m_layerCount;
  217. break;
  218. case TextureType::kCube:
  219. ci.extent.depth = 1;
  220. ci.arrayLayers = 6;
  221. break;
  222. case TextureType::kCubeArray:
  223. ci.extent.depth = 1;
  224. ci.arrayLayers = 6 * init.m_layerCount;
  225. break;
  226. case TextureType::k3D:
  227. ci.extent.depth = init.m_depth;
  228. ci.arrayLayers = 1;
  229. break;
  230. default:
  231. ANKI_ASSERT(0);
  232. }
  233. ci.mipLevels = m_mipCount;
  234. ci.samples = VK_SAMPLE_COUNT_1_BIT;
  235. ci.tiling = VK_IMAGE_TILING_OPTIMAL;
  236. ci.usage = convertTextureUsage(init.m_usage, init.m_format);
  237. m_vkUsageFlags = ci.usage;
  238. ci.queueFamilyIndexCount = getGrManagerImpl().getQueueFamilies().getSize();
  239. ci.pQueueFamilyIndices = &getGrManagerImpl().getQueueFamilies()[0];
  240. ci.sharingMode = (ci.queueFamilyIndexCount > 1) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
  241. ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  242. ANKI_VK_CHECK(vkCreateImage(getVkDevice(), &ci, nullptr, &m_imageHandle));
  243. getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_OBJECT_TYPE_IMAGE, m_imageHandle);
  244. #if 0
  245. printf("Creating texture %p %s\n", static_cast<void*>(m_imageHandle),
  246. init.getName() ? init.getName().cstr() : "Unnamed");
  247. #endif
  248. // Allocate memory
  249. //
  250. VkMemoryDedicatedRequirementsKHR dedicatedRequirements = {};
  251. dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR;
  252. VkMemoryRequirements2 requirements = {};
  253. requirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
  254. requirements.pNext = &dedicatedRequirements;
  255. VkImageMemoryRequirementsInfo2 imageRequirementsInfo = {};
  256. imageRequirementsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
  257. imageRequirementsInfo.image = m_imageHandle;
  258. vkGetImageMemoryRequirements2(getVkDevice(), &imageRequirementsInfo, &requirements);
  259. U32 memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(requirements.memoryRequirements.memoryTypeBits,
  260. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
  261. // Fallback
  262. if(memIdx == kMaxU32)
  263. {
  264. memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(requirements.memoryRequirements.memoryTypeBits,
  265. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0);
  266. }
  267. ANKI_ASSERT(memIdx != kMaxU32);
  268. // Allocate
  269. if(!dedicatedRequirements.prefersDedicatedAllocation)
  270. {
  271. getGrManagerImpl().getGpuMemoryManager().allocateMemory(memIdx, requirements.memoryRequirements.size,
  272. U32(requirements.memoryRequirements.alignment), m_memHandle);
  273. }
  274. else
  275. {
  276. getGrManagerImpl().getGpuMemoryManager().allocateMemoryDedicated(memIdx, requirements.memoryRequirements.size, m_imageHandle, m_memHandle);
  277. }
  278. // Bind
  279. ANKI_VK_CHECK(vkBindImageMemory(getVkDevice(), m_imageHandle, m_memHandle.m_memory, m_memHandle.m_offset));
  280. return Error::kNone;
  281. }
  282. void TextureImpl::computeBarrierInfo(TextureUsageBit usage, Bool src, U32 level, VkPipelineStageFlags& stages, VkAccessFlags& accesses) const
  283. {
  284. ANKI_ASSERT(level < m_mipCount);
  285. ANKI_ASSERT(usageValid(usage));
  286. stages = 0;
  287. accesses = 0;
  288. const Bool depthStencil = !!m_aspect;
  289. if(!!(usage & (TextureUsageBit::kSampledGeometry | TextureUsageBit::kUavGeometryRead)))
  290. {
  291. stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
  292. | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
  293. accesses |= VK_ACCESS_SHADER_READ_BIT;
  294. }
  295. if(!!(usage & TextureUsageBit::kUavGeometryWrite))
  296. {
  297. stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
  298. | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
  299. accesses |= VK_ACCESS_SHADER_WRITE_BIT;
  300. }
  301. if(!!(usage & (TextureUsageBit::kSampledFragment | TextureUsageBit::kUavFragmentRead)))
  302. {
  303. stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  304. accesses |= VK_ACCESS_SHADER_READ_BIT;
  305. }
  306. if(!!(usage & TextureUsageBit::kUavFragmentWrite))
  307. {
  308. stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  309. accesses |= VK_ACCESS_SHADER_WRITE_BIT;
  310. }
  311. if(!!(usage & (TextureUsageBit::kSampledCompute | TextureUsageBit::kUavComputeRead)))
  312. {
  313. stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  314. accesses |= VK_ACCESS_SHADER_READ_BIT;
  315. }
  316. if(!!(usage & TextureUsageBit::kUavComputeWrite))
  317. {
  318. stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  319. accesses |= VK_ACCESS_SHADER_WRITE_BIT;
  320. }
  321. if(!!(usage & (TextureUsageBit::kSampledTraceRays | TextureUsageBit::kUavTraceRaysRead)))
  322. {
  323. stages |= VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
  324. accesses |= VK_ACCESS_SHADER_READ_BIT;
  325. }
  326. if(!!(usage & TextureUsageBit::kUavTraceRaysWrite))
  327. {
  328. stages |= VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
  329. accesses |= VK_ACCESS_SHADER_WRITE_BIT;
  330. }
  331. if(!!(usage & TextureUsageBit::kFramebufferRead))
  332. {
  333. if(depthStencil)
  334. {
  335. stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
  336. accesses |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
  337. }
  338. else
  339. {
  340. stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  341. accesses |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
  342. }
  343. }
  344. if(!!(usage & TextureUsageBit::kFramebufferWrite))
  345. {
  346. if(depthStencil)
  347. {
  348. stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
  349. accesses |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  350. }
  351. else
  352. {
  353. stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  354. accesses |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  355. }
  356. }
  357. if(!!(usage & TextureUsageBit::kFramebufferShadingRate))
  358. {
  359. stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
  360. accesses |= VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
  361. }
  362. if(!!(usage & TextureUsageBit::kGenerateMipmaps))
  363. {
  364. stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
  365. if(src)
  366. {
  367. const Bool lastLevel = level == m_mipCount - 1;
  368. if(lastLevel)
  369. {
  370. accesses |= VK_ACCESS_TRANSFER_WRITE_BIT;
  371. }
  372. else
  373. {
  374. accesses |= VK_ACCESS_TRANSFER_READ_BIT;
  375. }
  376. }
  377. else
  378. {
  379. ANKI_ASSERT(level == 0
  380. && "The upper layers should not allow others levels to transition to gen mips state. This "
  381. "happens elsewhere");
  382. accesses |= VK_ACCESS_TRANSFER_READ_BIT;
  383. }
  384. }
  385. if(!!(usage & TextureUsageBit::kTransferDestination))
  386. {
  387. stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
  388. accesses |= VK_ACCESS_TRANSFER_WRITE_BIT;
  389. }
  390. if(!!(usage & TextureUsageBit::kPresent))
  391. {
  392. stages |= VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  393. accesses |= VK_ACCESS_MEMORY_READ_BIT;
  394. }
  395. }
  396. void TextureImpl::computeBarrierInfo(TextureUsageBit before, TextureUsageBit after, U32 level, VkPipelineStageFlags& srcStages,
  397. VkAccessFlags& srcAccesses, VkPipelineStageFlags& dstStages, VkAccessFlags& dstAccesses) const
  398. {
  399. computeBarrierInfo(before, true, level, srcStages, srcAccesses);
  400. computeBarrierInfo(after, false, level, dstStages, dstAccesses);
  401. if(srcStages == 0)
  402. {
  403. srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
  404. }
  405. ANKI_ASSERT(dstStages);
  406. }
  407. VkImageLayout TextureImpl::computeLayout(TextureUsageBit usage, U level) const
  408. {
  409. ANKI_ASSERT(level < m_mipCount);
  410. ANKI_ASSERT(usageValid(usage));
  411. VkImageLayout out = VK_IMAGE_LAYOUT_MAX_ENUM;
  412. const Bool lastLevel = level == m_mipCount - 1u;
  413. const Bool depthStencil = !!m_aspect;
  414. if(usage == TextureUsageBit::kNone)
  415. {
  416. out = VK_IMAGE_LAYOUT_UNDEFINED;
  417. }
  418. else if(depthStencil)
  419. {
  420. if(!(usage & ~(TextureUsageBit::kAllSampled | TextureUsageBit::kFramebufferRead)))
  421. {
  422. // Only depth tests and sampled
  423. out = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
  424. }
  425. else
  426. {
  427. // Only attachment write, the rest (eg transfer) are not supported for now
  428. ANKI_ASSERT(usage == TextureUsageBit::kFramebufferWrite || usage == TextureUsageBit::kAllFramebuffer);
  429. out = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  430. }
  431. }
  432. else if(!(usage & ~TextureUsageBit::kAllFramebuffer))
  433. {
  434. // Color attachment
  435. out = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  436. }
  437. else if(!(usage & ~TextureUsageBit::kFramebufferShadingRate))
  438. {
  439. // SRI
  440. out = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
  441. }
  442. else if(!(usage & ~TextureUsageBit::kAllUav))
  443. {
  444. // Only image load/store
  445. out = VK_IMAGE_LAYOUT_GENERAL;
  446. }
  447. else if(!(usage & ~TextureUsageBit::kAllSampled))
  448. {
  449. // Only sampled
  450. out = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  451. }
  452. else if(usage == TextureUsageBit::kGenerateMipmaps)
  453. {
  454. if(!lastLevel)
  455. {
  456. out = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
  457. }
  458. else
  459. {
  460. out = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  461. }
  462. }
  463. else if(usage == TextureUsageBit::kTransferDestination)
  464. {
  465. out = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  466. }
  467. else if(usage == TextureUsageBit::kPresent)
  468. {
  469. out = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  470. }
  471. else
  472. {
  473. // No idea so play it safe
  474. out = VK_IMAGE_LAYOUT_GENERAL;
  475. }
  476. return out;
  477. }
  478. const MicroImageView& TextureImpl::getOrCreateView(const TextureSubresourceInfo& subresource) const
  479. {
  480. if(m_singleSurfaceImageView.m_handle != VK_NULL_HANDLE)
  481. {
  482. return m_singleSurfaceImageView;
  483. }
  484. {
  485. RLockGuard<RWMutex> lock(m_viewsMapMtx);
  486. auto it = m_viewsMap.find(subresource);
  487. if(it != m_viewsMap.getEnd())
  488. {
  489. return *it;
  490. }
  491. }
  492. // Not found need to create it
  493. WLockGuard<RWMutex> lock(m_viewsMapMtx);
  494. // Search again
  495. auto it = m_viewsMap.find(subresource);
  496. if(it != m_viewsMap.getEnd())
  497. {
  498. return *it;
  499. }
  500. // Not found in the 2nd search, create it
  501. VkImageView handle = VK_NULL_HANDLE;
  502. TextureType viewTexType = TextureType::kCount;
  503. // Compute the VkImageViewCreateInfo
  504. VkImageViewCreateInfo viewCi;
  505. computeVkImageViewCreateInfo(subresource, viewCi, viewTexType);
  506. ANKI_ASSERT(viewTexType != TextureType::kCount);
  507. ANKI_VK_CHECKF(vkCreateImageView(getVkDevice(), &viewCi, nullptr, &handle));
  508. getGrManagerImpl().trySetVulkanHandleName(getName(), VK_OBJECT_TYPE_IMAGE_VIEW, ptrToNumber(handle));
  509. it = m_viewsMap.emplace(subresource);
  510. it->m_handle = handle;
  511. it->m_derivedTextureType = viewTexType;
  512. #if 0
  513. printf("Creating image view %p. Texture %p %s\n", static_cast<void*>(handle), static_cast<void*>(m_imageHandle),
  514. getName() ? getName().cstr() : "Unnamed");
  515. #endif
  516. ANKI_ASSERT(&(*m_viewsMap.find(subresource)) == &(*it));
  517. return *it;
  518. }
  519. TextureType TextureImpl::computeNewTexTypeOfSubresource(const TextureSubresourceInfo& subresource) const
  520. {
  521. ANKI_ASSERT(isSubresourceValid(subresource));
  522. if(textureTypeIsCube(m_texType))
  523. {
  524. if(subresource.m_faceCount != 6)
  525. {
  526. ANKI_ASSERT(subresource.m_faceCount == 1);
  527. return (subresource.m_layerCount > 1) ? TextureType::k2DArray : TextureType::k2D;
  528. }
  529. else if(subresource.m_layerCount == 1)
  530. {
  531. return TextureType::kCube;
  532. }
  533. }
  534. return m_texType;
  535. }
  536. } // end namespace anki