TextureImpl.h 6.1 KB

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