Texture.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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/GrObject.h>
  7. namespace anki
  8. {
  9. /// @addtogroup graphics
  10. /// @{
  11. /// Texture initializer.
  12. class alignas(4) TextureInitInfo : public GrBaseInitInfo
  13. {
  14. public:
  15. U32 m_width = 0;
  16. U32 m_height = 0;
  17. U32 m_depth = 1; //< Relevant only for 3D textures.
  18. U32 m_layerCount = 1; ///< Relevant only for texture arrays.
  19. Format m_format = Format::NONE;
  20. TextureUsageBit m_usage = TextureUsageBit::NONE; ///< How the texture will be used.
  21. TextureUsageBit m_initialUsage = TextureUsageBit::NONE; ///< Its initial usage.
  22. TextureType m_type = TextureType::_2D;
  23. U8 m_mipmapCount = 1;
  24. U8 m_samples = 1;
  25. U8 _m_padding[1] = {0};
  26. TextureInitInfo() = default;
  27. TextureInitInfo(CString name)
  28. : GrBaseInitInfo(name)
  29. {
  30. }
  31. U64 computeHash() const
  32. {
  33. const U8* first = reinterpret_cast<const U8*>(&m_width);
  34. const U8* last = reinterpret_cast<const U8*>(&m_samples) + sizeof(m_samples);
  35. const U size = U(last - first);
  36. ANKI_ASSERT(size
  37. == sizeof(m_width) + sizeof(m_height) + sizeof(m_depth) + sizeof(m_layerCount) + sizeof(m_format)
  38. + sizeof(m_usage) + sizeof(m_initialUsage) + sizeof(m_type) + sizeof(m_mipmapCount)
  39. + sizeof(m_samples));
  40. return anki::computeHash(first, size);
  41. }
  42. Bool isValid() const
  43. {
  44. #define ANKI_CHECK_VAL_VALIDITY(x) \
  45. do \
  46. { \
  47. if(!(x)) \
  48. { \
  49. return false; \
  50. } \
  51. } while(0)
  52. ANKI_CHECK_VAL_VALIDITY(m_format != Format::NONE);
  53. ANKI_CHECK_VAL_VALIDITY(m_usage != TextureUsageBit::NONE);
  54. ANKI_CHECK_VAL_VALIDITY(m_mipmapCount > 0);
  55. ANKI_CHECK_VAL_VALIDITY(m_width > 0);
  56. ANKI_CHECK_VAL_VALIDITY(m_height > 0);
  57. switch(m_type)
  58. {
  59. case TextureType::_2D:
  60. ANKI_CHECK_VAL_VALIDITY(m_depth == 1);
  61. ANKI_CHECK_VAL_VALIDITY(m_layerCount == 1);
  62. break;
  63. case TextureType::CUBE:
  64. ANKI_CHECK_VAL_VALIDITY(m_depth == 1);
  65. ANKI_CHECK_VAL_VALIDITY(m_layerCount == 1);
  66. break;
  67. case TextureType::_3D:
  68. ANKI_CHECK_VAL_VALIDITY(m_depth > 0);
  69. ANKI_CHECK_VAL_VALIDITY(m_layerCount == 1);
  70. break;
  71. case TextureType::_2D_ARRAY:
  72. case TextureType::CUBE_ARRAY:
  73. ANKI_CHECK_VAL_VALIDITY(m_depth == 1);
  74. ANKI_CHECK_VAL_VALIDITY(m_layerCount > 0);
  75. break;
  76. default:
  77. ANKI_CHECK_VAL_VALIDITY(0);
  78. };
  79. return true;
  80. #undef ANKI_CHECK_VAL_VALIDITY
  81. }
  82. };
  83. /// GPU texture.
  84. class Texture : public GrObject
  85. {
  86. ANKI_GR_OBJECT
  87. public:
  88. static const GrObjectType CLASS_TYPE = GrObjectType::TEXTURE;
  89. U32 getWidth() const
  90. {
  91. ANKI_ASSERT(m_width);
  92. return m_width;
  93. }
  94. U32 getHeight() const
  95. {
  96. ANKI_ASSERT(m_height);
  97. return m_height;
  98. }
  99. U32 getDepth() const
  100. {
  101. ANKI_ASSERT(m_depth);
  102. return m_depth;
  103. }
  104. U32 getLayerCount() const
  105. {
  106. ANKI_ASSERT(m_layerCount);
  107. return m_layerCount;
  108. }
  109. U32 getMipmapCount() const
  110. {
  111. ANKI_ASSERT(m_mipCount);
  112. return m_mipCount;
  113. }
  114. TextureType getTextureType() const
  115. {
  116. ANKI_ASSERT(m_texType != TextureType::COUNT);
  117. return m_texType;
  118. }
  119. TextureUsageBit getTextureUsage() const
  120. {
  121. ANKI_ASSERT(!!m_usage);
  122. return m_usage;
  123. }
  124. Format getFormat() const
  125. {
  126. ANKI_ASSERT(m_format != Format::NONE);
  127. return m_format;
  128. }
  129. DepthStencilAspectBit getDepthStencilAspect() const
  130. {
  131. return m_aspect;
  132. }
  133. Bool isSubresourceValid(const TextureSubresourceInfo& subresource) const
  134. {
  135. #define ANKI_TEX_SUBRESOURCE_ASSERT(x_) \
  136. if(!(x_)) \
  137. { \
  138. return false; \
  139. }
  140. const TextureType type = m_texType;
  141. const Bool cube = textureTypeIsCube(type);
  142. // Mips
  143. ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_mipmapCount > 0);
  144. ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_firstMipmap + subresource.m_mipmapCount <= m_mipCount);
  145. // Layers
  146. ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_layerCount > 0);
  147. ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_firstLayer + subresource.m_layerCount <= m_layerCount);
  148. // Faces
  149. const U8 faceCount = (cube) ? 6 : 1;
  150. ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_faceCount == 1 || subresource.m_faceCount == 6);
  151. ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_firstFace + subresource.m_faceCount <= faceCount);
  152. // Aspect
  153. ANKI_TEX_SUBRESOURCE_ASSERT((m_aspect & subresource.m_depthStencilAspect) == subresource.m_depthStencilAspect);
  154. // Misc
  155. if(type == TextureType::CUBE_ARRAY && subresource.m_layerCount > 1)
  156. {
  157. // Because of the way surfaces are arranged in cube arrays
  158. ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_faceCount == 6);
  159. }
  160. #undef ANKI_TEX_SUBRESOURCE_ASSERT
  161. return true;
  162. }
  163. /// Mipmap generation requires a specific subresource range.
  164. Bool isSubresourceGoodForMipmapGeneration(const TextureSubresourceInfo& subresource) const
  165. {
  166. ANKI_ASSERT(isSubresourceValid(subresource));
  167. if(m_texType != TextureType::_3D)
  168. {
  169. return subresource.m_firstMipmap == 0 && subresource.m_mipmapCount == m_mipCount
  170. && subresource.m_faceCount == 1 && subresource.m_layerCount == 1
  171. && subresource.m_depthStencilAspect == m_aspect;
  172. }
  173. else
  174. {
  175. ANKI_ASSERT(!"TODO");
  176. return false;
  177. }
  178. }
  179. /// Return true if the subresource is good to be bound for image load store.
  180. Bool isSubresourceGoodForImageLoadStore(const TextureSubresourceInfo& subresource) const
  181. {
  182. ANKI_ASSERT(isSubresourceValid(subresource));
  183. // One mip and no depth stencil
  184. return subresource.m_mipmapCount == 1 && !subresource.m_depthStencilAspect;
  185. }
  186. /// Return true if the subresource can be bound for sampling.
  187. Bool isSubresourceGoodForSampling(const TextureSubresourceInfo& subresource) const
  188. {
  189. ANKI_ASSERT(isSubresourceValid(subresource));
  190. /// Can bound only one aspect at a time.
  191. return subresource.m_depthStencilAspect == DepthStencilAspectBit::DEPTH
  192. || subresource.m_depthStencilAspect == DepthStencilAspectBit::STENCIL
  193. || subresource.m_depthStencilAspect == DepthStencilAspectBit::NONE;
  194. }
  195. /// Return true if the subresource can be used in CommandBuffer::copyBufferToTextureView.
  196. Bool isSubresourceGoodForCopyFromBuffer(const TextureSubresourceInfo& subresource) const
  197. {
  198. ANKI_ASSERT(isSubresourceValid(subresource));
  199. return subresource.m_faceCount == 1 && subresource.m_mipmapCount == 1 && subresource.m_layerCount == 1
  200. && subresource.m_depthStencilAspect == DepthStencilAspectBit::NONE;
  201. }
  202. /// Return true if the subresource can be used as Framebuffer attachment.
  203. Bool isSubresourceGoodForFramebufferAttachment(const TextureSubresourceInfo& subresource) const
  204. {
  205. ANKI_ASSERT(isSubresourceValid(subresource));
  206. return subresource.m_faceCount == 1 && subresource.m_mipmapCount == 1 && subresource.m_layerCount == 1;
  207. }
  208. protected:
  209. U32 m_width = 0;
  210. U32 m_height = 0;
  211. U32 m_depth = 0;
  212. U32 m_layerCount = 0;
  213. U32 m_mipCount = 0;
  214. TextureType m_texType = TextureType::COUNT;
  215. TextureUsageBit m_usage = TextureUsageBit::NONE;
  216. Format m_format = Format::NONE;
  217. DepthStencilAspectBit m_aspect = DepthStencilAspectBit::NONE;
  218. /// Construct.
  219. Texture(GrManager* manager, CString name)
  220. : GrObject(manager, CLASS_TYPE, name)
  221. {
  222. }
  223. /// Destroy.
  224. ~Texture()
  225. {
  226. }
  227. private:
  228. /// Allocate and initialize a new instance.
  229. static ANKI_USE_RESULT Texture* newInstance(GrManager* manager, const TextureInitInfo& init);
  230. };
  231. /// @}
  232. } // end namespace anki