Texture.h 7.1 KB

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