Texture.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. // Copyright (C) 2009-present, 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/GrObject.h>
  7. namespace anki {
  8. // Forward
  9. class TextureSubresourceDesc;
  10. /// @addtogroup graphics
  11. /// @{
  12. /// Texture initializer.
  13. class TextureInitInfo : public GrBaseInitInfo
  14. {
  15. public:
  16. U32 m_width = 0;
  17. U32 m_height = 0;
  18. U32 m_depth = 1; ///< Relevant only for 3D textures.
  19. U32 m_layerCount = 1; ///< Relevant only for texture arrays.
  20. Format m_format = Format::kNone;
  21. TextureUsageBit m_usage = TextureUsageBit::kNone; ///< How the texture will be used.
  22. TextureType m_type = TextureType::k2D;
  23. U8 m_mipmapCount = 1;
  24. U8 m_samples = 1;
  25. TextureInitInfo() = default;
  26. TextureInitInfo(CString name)
  27. : GrBaseInitInfo(name)
  28. {
  29. }
  30. U64 computeHash() const
  31. {
  32. Array<U64, 9> arr;
  33. U32 count = 0;
  34. arr[count++] = m_width;
  35. arr[count++] = m_height;
  36. arr[count++] = m_depth;
  37. arr[count++] = m_layerCount;
  38. arr[count++] = U64(m_format);
  39. arr[count++] = U64(m_usage);
  40. arr[count++] = U64(m_type);
  41. arr[count++] = m_mipmapCount;
  42. arr[count++] = m_samples;
  43. return computeObjectHash(arr);
  44. }
  45. Bool isValid() const
  46. {
  47. #define ANKI_CHECK_VAL_VALIDITY(x) \
  48. do \
  49. { \
  50. if(!(x)) \
  51. { \
  52. return false; \
  53. } \
  54. } while(0)
  55. ANKI_CHECK_VAL_VALIDITY(m_format != Format::kNone);
  56. ANKI_CHECK_VAL_VALIDITY(m_usage != TextureUsageBit::kNone);
  57. ANKI_CHECK_VAL_VALIDITY(m_mipmapCount > 0);
  58. ANKI_CHECK_VAL_VALIDITY(m_width > 0);
  59. ANKI_CHECK_VAL_VALIDITY(m_height > 0);
  60. switch(m_type)
  61. {
  62. case TextureType::k2D:
  63. ANKI_CHECK_VAL_VALIDITY(m_depth == 1);
  64. ANKI_CHECK_VAL_VALIDITY(m_layerCount == 1);
  65. break;
  66. case TextureType::kCube:
  67. ANKI_CHECK_VAL_VALIDITY(m_depth == 1);
  68. ANKI_CHECK_VAL_VALIDITY(m_layerCount == 1);
  69. break;
  70. case TextureType::k3D:
  71. ANKI_CHECK_VAL_VALIDITY(m_depth > 0);
  72. ANKI_CHECK_VAL_VALIDITY(m_layerCount == 1);
  73. ANKI_CHECK_VAL_VALIDITY(!(m_usage & TextureUsageBit::kAllRtvDsv));
  74. break;
  75. case TextureType::k2DArray:
  76. case TextureType::kCubeArray:
  77. ANKI_CHECK_VAL_VALIDITY(m_depth == 1);
  78. ANKI_CHECK_VAL_VALIDITY(m_layerCount > 0);
  79. break;
  80. default:
  81. ANKI_CHECK_VAL_VALIDITY(0);
  82. };
  83. return true;
  84. #undef ANKI_CHECK_VAL_VALIDITY
  85. }
  86. };
  87. /// GPU texture.
  88. class Texture : public GrObject
  89. {
  90. ANKI_GR_OBJECT
  91. public:
  92. static constexpr GrObjectType kClassType = GrObjectType::kTexture;
  93. U32 getWidth() const
  94. {
  95. ANKI_ASSERT(m_width);
  96. return m_width;
  97. }
  98. U32 getHeight() const
  99. {
  100. ANKI_ASSERT(m_height);
  101. return m_height;
  102. }
  103. U32 getDepth() const
  104. {
  105. ANKI_ASSERT(m_depth);
  106. return m_depth;
  107. }
  108. U32 getLayerCount() const
  109. {
  110. ANKI_ASSERT(m_layerCount);
  111. return m_layerCount;
  112. }
  113. U8 getMipmapCount() const
  114. {
  115. ANKI_ASSERT(m_mipCount);
  116. return m_mipCount;
  117. }
  118. TextureType getTextureType() const
  119. {
  120. ANKI_ASSERT(m_texType != TextureType::kCount);
  121. return m_texType;
  122. }
  123. TextureUsageBit getTextureUsage() const
  124. {
  125. ANKI_ASSERT(!!m_usage);
  126. return m_usage;
  127. }
  128. Format getFormat() const
  129. {
  130. ANKI_ASSERT(m_format != Format::kNone);
  131. return m_format;
  132. }
  133. DepthStencilAspectBit getDepthStencilAspect() const
  134. {
  135. return m_aspect;
  136. }
  137. /// Returns an index to be used for bindless access. Only for sampling.
  138. /// @note It's thread-safe
  139. U32 getOrCreateBindlessTextureIndex(const TextureSubresourceDesc& subresource);
  140. protected:
  141. U32 m_width = 0;
  142. U32 m_height = 0;
  143. U32 m_depth = 0;
  144. U32 m_layerCount = 0;
  145. U8 m_mipCount = 0;
  146. TextureType m_texType = TextureType::kCount;
  147. TextureUsageBit m_usage = TextureUsageBit::kNone;
  148. Format m_format = Format::kNone;
  149. DepthStencilAspectBit m_aspect = DepthStencilAspectBit::kNone;
  150. /// Construct.
  151. Texture(CString name)
  152. : GrObject(kClassType, name)
  153. {
  154. }
  155. /// Destroy.
  156. ~Texture()
  157. {
  158. }
  159. private:
  160. /// Allocate and initialize a new instance.
  161. [[nodiscard]] static Texture* newInstance(const TextureInitInfo& init);
  162. };
  163. /// Defines a part of a texture. This part can be a single surface or volume or the whole texture.
  164. class TextureSubresourceDesc
  165. {
  166. public:
  167. U16 m_layer = 0;
  168. U8 m_mipmap = 0;
  169. U8 m_face = 0;
  170. /// This flag doesn't mean the whole texture unless the m_aspect is equal to the aspect of the Texture.
  171. Bool m_allSurfacesOrVolumes = true;
  172. DepthStencilAspectBit m_depthStencilAspect = DepthStencilAspectBit::kNone;
  173. U8 _m_padding[2] = {0, 0};
  174. constexpr TextureSubresourceDesc(const TextureSubresourceDesc&) = default;
  175. constexpr TextureSubresourceDesc& operator=(const TextureSubresourceDesc&) = default;
  176. constexpr Bool operator==(const TextureSubresourceDesc& b) const
  177. {
  178. return m_mipmap == b.m_mipmap && m_face == b.m_face && m_layer == b.m_layer && m_allSurfacesOrVolumes == b.m_allSurfacesOrVolumes
  179. && m_depthStencilAspect == b.m_depthStencilAspect;
  180. }
  181. static constexpr TextureSubresourceDesc all(DepthStencilAspectBit aspect = DepthStencilAspectBit::kNone)
  182. {
  183. return TextureSubresourceDesc(0, 0, 0, true, aspect);
  184. }
  185. static constexpr TextureSubresourceDesc surface(U32 mip, U32 face, U32 layer, DepthStencilAspectBit aspect = DepthStencilAspectBit::kNone)
  186. {
  187. return TextureSubresourceDesc(mip, face, layer, false, aspect);
  188. }
  189. static constexpr TextureSubresourceDesc firstSurface(DepthStencilAspectBit aspect = DepthStencilAspectBit::kNone)
  190. {
  191. return TextureSubresourceDesc(0, 0, 0, false, aspect);
  192. }
  193. static constexpr TextureSubresourceDesc volume(U32 mip)
  194. {
  195. return TextureSubresourceDesc(mip, 0, 0, false, DepthStencilAspectBit::kNone);
  196. }
  197. /// Returns true if there is a surface or volume that overlaps. It doesn't check the aspect.
  198. Bool overlapsWith(const TextureSubresourceDesc& b) const
  199. {
  200. return m_allSurfacesOrVolumes || b.m_allSurfacesOrVolumes || (m_mipmap == b.m_mipmap && m_face == b.m_face && m_layer == b.m_layer);
  201. }
  202. void validate(const Texture& tex) const
  203. {
  204. if(!m_allSurfacesOrVolumes)
  205. {
  206. ANKI_ASSERT(m_mipmap <= tex.getMipmapCount());
  207. [[maybe_unused]] const U8 faceCount = textureTypeIsCube(tex.getTextureType()) ? 6 : 1;
  208. ANKI_ASSERT(m_face < faceCount);
  209. ANKI_ASSERT(m_layer < tex.getLayerCount());
  210. }
  211. else
  212. {
  213. ANKI_ASSERT(m_mipmap == 0 && m_face == 0 && m_layer == 0);
  214. }
  215. if(getFormatInfo(tex.getFormat()).m_depthStencil == DepthStencilAspectBit::kDepthStencil)
  216. {
  217. ANKI_ASSERT(!!m_depthStencilAspect);
  218. }
  219. else if(getFormatInfo(tex.getFormat()).m_depthStencil == DepthStencilAspectBit::kDepth)
  220. {
  221. ANKI_ASSERT(m_depthStencilAspect == DepthStencilAspectBit::kDepth);
  222. }
  223. else if(getFormatInfo(tex.getFormat()).m_depthStencil == DepthStencilAspectBit::kStencil)
  224. {
  225. ANKI_ASSERT(m_depthStencilAspect == DepthStencilAspectBit::kStencil);
  226. }
  227. else
  228. {
  229. ANKI_ASSERT(m_depthStencilAspect == DepthStencilAspectBit::kNone);
  230. }
  231. }
  232. private:
  233. constexpr TextureSubresourceDesc(U32 mip, U32 face, U32 layer, Bool allSurfs, DepthStencilAspectBit aspect)
  234. : m_layer(layer & kMaxU16)
  235. , m_mipmap(mip & kMaxU8)
  236. , m_face(face & kMaxU8)
  237. , m_allSurfacesOrVolumes(allSurfs)
  238. , m_depthStencilAspect(aspect)
  239. {
  240. static_assert(sizeof(TextureSubresourceDesc) == 8, "Because it may get hashed");
  241. }
  242. };
  243. /// Defines a part of a texture. This part can be a single surface or volume or the whole texture.
  244. class TextureView
  245. {
  246. public:
  247. TextureView()
  248. : m_subresource(TextureSubresourceDesc::all())
  249. {
  250. }
  251. explicit TextureView(const Texture* tex, const TextureSubresourceDesc& subresource = TextureSubresourceDesc::all())
  252. : m_tex(tex)
  253. , m_subresource(subresource)
  254. {
  255. ANKI_ASSERT(tex);
  256. if(textureTypeIsCube(m_tex->getTextureType()))
  257. {
  258. m_subresource.m_allSurfacesOrVolumes = subresource.m_allSurfacesOrVolumes;
  259. }
  260. else
  261. {
  262. m_subresource.m_allSurfacesOrVolumes =
  263. (m_tex->getMipmapCount() == 1 && m_tex->getLayerCount() == 1) || subresource.m_allSurfacesOrVolumes;
  264. }
  265. // Sanitize a bit
  266. if(subresource.m_depthStencilAspect == DepthStencilAspectBit::kNone && tex->getDepthStencilAspect() != DepthStencilAspectBit::kNone)
  267. {
  268. m_subresource.m_depthStencilAspect = tex->getDepthStencilAspect();
  269. }
  270. validate();
  271. }
  272. TextureView(const TextureView&) = default;
  273. TextureView& operator=(const TextureView&) = default;
  274. [[nodiscard]] Bool isValid() const
  275. {
  276. return m_tex != nullptr;
  277. }
  278. [[nodiscard]] const Texture& getTexture() const
  279. {
  280. validate();
  281. return *m_tex;
  282. }
  283. /// Returns true if the view contains all surfaces or volumes. It's orthogonal to depth stencil aspect.
  284. [[nodiscard]] Bool isAllSurfacesOrVolumes() const
  285. {
  286. validate();
  287. return m_subresource.m_allSurfacesOrVolumes;
  288. }
  289. [[nodiscard]] DepthStencilAspectBit getDepthStencilAspect() const
  290. {
  291. validate();
  292. return m_subresource.m_depthStencilAspect;
  293. }
  294. [[nodiscard]] U32 getFirstMipmap() const
  295. {
  296. validate();
  297. return (m_subresource.m_allSurfacesOrVolumes) ? 0 : m_subresource.m_mipmap;
  298. }
  299. [[nodiscard]] U32 getMipmapCount() const
  300. {
  301. validate();
  302. return (m_subresource.m_allSurfacesOrVolumes) ? m_tex->getMipmapCount() : 1;
  303. }
  304. [[nodiscard]] U32 getFirstLayer() const
  305. {
  306. validate();
  307. return (m_subresource.m_allSurfacesOrVolumes) ? 0 : m_subresource.m_layer;
  308. }
  309. [[nodiscard]] U32 getLayerCount() const
  310. {
  311. validate();
  312. return (m_subresource.m_allSurfacesOrVolumes) ? m_tex->getLayerCount() : 1;
  313. }
  314. [[nodiscard]] U32 getFirstFace() const
  315. {
  316. validate();
  317. return (m_subresource.m_allSurfacesOrVolumes) ? 0 : m_subresource.m_face;
  318. }
  319. [[nodiscard]] U32 getFaceCount() const
  320. {
  321. validate();
  322. return (m_subresource.m_allSurfacesOrVolumes) ? (textureTypeIsCube(m_tex->getTextureType()) ? 6 : 1) : 1;
  323. }
  324. [[nodiscard]] Bool isGoodForSampling() const
  325. {
  326. validate();
  327. /// Can bound only one aspect at a time.
  328. return (m_subresource.m_depthStencilAspect == DepthStencilAspectBit::kDepth
  329. || m_subresource.m_depthStencilAspect == DepthStencilAspectBit::kStencil
  330. || m_subresource.m_depthStencilAspect == DepthStencilAspectBit::kNone)
  331. && !!(m_tex->getTextureUsage() & TextureUsageBit::kAllSrv);
  332. }
  333. /// Return true if the subresource can be used in CommandBuffer::copyBufferToTexture.
  334. [[nodiscard]] Bool isGoodForCopyBufferToTexture() const
  335. {
  336. validate();
  337. return isSingleSurfaceOrVolume() && m_subresource.m_depthStencilAspect == DepthStencilAspectBit::kNone
  338. && !!(m_tex->getTextureUsage() & TextureUsageBit::kCopyDestination);
  339. }
  340. [[nodiscard]] Bool isGoodForStorage() const
  341. {
  342. validate();
  343. return isSingleSurfaceOrVolume() && m_subresource.m_depthStencilAspect == DepthStencilAspectBit::kNone
  344. && !!(m_tex->getTextureUsage() & TextureUsageBit::kAllUav);
  345. }
  346. [[nodiscard]] Bool isGoodForRenderTarget() const
  347. {
  348. validate();
  349. return isSingleSurfaceOrVolume() && !!(m_tex->getTextureUsage() & TextureUsageBit::kAllRtvDsv);
  350. }
  351. /// Returns true if there is a surface or volume that overlaps. It doesn't check the aspect.
  352. [[nodiscard]] Bool overlapsWith(const TextureView& b) const
  353. {
  354. validate();
  355. b.validate();
  356. ANKI_ASSERT(m_tex == b.m_tex);
  357. return m_subresource.overlapsWith(b.m_subresource);
  358. }
  359. const TextureSubresourceDesc& getSubresource() const
  360. {
  361. validate();
  362. return m_subresource;
  363. }
  364. private:
  365. const Texture* m_tex = nullptr;
  366. TextureSubresourceDesc m_subresource;
  367. void validate() const
  368. {
  369. ANKI_ASSERT(m_tex);
  370. m_subresource.validate(*m_tex);
  371. }
  372. Bool isSingleSurfaceOrVolume() const
  373. {
  374. validate();
  375. Bool singleSurfaceOrVolume;
  376. if(textureTypeIsCube(m_tex->getTextureType()))
  377. {
  378. singleSurfaceOrVolume = !m_subresource.m_allSurfacesOrVolumes;
  379. }
  380. else
  381. {
  382. singleSurfaceOrVolume = (m_tex->getMipmapCount() == 1 && m_tex->getLayerCount() == 1) || !m_subresource.m_allSurfacesOrVolumes;
  383. }
  384. return singleSurfaceOrVolume;
  385. }
  386. };
  387. /// @}
  388. } // end namespace anki