1 /// @brief Include to use generic textures which can represent any texture target but they don't have target specific built-in caches making accesses slower. 2 /// @file gli/texture.hpp 3 4 #pragma once 5 6 #include "image.hpp" 7 #include "target.hpp" 8 #include "levels.hpp" 9 #include <array> 10 11 namespace gli 12 { 13 /// Genetic texture class. It can support any target. 14 class texture 15 { 16 public: 17 typedef size_t size_type; 18 typedef gli::target target_type; 19 typedef gli::format format_type; 20 typedef gli::swizzles swizzles_type; 21 typedef storage_linear storage_type; 22 typedef storage_type::data_type data_type; 23 typedef storage_type::extent_type extent_type; 24 25 /// Create an empty texture instance 26 texture(); 27 28 /// Create a texture object and allocate a texture storage for it 29 /// @param Target Type/Shape of the texture storage_linear 30 /// @param Format Texel format 31 /// @param Extent Size of the texture: width, height and depth. 32 /// @param Layers Number of one-dimensional or two-dimensional images of identical size and format 33 /// @param Faces 6 for cube map textures otherwise 1. 34 /// @param Levels Number of images in the texture mipmap chain. 35 /// @param Swizzles A mechanism to swizzle the components of a texture before they are applied according to the texture environment. 36 texture( 37 target_type Target, 38 format_type Format, 39 extent_type const& Extent, 40 size_type Layers, 41 size_type Faces, 42 size_type Levels, 43 swizzles_type const& Swizzles = swizzles_type(SWIZZLE_RED, SWIZZLE_GREEN, SWIZZLE_BLUE, SWIZZLE_ALPHA)); 44 45 /// Create a texture object by sharing an existing texture storage_type from another texture instance. 46 /// This texture object is effectively a texture view where the layer, the face and the level allows identifying 47 /// a specific subset of the texture storage_linear source. 48 /// This texture object is effectively a texture view where the target and format can be reinterpreted 49 /// with a different compatible texture target and texture format. 50 texture( 51 texture const& Texture, 52 target_type Target, 53 format_type Format, 54 size_type BaseLayer, size_type MaxLayer, 55 size_type BaseFace, size_type MaxFace, 56 size_type BaseLevel, size_type MaxLevel, 57 swizzles_type const& Swizzles = swizzles_type(SWIZZLE_RED, SWIZZLE_GREEN, SWIZZLE_BLUE, SWIZZLE_ALPHA)); 58 59 /// Create a texture object by sharing an existing texture storage_type from another texture instance. 60 /// This texture object is effectively a texture view where the target and format can be reinterpreted 61 /// with a different compatible texture target and texture format. 62 texture( 63 texture const& Texture, 64 target_type Target, 65 format_type Format, 66 swizzles_type const& Swizzles = swizzles_type(SWIZZLE_RED, SWIZZLE_GREEN, SWIZZLE_BLUE, SWIZZLE_ALPHA)); 67 ~texture()68 virtual ~texture(){} 69 70 /// Return whether the texture instance is empty, no storage_type or description have been assigned to the instance. 71 bool empty() const; 72 73 /// Return the target of a texture instance. target() const74 target_type target() const{return this->Target;} 75 76 /// Return the texture instance format 77 format_type format() const; 78 79 swizzles_type swizzles() const; 80 81 /// Return the base layer of the texture instance, effectively a memory offset in the actual texture storage_type to identify where to start reading the layers. 82 size_type base_layer() const; 83 84 /// Return the max layer of the texture instance, effectively a memory offset to the beginning of the last layer in the actual texture storage_type that the texture instance can access. 85 size_type max_layer() const; 86 87 /// Return max_layer() - base_layer() + 1 88 size_type layers() const; 89 90 /// Return the base face of the texture instance, effectively a memory offset in the actual texture storage_type to identify where to start reading the faces. 91 size_type base_face() const; 92 93 /// Return the max face of the texture instance, effectively a memory offset to the beginning of the last face in the actual texture storage_type that the texture instance can access. 94 size_type max_face() const; 95 96 /// Return max_face() - base_face() + 1 97 size_type faces() const; 98 99 /// Return the base level of the texture instance, effectively a memory offset in the actual texture storage_type to identify where to start reading the levels. 100 size_type base_level() const; 101 102 /// Return the max level of the texture instance, effectively a memory offset to the beginning of the last level in the actual texture storage_type that the texture instance can access. 103 size_type max_level() const; 104 105 /// Return max_level() - base_level() + 1. 106 size_type levels() const; 107 108 /// Return the size of a texture instance: width, height and depth. 109 extent_type extent(size_type Level = 0) const; 110 111 /// Return the memory size of a texture instance storage_type in bytes. 112 size_type size() const; 113 114 /// Return the number of blocks contained in a texture instance storage_type. 115 /// genType size must match the block size conresponding to the texture format. 116 template <typename genType> 117 size_type size() const; 118 119 /// Return the memory size of a specific level identified by Level. 120 size_type size(size_type Level) const; 121 122 /// Return the memory size of a specific level identified by Level. 123 /// genType size must match the block size conresponding to the texture format. 124 template <typename gen_type> 125 size_type size(size_type Level) const; 126 127 /// Return a pointer to the beginning of the texture instance data. 128 void* data(); 129 130 /// Return a pointer of type genType which size must match the texture format block size 131 template <typename gen_type> 132 gen_type* data(); 133 134 /// Return a pointer to the beginning of the texture instance data. 135 void const* data() const; 136 137 /// Return a pointer of type genType which size must match the texture format block size 138 template <typename gen_type> 139 gen_type const* data() const; 140 141 /// Return a pointer to the beginning of the texture instance data. 142 void* data(size_type Layer, size_type Face, size_type Level); 143 144 /// Return a pointer to the beginning of the texture instance data. 145 void const* const data(size_type Layer, size_type Face, size_type Level) const; 146 147 /// Return a pointer of type genType which size must match the texture format block size 148 template <typename gen_type> 149 gen_type* data(size_type Layer, size_type Face, size_type Level); 150 151 /// Return a pointer of type genType which size must match the texture format block size 152 template <typename gen_type> 153 gen_type const* const data(size_type Layer, size_type Face, size_type Level) const; 154 155 /// Clear the entire texture storage_linear with zeros 156 void clear(); 157 158 /// Clear the entire texture storage_linear with Texel which type must match the texture storage_linear format block size 159 /// If the type of gen_type doesn't match the type of the texture format, no conversion is performed and the data will be reinterpreted as if is was of the texture format. 160 template <typename gen_type> 161 void clear(gen_type const& Texel); 162 163 /// Clear a specific image of a texture. 164 template <typename gen_type> 165 void clear(size_type Layer, size_type Face, size_type Level, gen_type const& BlockData); 166 167 /// Clear a subset of a specific image of a texture. 168 template <typename gen_type> 169 void clear(size_type Layer, size_type Face, size_type Level, extent_type const& TexelOffset, extent_type const& TexelExtent, gen_type const& BlockData); 170 171 /// Copy a specific image of a texture 172 void copy( 173 texture const& TextureSrc, 174 size_t LayerSrc, size_t FaceSrc, size_t LevelSrc, 175 size_t LayerDst, size_t FaceDst, size_t LevelDst); 176 177 /// Copy a subset of a specific image of a texture 178 void copy( 179 texture const& TextureSrc, 180 size_t LayerSrc, size_t FaceSrc, size_t LevelSrc, extent_type const& OffsetSrc, 181 size_t LayerDst, size_t FaceDst, size_t LevelDst, extent_type const& OffsetDst, 182 extent_type const& Extent); 183 184 /// Reorder the component in texture memory. 185 template <typename gen_type> 186 void swizzle(gli::swizzles const& Swizzles); 187 188 /// Fetch a texel from a texture. The texture format must be uncompressed. 189 template <typename gen_type> 190 gen_type load(extent_type const & TexelCoord, size_type Layer, size_type Face, size_type Level) const; 191 192 /// Write a texel to a texture. The texture format must be uncompressed. 193 template <typename gen_type> 194 void store(extent_type const& TexelCoord, size_type Layer, size_type Face, size_type Level, gen_type const& Texel); 195 196 protected: 197 std::shared_ptr<storage_type> Storage; 198 target_type Target; 199 format_type Format; 200 size_type BaseLayer; 201 size_type MaxLayer; 202 size_type BaseFace; 203 size_type MaxFace; 204 size_type BaseLevel; 205 size_type MaxLevel; 206 swizzles_type Swizzles; 207 208 // Pre compute at texture instance creation some information for faster access to texels 209 struct cache 210 { 211 public: 212 enum ctor 213 { 214 DEFAULT 215 }; 216 cachegli::texture::cache217 explicit cache(ctor) 218 {} 219 cachegli::texture::cache220 cache 221 ( 222 storage_type& Storage, 223 format_type Format, 224 size_type BaseLayer, size_type Layers, 225 size_type BaseFace, size_type MaxFace, 226 size_type BaseLevel, size_type MaxLevel 227 ) 228 : Faces(MaxFace - BaseFace + 1) 229 , Levels(MaxLevel - BaseLevel + 1) 230 { 231 GLI_ASSERT(static_cast<size_t>(gli::levels(Storage.extent(0))) < this->ImageMemorySize.size()); 232 233 this->BaseAddresses.resize(Layers * this->Faces * this->Levels); 234 235 for(size_type Layer = 0; Layer < Layers; ++Layer) 236 for(size_type Face = 0; Face < this->Faces; ++Face) 237 for(size_type Level = 0; Level < this->Levels; ++Level) 238 { 239 size_type const Index = index_cache(Layer, Face, Level); 240 this->BaseAddresses[Index] = Storage.data() + Storage.base_offset( 241 BaseLayer + Layer, BaseFace + Face, BaseLevel + Level); 242 } 243 244 for(size_type Level = 0; Level < this->Levels; ++Level) 245 { 246 extent_type const& SrcExtent = Storage.extent(BaseLevel + Level); 247 extent_type const& DstExtent = SrcExtent * block_extent(Format) / Storage.block_extent(); 248 249 this->ImageExtent[Level] = glm::max(DstExtent, extent_type(1)); 250 this->ImageMemorySize[Level] = Storage.level_size(BaseLevel + Level); 251 } 252 253 this->GlobalMemorySize = Storage.layer_size(BaseFace, MaxFace, BaseLevel, MaxLevel) * Layers; 254 } 255 256 // Base addresses of each images of a texture. get_base_addressgli::texture::cache257 data_type* get_base_address(size_type Layer, size_type Face, size_type Level) const 258 { 259 return this->BaseAddresses[index_cache(Layer, Face, Level)]; 260 } 261 262 // In texels get_extentgli::texture::cache263 extent_type get_extent(size_type Level) const 264 { 265 return this->ImageExtent[Level]; 266 }; 267 268 // In bytes get_memory_sizegli::texture::cache269 size_type get_memory_size(size_type Level) const 270 { 271 return this->ImageMemorySize[Level]; 272 }; 273 274 // In bytes get_memory_sizegli::texture::cache275 size_type get_memory_size() const 276 { 277 return this->GlobalMemorySize; 278 }; 279 280 private: index_cachegli::texture::cache281 size_type index_cache(size_type Layer, size_type Face, size_type Level) const 282 { 283 return ((Layer * this->Faces) + Face) * this->Levels + Level; 284 } 285 286 size_type Faces; 287 size_type Levels; 288 std::vector<data_type*> BaseAddresses; 289 std::array<extent_type, 16> ImageExtent; 290 std::array<size_type, 16> ImageMemorySize; 291 size_type GlobalMemorySize; 292 } Cache; 293 }; 294 }//namespace gli 295 296 #include "./core/texture.inl" 297 298