| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #pragma once
- #include <AnKi/Gr/GrObject.h>
- namespace anki
- {
- /// @addtogroup graphics
- /// @{
- /// Texture initializer.
- class alignas(4) TextureInitInfo : public GrBaseInitInfo
- {
- public:
- U32 m_width = 0;
- U32 m_height = 0;
- U32 m_depth = 1; //< Relevant only for 3D textures.
- U32 m_layerCount = 1; ///< Relevant only for texture arrays.
- Format m_format = Format::NONE;
- TextureUsageBit m_usage = TextureUsageBit::NONE; ///< How the texture will be used.
- TextureUsageBit m_initialUsage = TextureUsageBit::NONE; ///< Its initial usage.
- TextureType m_type = TextureType::_2D;
- U8 m_mipmapCount = 1;
- U8 m_samples = 1;
- U8 _m_padding[1] = {0};
- TextureInitInfo() = default;
- TextureInitInfo(CString name)
- : GrBaseInitInfo(name)
- {
- }
- U64 computeHash() const
- {
- const U8* first = reinterpret_cast<const U8*>(&m_width);
- const U8* last = reinterpret_cast<const U8*>(&m_samples) + sizeof(m_samples);
- const U size = U(last - first);
- ANKI_ASSERT(size
- == sizeof(m_width) + sizeof(m_height) + sizeof(m_depth) + sizeof(m_layerCount) + sizeof(m_format)
- + sizeof(m_usage) + sizeof(m_initialUsage) + sizeof(m_type) + sizeof(m_mipmapCount)
- + sizeof(m_samples));
- return anki::computeHash(first, size);
- }
- Bool isValid() const
- {
- #define ANKI_CHECK_VAL_VALIDITY(x) \
- do \
- { \
- if(!(x)) \
- { \
- return false; \
- } \
- } while(0)
- ANKI_CHECK_VAL_VALIDITY(m_format != Format::NONE);
- ANKI_CHECK_VAL_VALIDITY(m_usage != TextureUsageBit::NONE);
- ANKI_CHECK_VAL_VALIDITY(m_mipmapCount > 0);
- ANKI_CHECK_VAL_VALIDITY(m_width > 0);
- ANKI_CHECK_VAL_VALIDITY(m_height > 0);
- switch(m_type)
- {
- case TextureType::_2D:
- ANKI_CHECK_VAL_VALIDITY(m_depth == 1);
- ANKI_CHECK_VAL_VALIDITY(m_layerCount == 1);
- break;
- case TextureType::CUBE:
- ANKI_CHECK_VAL_VALIDITY(m_depth == 1);
- ANKI_CHECK_VAL_VALIDITY(m_layerCount == 1);
- break;
- case TextureType::_3D:
- ANKI_CHECK_VAL_VALIDITY(m_depth > 0);
- ANKI_CHECK_VAL_VALIDITY(m_layerCount == 1);
- break;
- case TextureType::_2D_ARRAY:
- case TextureType::CUBE_ARRAY:
- ANKI_CHECK_VAL_VALIDITY(m_depth == 1);
- ANKI_CHECK_VAL_VALIDITY(m_layerCount > 0);
- break;
- default:
- ANKI_CHECK_VAL_VALIDITY(0);
- };
- return true;
- #undef ANKI_CHECK_VAL_VALIDITY
- }
- };
- /// GPU texture.
- class Texture : public GrObject
- {
- ANKI_GR_OBJECT
- public:
- static const GrObjectType CLASS_TYPE = GrObjectType::TEXTURE;
- U32 getWidth() const
- {
- ANKI_ASSERT(m_width);
- return m_width;
- }
- U32 getHeight() const
- {
- ANKI_ASSERT(m_height);
- return m_height;
- }
- U32 getDepth() const
- {
- ANKI_ASSERT(m_depth);
- return m_depth;
- }
- U32 getLayerCount() const
- {
- ANKI_ASSERT(m_layerCount);
- return m_layerCount;
- }
- U32 getMipmapCount() const
- {
- ANKI_ASSERT(m_mipCount);
- return m_mipCount;
- }
- TextureType getTextureType() const
- {
- ANKI_ASSERT(m_texType != TextureType::COUNT);
- return m_texType;
- }
- TextureUsageBit getTextureUsage() const
- {
- ANKI_ASSERT(!!m_usage);
- return m_usage;
- }
- Format getFormat() const
- {
- ANKI_ASSERT(m_format != Format::NONE);
- return m_format;
- }
- DepthStencilAspectBit getDepthStencilAspect() const
- {
- return m_aspect;
- }
- Bool isSubresourceValid(const TextureSubresourceInfo& subresource) const
- {
- #define ANKI_TEX_SUBRESOURCE_ASSERT(x_) \
- if(!(x_)) \
- { \
- return false; \
- }
- const TextureType type = m_texType;
- const Bool cube = textureTypeIsCube(type);
- // Mips
- ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_mipmapCount > 0);
- ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_firstMipmap + subresource.m_mipmapCount <= m_mipCount);
- // Layers
- ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_layerCount > 0);
- ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_firstLayer + subresource.m_layerCount <= m_layerCount);
- // Faces
- const U8 faceCount = (cube) ? 6 : 1;
- ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_faceCount == 1 || subresource.m_faceCount == 6);
- ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_firstFace + subresource.m_faceCount <= faceCount);
- // Aspect
- ANKI_TEX_SUBRESOURCE_ASSERT((m_aspect & subresource.m_depthStencilAspect) == subresource.m_depthStencilAspect);
- // Misc
- if(type == TextureType::CUBE_ARRAY && subresource.m_layerCount > 1)
- {
- // Because of the way surfaces are arranged in cube arrays
- ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_faceCount == 6);
- }
- #undef ANKI_TEX_SUBRESOURCE_ASSERT
- return true;
- }
- /// Mipmap generation requires a specific subresource range.
- Bool isSubresourceGoodForMipmapGeneration(const TextureSubresourceInfo& subresource) const
- {
- ANKI_ASSERT(isSubresourceValid(subresource));
- if(m_texType != TextureType::_3D)
- {
- return subresource.m_firstMipmap == 0 && subresource.m_mipmapCount == m_mipCount
- && subresource.m_faceCount == 1 && subresource.m_layerCount == 1
- && subresource.m_depthStencilAspect == m_aspect;
- }
- else
- {
- ANKI_ASSERT(!"TODO");
- return false;
- }
- }
- /// Return true if the subresource is good to be bound for image load store.
- Bool isSubresourceGoodForImageLoadStore(const TextureSubresourceInfo& subresource) const
- {
- ANKI_ASSERT(isSubresourceValid(subresource));
- // One mip and no depth stencil
- return subresource.m_mipmapCount == 1 && !subresource.m_depthStencilAspect;
- }
- /// Return true if the subresource can be bound for sampling.
- Bool isSubresourceGoodForSampling(const TextureSubresourceInfo& subresource) const
- {
- ANKI_ASSERT(isSubresourceValid(subresource));
- /// Can bound only one aspect at a time.
- return subresource.m_depthStencilAspect == DepthStencilAspectBit::DEPTH
- || subresource.m_depthStencilAspect == DepthStencilAspectBit::STENCIL
- || subresource.m_depthStencilAspect == DepthStencilAspectBit::NONE;
- }
- /// Return true if the subresource can be used in CommandBuffer::copyBufferToTextureView.
- Bool isSubresourceGoodForCopyFromBuffer(const TextureSubresourceInfo& subresource) const
- {
- ANKI_ASSERT(isSubresourceValid(subresource));
- return subresource.m_faceCount == 1 && subresource.m_mipmapCount == 1 && subresource.m_layerCount == 1
- && subresource.m_depthStencilAspect == DepthStencilAspectBit::NONE;
- }
- /// Return true if the subresource can be used as Framebuffer attachment.
- Bool isSubresourceGoodForFramebufferAttachment(const TextureSubresourceInfo& subresource) const
- {
- ANKI_ASSERT(isSubresourceValid(subresource));
- return subresource.m_faceCount == 1 && subresource.m_mipmapCount == 1 && subresource.m_layerCount == 1;
- }
- protected:
- U32 m_width = 0;
- U32 m_height = 0;
- U32 m_depth = 0;
- U32 m_layerCount = 0;
- U32 m_mipCount = 0;
- TextureType m_texType = TextureType::COUNT;
- TextureUsageBit m_usage = TextureUsageBit::NONE;
- Format m_format = Format::NONE;
- DepthStencilAspectBit m_aspect = DepthStencilAspectBit::NONE;
- /// Construct.
- Texture(GrManager* manager, CString name)
- : GrObject(manager, CLASS_TYPE, name)
- {
- }
- /// Destroy.
- ~Texture()
- {
- }
- private:
- /// Allocate and initialize a new instance.
- static ANKI_USE_RESULT Texture* newInstance(GrManager* manager, const TextureInitInfo& init);
- };
- /// @}
- } // end namespace anki
|