TextureImpl.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. #pragma once
  6. #include <AnKi/Gr/Texture.h>
  7. #include <AnKi/Gr/Vulkan/VulkanObject.h>
  8. #include <AnKi/Gr/Vulkan/GpuMemoryManager.h>
  9. #include <AnKi/Gr/Utils/Functions.h>
  10. #include <AnKi/Gr/Vulkan/SamplerFactory.h>
  11. #include <AnKi/Util/HashMap.h>
  12. namespace anki
  13. {
  14. // Forward
  15. class TextureUsageState;
  16. /// @addtogroup vulkan
  17. /// @{
  18. enum class TextureImplWorkaround : U8
  19. {
  20. NONE,
  21. R8G8B8_TO_R8G8B8A8 = 1 << 0,
  22. S8_TO_D24S8 = 1 << 1,
  23. D24S8_TO_D32S8 = 1 << 2,
  24. };
  25. ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(TextureImplWorkaround)
  26. /// A Vulkan image view with some extra data.
  27. class MicroImageView
  28. {
  29. friend class TextureImpl;
  30. public:
  31. MicroImageView() = default;
  32. MicroImageView(MicroImageView&& b)
  33. {
  34. *this = std::move(b);
  35. }
  36. ~MicroImageView()
  37. {
  38. for(U32 idx : m_bindlessIndices)
  39. {
  40. ANKI_ASSERT(idx == MAX_U32 && "Forgot to unbind the bindless");
  41. (void)idx;
  42. }
  43. ANKI_ASSERT(m_handle == VK_NULL_HANDLE);
  44. }
  45. MicroImageView& operator=(MicroImageView&& b)
  46. {
  47. m_handle = b.m_handle;
  48. b.m_handle = VK_NULL_HANDLE;
  49. m_bindlessIndices = b.m_bindlessIndices;
  50. b.m_bindlessIndices = {MAX_U32, MAX_U32};
  51. m_derivedTextureType = b.m_derivedTextureType;
  52. b.m_derivedTextureType = TextureType::COUNT;
  53. return *this;
  54. }
  55. VkImageView getHandle() const
  56. {
  57. ANKI_ASSERT(m_handle);
  58. return m_handle;
  59. }
  60. /// @note It's thread-safe.
  61. U32 getOrCreateBindlessIndex(VkImageLayout layout, GrManagerImpl& gr) const;
  62. TextureType getDerivedTextureType() const
  63. {
  64. ANKI_ASSERT(m_derivedTextureType != TextureType::COUNT);
  65. return m_derivedTextureType;
  66. }
  67. private:
  68. VkImageView m_handle = VK_NULL_HANDLE;
  69. /// Index 0: Sampled image with SHADER_READ_ONLY layout.
  70. /// Index 1: Storage image with ofcource GENERAL layout.
  71. mutable Array<U32, 2> m_bindlessIndices = {MAX_U32, MAX_U32};
  72. /// Protect the m_bindlessIndices.
  73. mutable SpinLock m_lock;
  74. /// Because for example a single surface view of a cube texture will be a 2D view.
  75. TextureType m_derivedTextureType = TextureType::COUNT;
  76. };
  77. /// Texture container.
  78. class TextureImpl final : public Texture, public VulkanObject<Texture, TextureImpl>
  79. {
  80. public:
  81. VkImage m_imageHandle = VK_NULL_HANDLE;
  82. GpuMemoryHandle m_memHandle;
  83. VkFormat m_vkFormat = VK_FORMAT_UNDEFINED;
  84. TextureImplWorkaround m_workarounds = TextureImplWorkaround::NONE;
  85. VkImageViewCreateInfo m_viewCreateInfoTemplate;
  86. TextureImpl(GrManager* manager, CString name)
  87. : Texture(manager, name)
  88. {
  89. }
  90. ~TextureImpl();
  91. ANKI_USE_RESULT Error init(const TextureInitInfo& init)
  92. {
  93. return initInternal(VK_NULL_HANDLE, init);
  94. }
  95. ANKI_USE_RESULT Error initExternal(VkImage image, const TextureInitInfo& init)
  96. {
  97. return initInternal(image, init);
  98. }
  99. Bool aspectValid(DepthStencilAspectBit aspect) const
  100. {
  101. return m_aspect == aspect || !!(aspect & m_aspect);
  102. }
  103. /// Compute the layer as defined by Vulkan.
  104. U32 computeVkArrayLayer(const TextureSurfaceInfo& surf) const
  105. {
  106. U32 layer = 0;
  107. switch(m_texType)
  108. {
  109. case TextureType::_2D:
  110. layer = 0;
  111. break;
  112. case TextureType::CUBE:
  113. layer = surf.m_face;
  114. break;
  115. case TextureType::_2D_ARRAY:
  116. layer = surf.m_layer;
  117. break;
  118. case TextureType::CUBE_ARRAY:
  119. layer = surf.m_layer * 6 + surf.m_face;
  120. break;
  121. default:
  122. ANKI_ASSERT(0);
  123. }
  124. return layer;
  125. }
  126. U32 computeVkArrayLayer(const TextureVolumeInfo& vol) const
  127. {
  128. ANKI_ASSERT(m_texType == TextureType::_3D);
  129. return 0;
  130. }
  131. Bool usageValid(TextureUsageBit usage) const
  132. {
  133. #if ANKI_ENABLE_ASSERTIONS
  134. LockGuard<SpinLock> lock(m_usedForMtx);
  135. m_usedFor |= usage;
  136. #endif
  137. return (usage & m_usage) == usage;
  138. }
  139. /// By knowing the previous and new texture usage calculate the relavant info for a ppline barrier.
  140. void computeBarrierInfo(TextureUsageBit before, TextureUsageBit after, U32 level, VkPipelineStageFlags& srcStages,
  141. VkAccessFlags& srcAccesses, VkPipelineStageFlags& dstStages,
  142. VkAccessFlags& dstAccesses) const;
  143. /// Predict the image layout.
  144. VkImageLayout computeLayout(TextureUsageBit usage, U level) const;
  145. void computeVkImageSubresourceRange(const TextureSubresourceInfo& in, VkImageSubresourceRange& range) const
  146. {
  147. ANKI_ASSERT(isSubresourceValid(in));
  148. range.aspectMask = convertImageAspect(in.m_depthStencilAspect);
  149. range.baseMipLevel = in.m_firstMipmap;
  150. range.levelCount = in.m_mipmapCount;
  151. const U32 faceCount = textureTypeIsCube(m_texType) ? 6 : 1;
  152. range.baseArrayLayer = in.m_firstLayer * faceCount + in.m_firstFace;
  153. range.layerCount = in.m_layerCount * in.m_faceCount;
  154. }
  155. void computeVkImageViewCreateInfo(const TextureSubresourceInfo& subresource, VkImageViewCreateInfo& viewCi,
  156. TextureType& newTextureType) const
  157. {
  158. ANKI_ASSERT(isSubresourceValid(subresource));
  159. viewCi = m_viewCreateInfoTemplate;
  160. computeVkImageSubresourceRange(subresource, viewCi.subresourceRange);
  161. // Fixup the image view type
  162. newTextureType = computeNewTexTypeOfSubresource(subresource);
  163. viewCi.viewType = convertTextureViewType(newTextureType);
  164. }
  165. const MicroImageView& getOrCreateView(const TextureSubresourceInfo& subresource) const;
  166. private:
  167. mutable HashMap<TextureSubresourceInfo, MicroImageView> m_viewsMap;
  168. mutable RWMutex m_viewsMapMtx;
  169. /// This is a special optimization for textures that have only one surface. In this case we don't need to go through
  170. /// the hashmap above.
  171. MicroImageView m_singleSurfaceImageView;
  172. VkDeviceMemory m_dedicatedMem = VK_NULL_HANDLE;
  173. #if ANKI_ENABLE_ASSERTIONS
  174. mutable TextureUsageBit m_usedFor = TextureUsageBit::NONE;
  175. mutable SpinLock m_usedForMtx;
  176. #endif
  177. ANKI_USE_RESULT static VkFormatFeatureFlags calcFeatures(const TextureInitInfo& init);
  178. ANKI_USE_RESULT static VkImageCreateFlags calcCreateFlags(const TextureInitInfo& init);
  179. ANKI_USE_RESULT Bool imageSupported(const TextureInitInfo& init);
  180. ANKI_USE_RESULT Error initImage(const TextureInitInfo& init);
  181. template<typename TextureInfo>
  182. void updateUsageState(const TextureInfo& surfOrVol, TextureUsageBit usage, StackAllocator<U8>& alloc,
  183. TextureUsageState& state) const;
  184. void updateUsageState(TextureUsageBit usage, StackAllocator<U8>& alloc, TextureUsageState& state) const;
  185. /// Compute the new type of a texture view.
  186. TextureType computeNewTexTypeOfSubresource(const TextureSubresourceInfo& subresource) const;
  187. ANKI_USE_RESULT Error initInternal(VkImage externalImage, const TextureInitInfo& init);
  188. void computeBarrierInfo(TextureUsageBit usage, Bool src, U32 level, VkPipelineStageFlags& stages,
  189. VkAccessFlags& accesses) const;
  190. void destroyMicroImageView(MicroImageView& view);
  191. };
  192. /// @}
  193. } // end namespace anki