TextureImpl.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. // Copyright (C) 2009-2021, 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. {
  14. U32 MicroImageView::getOrCreateBindlessIndex(VkImageLayout layout, GrManagerImpl& gr) const
  15. {
  16. ANKI_ASSERT(layout == VK_IMAGE_LAYOUT_GENERAL || layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
  17. const U32 arrayIdx = (layout == VK_IMAGE_LAYOUT_GENERAL) ? 1 : 0;
  18. LockGuard<SpinLock> lock(m_lock);
  19. U32 outIdx;
  20. if(m_bindlessIndices[arrayIdx] != MAX_U32)
  21. {
  22. outIdx = m_bindlessIndices[arrayIdx];
  23. }
  24. else
  25. {
  26. // Needs binding to the bindless descriptor set
  27. if(layout == VK_IMAGE_LAYOUT_GENERAL)
  28. {
  29. outIdx = gr.getDescriptorSetFactory().bindBindlessImage(m_handle);
  30. }
  31. else
  32. {
  33. outIdx = gr.getDescriptorSetFactory().bindBindlessTexture(m_handle, layout);
  34. }
  35. m_bindlessIndices[arrayIdx] = outIdx;
  36. }
  37. return outIdx;
  38. }
  39. TextureImpl::~TextureImpl()
  40. {
  41. #if ANKI_ENABLE_ASSERTIONS
  42. if(m_usage != m_usedFor)
  43. {
  44. ANKI_VK_LOGW("Texture %s hasn't been used in all types of usages", getName().cstr());
  45. }
  46. #endif
  47. for(MicroImageView& it : m_viewsMap)
  48. {
  49. destroyMicroImageView(it);
  50. }
  51. m_viewsMap.destroy(getAllocator());
  52. if(m_singleSurfaceImageView.m_handle != VK_NULL_HANDLE)
  53. {
  54. destroyMicroImageView(m_singleSurfaceImageView);
  55. }
  56. if(m_imageHandle && !(m_usage & TextureUsageBit::PRESENT))
  57. {
  58. vkDestroyImage(getDevice(), m_imageHandle, nullptr);
  59. }
  60. if(m_memHandle)
  61. {
  62. getGrManagerImpl().getGpuMemoryManager().freeMemory(m_memHandle);
  63. }
  64. if(m_dedicatedMem)
  65. {
  66. vkFreeMemory(getDevice(), m_dedicatedMem, nullptr);
  67. }
  68. }
  69. Error TextureImpl::initInternal(VkImage externalImage, const TextureInitInfo& init_)
  70. {
  71. TextureInitInfo init = init_;
  72. ANKI_ASSERT(init.isValid());
  73. if(externalImage)
  74. {
  75. ANKI_ASSERT(!!(init.m_usage & TextureUsageBit::PRESENT));
  76. }
  77. // Set some stuff
  78. m_width = init.m_width;
  79. m_height = init.m_height;
  80. m_depth = init.m_depth;
  81. m_texType = init.m_type;
  82. if(m_texType == TextureType::_3D)
  83. {
  84. m_mipCount = min<U32>(init.m_mipmapCount, computeMaxMipmapCount3d(m_width, m_height, m_depth));
  85. }
  86. else
  87. {
  88. m_mipCount = min<U32>(init.m_mipmapCount, computeMaxMipmapCount2d(m_width, m_height));
  89. }
  90. init.m_mipmapCount = U8(m_mipCount);
  91. m_layerCount = init.m_layerCount;
  92. m_format = init.m_format;
  93. m_vkFormat = convertFormat(m_format);
  94. m_aspect = getImageAspectFromFormat(m_format);
  95. m_usage = init.m_usage;
  96. if(externalImage)
  97. {
  98. m_imageHandle = externalImage;
  99. }
  100. else
  101. {
  102. ANKI_CHECK(initImage(init));
  103. }
  104. // Init the template
  105. zeroMemory(m_viewCreateInfoTemplate); // zero it, it will be used for hashing
  106. m_viewCreateInfoTemplate.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  107. m_viewCreateInfoTemplate.image = m_imageHandle;
  108. m_viewCreateInfoTemplate.viewType = convertTextureViewType(init.m_type);
  109. m_viewCreateInfoTemplate.format = m_vkFormat;
  110. m_viewCreateInfoTemplate.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  111. m_viewCreateInfoTemplate.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  112. m_viewCreateInfoTemplate.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  113. m_viewCreateInfoTemplate.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  114. m_viewCreateInfoTemplate.subresourceRange.aspectMask = convertImageAspect(m_aspect);
  115. m_viewCreateInfoTemplate.subresourceRange.baseArrayLayer = 0;
  116. m_viewCreateInfoTemplate.subresourceRange.baseMipLevel = 0;
  117. m_viewCreateInfoTemplate.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
  118. m_viewCreateInfoTemplate.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
  119. // Transition the image layout from undefined to something relevant
  120. if(!!init.m_initialUsage)
  121. {
  122. ANKI_ASSERT(usageValid(init.m_initialUsage));
  123. ANKI_ASSERT(!(init.m_initialUsage & TextureUsageBit::GENERATE_MIPMAPS) && "That doesn't make any sense");
  124. CommandBufferInitInfo cmdbinit;
  125. cmdbinit.m_flags = CommandBufferFlag::GENERAL_WORK | CommandBufferFlag::SMALL_BATCH;
  126. CommandBufferPtr cmdb = getManager().newCommandBuffer(cmdbinit);
  127. VkImageSubresourceRange range;
  128. range.aspectMask = convertImageAspect(m_aspect);
  129. range.baseArrayLayer = 0;
  130. range.baseMipLevel = 0;
  131. range.layerCount = m_layerCount;
  132. range.levelCount = m_mipCount;
  133. CommandBufferImpl& cmdbImpl = static_cast<CommandBufferImpl&>(*cmdb);
  134. cmdbImpl.setTextureBarrierRange(TexturePtr(this), TextureUsageBit::NONE, init.m_initialUsage, range);
  135. cmdbImpl.endRecording();
  136. getGrManagerImpl().flushCommandBuffer(cmdbImpl.getMicroCommandBuffer(), false, {}, nullptr);
  137. }
  138. // Create a view if the texture is a single surface
  139. if(m_texType == TextureType::_2D && m_mipCount == 1 && m_aspect == DepthStencilAspectBit::NONE)
  140. {
  141. VkImageViewCreateInfo viewCi;
  142. TextureSubresourceInfo subresource;
  143. computeVkImageViewCreateInfo(subresource, viewCi, m_singleSurfaceImageView.m_derivedTextureType);
  144. ANKI_ASSERT(m_singleSurfaceImageView.m_derivedTextureType == m_texType);
  145. ANKI_VK_CHECKF(vkCreateImageView(getDevice(), &viewCi, nullptr, &m_singleSurfaceImageView.m_handle));
  146. getGrManagerImpl().trySetVulkanHandleName(getName(), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
  147. ptrToNumber(m_singleSurfaceImageView.m_handle));
  148. }
  149. return Error::NONE;
  150. }
  151. VkFormatFeatureFlags TextureImpl::calcFeatures(const TextureInitInfo& init)
  152. {
  153. VkFormatFeatureFlags flags = 0;
  154. if(init.m_mipmapCount > 1 && !!(init.m_usage & TextureUsageBit::GENERATE_MIPMAPS))
  155. {
  156. // May be used for mip gen.
  157. flags |= VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT;
  158. }
  159. if(!!(init.m_usage & TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT))
  160. {
  161. if(formatIsDepthStencil(init.m_format))
  162. {
  163. flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
  164. }
  165. else
  166. {
  167. flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
  168. }
  169. }
  170. if(!!(init.m_usage & TextureUsageBit::ALL_SAMPLED))
  171. {
  172. flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
  173. }
  174. ANKI_ASSERT(flags);
  175. return flags;
  176. }
  177. VkImageCreateFlags TextureImpl::calcCreateFlags(const TextureInitInfo& init)
  178. {
  179. VkImageCreateFlags flags = 0;
  180. if(init.m_type == TextureType::CUBE || init.m_type == TextureType::CUBE_ARRAY)
  181. {
  182. flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
  183. }
  184. return flags;
  185. }
  186. Bool TextureImpl::imageSupported(const TextureInitInfo& init)
  187. {
  188. VkImageFormatProperties props = {};
  189. VkResult res = vkGetPhysicalDeviceImageFormatProperties(
  190. getGrManagerImpl().getPhysicalDevice(), m_vkFormat, convertTextureType(init.m_type), VK_IMAGE_TILING_OPTIMAL,
  191. convertTextureUsage(init.m_usage, init.m_format), calcCreateFlags(init), &props);
  192. if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
  193. {
  194. return false;
  195. }
  196. else
  197. {
  198. ANKI_ASSERT(res == VK_SUCCESS);
  199. return true;
  200. }
  201. }
  202. Error TextureImpl::initImage(const TextureInitInfo& init_)
  203. {
  204. TextureInitInfo init = init_;
  205. // Check if format is supported
  206. Bool supported;
  207. while(!(supported = imageSupported(init)))
  208. {
  209. // Try to find a fallback
  210. if(init.m_format >= Format::R8G8B8_UNORM && init.m_format <= Format::R8G8B8_SRGB)
  211. {
  212. ANKI_ASSERT(!(init.m_usage & TextureUsageBit::ALL_IMAGE) && "Can't do that ATM");
  213. const U idx = U(init.m_format) - U(Format::R8G8B8_UNORM);
  214. init.m_format = Format(U(Format::R8G8B8A8_UNORM) + idx);
  215. ANKI_ASSERT(init.m_format >= Format::R8G8B8A8_UNORM && init.m_format <= Format::R8G8B8A8_SRGB);
  216. m_format = init.m_format;
  217. m_vkFormat = convertFormat(m_format);
  218. m_workarounds = TextureImplWorkaround::R8G8B8_TO_R8G8B8A8;
  219. }
  220. else if(init.m_format == Format::S8_UINT)
  221. {
  222. ANKI_ASSERT(!(init.m_usage & (TextureUsageBit::ALL_IMAGE | TextureUsageBit::ALL_TRANSFER))
  223. && "Can't do that ATM");
  224. init.m_format = Format::D24_UNORM_S8_UINT;
  225. m_format = init.m_format;
  226. m_vkFormat = convertFormat(m_format);
  227. m_workarounds = TextureImplWorkaround::S8_TO_D24S8;
  228. }
  229. else if(init.m_format == Format::D24_UNORM_S8_UINT)
  230. {
  231. ANKI_ASSERT(!(init.m_usage & (TextureUsageBit::ALL_IMAGE | TextureUsageBit::ALL_TRANSFER))
  232. && "Can't do that ATM");
  233. init.m_format = Format::D32_SFLOAT_S8_UINT;
  234. m_format = init.m_format;
  235. m_vkFormat = convertFormat(m_format);
  236. m_workarounds = TextureImplWorkaround::D24S8_TO_D32S8;
  237. }
  238. else
  239. {
  240. break;
  241. }
  242. }
  243. if(!supported)
  244. {
  245. ANKI_VK_LOGE("Unsupported texture format: %u", U32(init.m_format));
  246. return Error::FUNCTION_FAILED;
  247. }
  248. // Contunue with the creation
  249. VkImageCreateInfo ci = {};
  250. ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  251. ci.flags = calcCreateFlags(init);
  252. ci.imageType = convertTextureType(m_texType);
  253. ci.format = m_vkFormat;
  254. ci.extent.width = init.m_width;
  255. ci.extent.height = init.m_height;
  256. switch(m_texType)
  257. {
  258. case TextureType::_1D:
  259. case TextureType::_2D:
  260. ci.extent.depth = 1;
  261. ci.arrayLayers = 1;
  262. break;
  263. case TextureType::_2D_ARRAY:
  264. ci.extent.depth = 1;
  265. ci.arrayLayers = init.m_layerCount;
  266. break;
  267. case TextureType::CUBE:
  268. ci.extent.depth = 1;
  269. ci.arrayLayers = 6;
  270. break;
  271. case TextureType::CUBE_ARRAY:
  272. ci.extent.depth = 1;
  273. ci.arrayLayers = 6 * init.m_layerCount;
  274. break;
  275. case TextureType::_3D:
  276. ci.extent.depth = init.m_depth;
  277. ci.arrayLayers = 1;
  278. break;
  279. default:
  280. ANKI_ASSERT(0);
  281. }
  282. ci.mipLevels = m_mipCount;
  283. ci.samples = VK_SAMPLE_COUNT_1_BIT;
  284. ci.tiling = VK_IMAGE_TILING_OPTIMAL;
  285. ci.usage = convertTextureUsage(init.m_usage, init.m_format);
  286. ci.queueFamilyIndexCount = getGrManagerImpl().getQueueFamilies().getSize();
  287. ci.pQueueFamilyIndices = &getGrManagerImpl().getQueueFamilies()[0];
  288. ci.sharingMode = (ci.queueFamilyIndexCount > 1) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
  289. ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  290. ANKI_VK_CHECK(vkCreateImage(getDevice(), &ci, nullptr, &m_imageHandle));
  291. getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, m_imageHandle);
  292. #if 0
  293. printf("Creating texture %p %s\n", static_cast<void*>(m_imageHandle),
  294. init.getName() ? init.getName().cstr() : "Unnamed");
  295. #endif
  296. // Allocate memory
  297. //
  298. VkMemoryDedicatedRequirementsKHR dedicatedRequirements = {};
  299. dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR;
  300. VkMemoryRequirements2 requirements = {};
  301. requirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
  302. requirements.pNext = &dedicatedRequirements;
  303. VkImageMemoryRequirementsInfo2 imageRequirementsInfo = {};
  304. imageRequirementsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
  305. imageRequirementsInfo.image = m_imageHandle;
  306. vkGetImageMemoryRequirements2(getDevice(), &imageRequirementsInfo, &requirements);
  307. U32 memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(requirements.memoryRequirements.memoryTypeBits,
  308. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
  309. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
  310. // Fallback
  311. if(memIdx == MAX_U32)
  312. {
  313. memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(requirements.memoryRequirements.memoryTypeBits,
  314. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0);
  315. }
  316. ANKI_ASSERT(memIdx != MAX_U32);
  317. if(!dedicatedRequirements.prefersDedicatedAllocation)
  318. {
  319. // Allocate
  320. getGrManagerImpl().getGpuMemoryManager().allocateMemory(memIdx, requirements.memoryRequirements.size,
  321. U32(requirements.memoryRequirements.alignment), false,
  322. m_memHandle);
  323. // Bind mem to image
  324. ANKI_TRACE_SCOPED_EVENT(VK_BIND_OBJECT);
  325. ANKI_VK_CHECK(vkBindImageMemory(getDevice(), m_imageHandle, m_memHandle.m_memory, m_memHandle.m_offset));
  326. }
  327. else
  328. {
  329. VkMemoryDedicatedAllocateInfoKHR dedicatedInfo = {};
  330. dedicatedInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR;
  331. dedicatedInfo.image = m_imageHandle;
  332. VkMemoryAllocateInfo memoryAllocateInfo = {};
  333. memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  334. memoryAllocateInfo.pNext = &dedicatedInfo;
  335. memoryAllocateInfo.allocationSize = requirements.memoryRequirements.size;
  336. memoryAllocateInfo.memoryTypeIndex = memIdx;
  337. ANKI_VK_CHECK(vkAllocateMemory(getDevice(), &memoryAllocateInfo, nullptr, &m_dedicatedMem));
  338. getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
  339. ptrToNumber(m_dedicatedMem));
  340. ANKI_TRACE_SCOPED_EVENT(VK_BIND_OBJECT);
  341. ANKI_VK_CHECK(vkBindImageMemory(getDevice(), m_imageHandle, m_dedicatedMem, 0));
  342. }
  343. return Error::NONE;
  344. }
  345. void TextureImpl::computeBarrierInfo(TextureUsageBit usage, Bool src, U32 level, VkPipelineStageFlags& stages,
  346. VkAccessFlags& accesses) const
  347. {
  348. ANKI_ASSERT(level < m_mipCount);
  349. ANKI_ASSERT(usageValid(usage));
  350. stages = 0;
  351. accesses = 0;
  352. const Bool depthStencil = !!m_aspect;
  353. if(!!(usage & (TextureUsageBit::SAMPLED_GEOMETRY | TextureUsageBit::IMAGE_GEOMETRY_READ)))
  354. {
  355. stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
  356. | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
  357. accesses |= VK_ACCESS_SHADER_READ_BIT;
  358. }
  359. if(!!(usage & TextureUsageBit::IMAGE_GEOMETRY_WRITE))
  360. {
  361. stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
  362. | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
  363. accesses |= VK_ACCESS_SHADER_WRITE_BIT;
  364. }
  365. if(!!(usage & (TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::IMAGE_FRAGMENT_READ)))
  366. {
  367. stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  368. accesses |= VK_ACCESS_SHADER_READ_BIT;
  369. }
  370. if(!!(usage & TextureUsageBit::IMAGE_FRAGMENT_WRITE))
  371. {
  372. stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  373. accesses |= VK_ACCESS_SHADER_WRITE_BIT;
  374. }
  375. if(!!(usage & (TextureUsageBit::SAMPLED_COMPUTE | TextureUsageBit::IMAGE_COMPUTE_READ)))
  376. {
  377. stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  378. accesses |= VK_ACCESS_SHADER_READ_BIT;
  379. }
  380. if(!!(usage & TextureUsageBit::IMAGE_COMPUTE_WRITE))
  381. {
  382. stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  383. accesses |= VK_ACCESS_SHADER_WRITE_BIT;
  384. }
  385. if(!!(usage & (TextureUsageBit::SAMPLED_TRACE_RAYS | TextureUsageBit::IMAGE_TRACE_RAYS_READ)))
  386. {
  387. stages |= VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
  388. accesses |= VK_ACCESS_SHADER_READ_BIT;
  389. }
  390. if(!!(usage & TextureUsageBit::IMAGE_TRACE_RAYS_WRITE))
  391. {
  392. stages |= VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
  393. accesses |= VK_ACCESS_SHADER_WRITE_BIT;
  394. }
  395. if(!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ))
  396. {
  397. if(depthStencil)
  398. {
  399. stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
  400. accesses |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
  401. }
  402. else
  403. {
  404. stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  405. accesses |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
  406. }
  407. }
  408. if(!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE))
  409. {
  410. if(depthStencil)
  411. {
  412. stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
  413. accesses |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  414. }
  415. else
  416. {
  417. stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  418. accesses |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  419. }
  420. }
  421. if(!!(usage & TextureUsageBit::GENERATE_MIPMAPS))
  422. {
  423. stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
  424. if(src)
  425. {
  426. const Bool lastLevel = level == m_mipCount - 1;
  427. if(lastLevel)
  428. {
  429. accesses |= VK_ACCESS_TRANSFER_WRITE_BIT;
  430. }
  431. else
  432. {
  433. accesses |= VK_ACCESS_TRANSFER_READ_BIT;
  434. }
  435. }
  436. else
  437. {
  438. ANKI_ASSERT(level == 0
  439. && "The upper layers should not allow others levels to transition to gen mips state. This "
  440. "happens elsewhere");
  441. accesses |= VK_ACCESS_TRANSFER_READ_BIT;
  442. }
  443. }
  444. if(!!(usage & TextureUsageBit::TRANSFER_DESTINATION))
  445. {
  446. stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
  447. accesses |= VK_ACCESS_TRANSFER_WRITE_BIT;
  448. }
  449. if(!!(usage & TextureUsageBit::PRESENT))
  450. {
  451. stages |= VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  452. accesses |= VK_ACCESS_MEMORY_READ_BIT;
  453. }
  454. }
  455. void TextureImpl::computeBarrierInfo(TextureUsageBit before, TextureUsageBit after, U32 level,
  456. VkPipelineStageFlags& srcStages, VkAccessFlags& srcAccesses,
  457. VkPipelineStageFlags& dstStages, VkAccessFlags& dstAccesses) const
  458. {
  459. computeBarrierInfo(before, true, level, srcStages, srcAccesses);
  460. computeBarrierInfo(after, false, level, dstStages, dstAccesses);
  461. if(srcStages == 0)
  462. {
  463. srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
  464. }
  465. ANKI_ASSERT(dstStages);
  466. }
  467. VkImageLayout TextureImpl::computeLayout(TextureUsageBit usage, U level) const
  468. {
  469. ANKI_ASSERT(level < m_mipCount);
  470. ANKI_ASSERT(usageValid(usage));
  471. VkImageLayout out = VK_IMAGE_LAYOUT_MAX_ENUM;
  472. const Bool lastLevel = level == m_mipCount - 1u;
  473. const Bool depthStencil = !!m_aspect;
  474. if(usage == TextureUsageBit::NONE)
  475. {
  476. out = VK_IMAGE_LAYOUT_UNDEFINED;
  477. }
  478. else if(depthStencil)
  479. {
  480. if(!(usage & ~(TextureUsageBit::ALL_SAMPLED | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ)))
  481. {
  482. // Only depth tests and sampled
  483. out = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
  484. }
  485. else
  486. {
  487. // Only attachment write, the rest (eg transfer) are not supported for now
  488. ANKI_ASSERT(usage == TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE
  489. || usage == TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT);
  490. out = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  491. }
  492. }
  493. else if(!(usage & ~TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT))
  494. {
  495. // Color attachment
  496. out = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  497. }
  498. else if(!(usage & ~TextureUsageBit::ALL_IMAGE))
  499. {
  500. // Only image load/store
  501. out = VK_IMAGE_LAYOUT_GENERAL;
  502. }
  503. else if(!(usage & ~TextureUsageBit::ALL_SAMPLED))
  504. {
  505. // Only sampled
  506. out = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  507. }
  508. else if(usage == TextureUsageBit::GENERATE_MIPMAPS)
  509. {
  510. if(!lastLevel)
  511. {
  512. out = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
  513. }
  514. else
  515. {
  516. out = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  517. }
  518. }
  519. else if(usage == TextureUsageBit::TRANSFER_DESTINATION)
  520. {
  521. out = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  522. }
  523. else if(usage == TextureUsageBit::PRESENT)
  524. {
  525. out = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  526. }
  527. ANKI_ASSERT(out != VK_IMAGE_LAYOUT_MAX_ENUM);
  528. return out;
  529. }
  530. const MicroImageView& TextureImpl::getOrCreateView(const TextureSubresourceInfo& subresource) const
  531. {
  532. if(m_singleSurfaceImageView.m_handle != VK_NULL_HANDLE)
  533. {
  534. return m_singleSurfaceImageView;
  535. }
  536. {
  537. RLockGuard<RWMutex> lock(m_viewsMapMtx);
  538. auto it = m_viewsMap.find(subresource);
  539. if(it != m_viewsMap.getEnd())
  540. {
  541. return *it;
  542. }
  543. }
  544. // Not found need to create it
  545. WLockGuard<RWMutex> lock(m_viewsMapMtx);
  546. // Search again
  547. auto it = m_viewsMap.find(subresource);
  548. if(it != m_viewsMap.getEnd())
  549. {
  550. return *it;
  551. }
  552. // Not found in the 2nd search, create it
  553. VkImageView handle = VK_NULL_HANDLE;
  554. TextureType viewTexType = TextureType::COUNT;
  555. // Compute the VkImageViewCreateInfo
  556. VkImageViewCreateInfo viewCi;
  557. computeVkImageViewCreateInfo(subresource, viewCi, viewTexType);
  558. ANKI_ASSERT(viewTexType != TextureType::COUNT);
  559. ANKI_VK_CHECKF(vkCreateImageView(getDevice(), &viewCi, nullptr, &handle));
  560. getGrManagerImpl().trySetVulkanHandleName(getName(), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
  561. ptrToNumber(handle));
  562. it = m_viewsMap.emplace(getAllocator(), subresource);
  563. it->m_handle = handle;
  564. it->m_derivedTextureType = viewTexType;
  565. #if 0
  566. printf("Creating image view %p. Texture %p %s\n", static_cast<void*>(handle), static_cast<void*>(m_imageHandle),
  567. getName() ? getName().cstr() : "Unnamed");
  568. #endif
  569. ANKI_ASSERT(&(*m_viewsMap.find(subresource)) == &(*it));
  570. return *it;
  571. }
  572. TextureType TextureImpl::computeNewTexTypeOfSubresource(const TextureSubresourceInfo& subresource) const
  573. {
  574. ANKI_ASSERT(isSubresourceValid(subresource));
  575. if(textureTypeIsCube(m_texType))
  576. {
  577. if(subresource.m_faceCount != 6)
  578. {
  579. ANKI_ASSERT(subresource.m_faceCount == 1);
  580. return (subresource.m_layerCount > 1) ? TextureType::_2D_ARRAY : TextureType::_2D;
  581. }
  582. else if(subresource.m_layerCount == 1)
  583. {
  584. return TextureType::CUBE;
  585. }
  586. }
  587. return m_texType;
  588. }
  589. void TextureImpl::destroyMicroImageView(MicroImageView& view)
  590. {
  591. if(view.m_handle != VK_NULL_HANDLE)
  592. {
  593. vkDestroyImageView(getDevice(), view.m_handle, nullptr);
  594. view.m_handle = VK_NULL_HANDLE;
  595. }
  596. if(view.m_bindlessIndices[0] != MAX_U32)
  597. {
  598. getGrManagerImpl().getDescriptorSetFactory().unbindBindlessTexture(view.m_bindlessIndices[0]);
  599. view.m_bindlessIndices[0] = MAX_U32;
  600. }
  601. if(view.m_bindlessIndices[1] != MAX_U32)
  602. {
  603. getGrManagerImpl().getDescriptorSetFactory().unbindBindlessImage(view.m_bindlessIndices[1]);
  604. view.m_bindlessIndices[1] = MAX_U32;
  605. }
  606. }
  607. } // end namespace anki