TextureImpl.cpp 20 KB

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