Overte C++ Documentation
Texture.h
1 //
2 // Texture.h
3 // libraries/gpu/src/gpu
4 //
5 // Created by Sam Gateau on 1/16/2015.
6 // Copyright 2014 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 #ifndef hifi_gpu_Texture_h
12 #define hifi_gpu_Texture_h
13 
14 #include <algorithm> //min max and more
15 #include <bitset>
16 
17 #include <QMetaType>
18 #include <QUrl>
19 
20 #include <functional>
21 #include <shared/Storage.h>
22 #include <shared/FileCache.h>
23 #include <RegisteredMetaTypes.h>
24 #include "Forward.h"
25 #include "Resource.h"
26 #include "Metric.h"
27 #include "Sampler.h"
28 #include "SerDes.h"
29 
30 const int ABSOLUTE_MAX_TEXTURE_NUM_PIXELS = 8192 * 8192;
31 
32 namespace ktx {
33  class KTX;
34  using KTXUniquePointer = std::unique_ptr<KTX>;
35  struct KTXDescriptor;
36  using KTXDescriptorPointer = std::unique_ptr<KTXDescriptor>;
37  struct Header;
38  struct KeyValue;
39  using KeyValues = std::list<KeyValue>;
40 }
41 
42 namespace khronos { namespace gl { namespace texture {
43  enum class InternalFormat: uint32_t;
44 }}}
45 
46 namespace gpu {
47 
48 enum class BackendTarget {
49  GL41,
50  GL45,
51  GLES32
52 };
53 
54 const std::string SOURCE_HASH_KEY { "hifi.sourceHash" };
55 
56 const uint8 SOURCE_HASH_BYTES = 16;
57 
58 // THe spherical harmonics is a nice tool for cubemap, so if required, the irradiance SH can be automatically generated
59 // with the cube texture
60 class Texture;
61 class SphericalHarmonics {
62 public:
63  glm::vec3 L00 ; float spare0;
64  glm::vec3 L1m1 ; float spare1;
65  glm::vec3 L10 ; float spare2;
66  glm::vec3 L11 ; float spare3;
67  glm::vec3 L2m2 ; float spare4;
68  glm::vec3 L2m1 ; float spare5;
69  glm::vec3 L20 ; float spare6;
70  glm::vec3 L21 ; float spare7;
71  glm::vec3 L22 ; float spare8;
72 
73  static const int NUM_COEFFICIENTS = 9;
74 
75  enum Preset {
76  OLD_TOWN_SQUARE = 0,
77  GRACE_CATHEDRAL,
78  EUCALYPTUS_GROVE,
79  ST_PETERS_BASILICA,
80  UFFIZI_GALLERY,
81  GALILEOS_TOMB,
82  VINE_STREET_KITCHEN,
83  BREEZEWAY,
84  CAMPUS_SUNSET,
85  FUNSTON_BEACH_SUNSET,
86 
87  NUM_PRESET,
88  };
89 
90  void assignPreset(int p);
91 
92  void evalFromTexture(const Texture& texture, gpu::BackendTarget target);
93 };
94 typedef std::shared_ptr< SphericalHarmonics > SHPointer;
95 
96 
97 inline DataSerializer &operator<<(DataSerializer &ser, const SphericalHarmonics &h) {
98  DataSerializer::SizeTracker tracker(ser);
99 
100  ser << h.L00 << h.spare0;
101  ser << h.L1m1 << h.spare1;
102  ser << h.L10 << h.spare2;
103  ser << h.L11 << h.spare3;
104  ser << h.L2m2 << h.spare4;
105  ser << h.L2m1 << h.spare5;
106  ser << h.L20 << h.spare6;
107  ser << h.L21 << h.spare7;
108  ser << h.L22 << h.spare8;
109  return ser;
110 }
111 
112 inline DataDeserializer &operator>>(DataDeserializer &des, SphericalHarmonics &h) {
113  DataDeserializer::SizeTracker tracker(des);
114 
115  des >> h.L00 >> h.spare0;
116  des >> h.L1m1 >> h.spare1;
117  des >> h.L10 >> h.spare2;
118  des >> h.L11 >> h.spare3;
119  des >> h.L2m2 >> h.spare4;
120  des >> h.L2m1 >> h.spare5;
121  des >> h.L20 >> h.spare6;
122  des >> h.L21 >> h.spare7;
123  des >> h.L22 >> h.spare8;
124  return des;
125 }
126 
127 enum class TextureUsageType : uint8 {
128  RENDERBUFFER, // Used as attachments to a framebuffer
129  RESOURCE, // Resource textures, like materials... subject to memory manipulation
130  STRICT_RESOURCE, // Resource textures not subject to manipulation, like the normal fitting texture
131  EXTERNAL,
132 };
133 
134 class Texture : public Resource {
135  static ContextMetricCount _textureCPUCount;
136  static ContextMetricSize _textureCPUMemSize;
137 
138  static std::atomic<Size> _allowedCPUMemoryUsage;
139  static std::atomic<bool> _enableSparseTextures;
140  static void updateTextureCPUMemoryUsage(Size prevObjectSize, Size newObjectSize);
141 
142 public:
143  static const uint32_t CUBE_FACE_COUNT { 6 };
144  static uint32_t getTextureCPUCount();
145  static Size getTextureCPUMemSize();
146 
147  static Size getAllowedGPUMemoryUsage();
148  static void setAllowedGPUMemoryUsage(Size size);
149 
150  static bool getEnableSparseTextures();
151  static void setEnableSparseTextures(bool enabled);
152 
153  using ExternalRecycler = std::function<void(uint32, void*)>;
154  using ExternalIdAndFence = std::pair<uint32, void*>;
155  using ExternalUpdates = std::list<ExternalIdAndFence>;
156 
157  class Usage {
158  public:
159  enum FlagBit {
160  COLOR = 0, // Texture is a color map
161  NORMAL, // Texture is a normal map
162  ALPHA, // Texture has an alpha channel
163  ALPHA_MASK, // Texture alpha channel is a Mask 0/1
164  NUM_FLAGS,
165  };
166 
167  typedef std::bitset<NUM_FLAGS> Flags;
168 
169  // The key is the Flags
170  Flags _flags;
171 
172  Usage() : _flags(0) {}
173  Usage(const Flags& flags) : _flags(flags) {}
174 
175  bool operator== (const Usage& rhs) const { return _flags == rhs._flags; }
176  bool operator!= (const Usage& rhs) const { return _flags != rhs._flags; }
177 
178  class Builder {
179  friend class Usage;
180  Flags _flags{ 0 };
181  public:
182  Builder() {}
183 
184  Usage build() const { return Usage(_flags); }
185 
186  Builder& withColor() { _flags.set(COLOR); return (*this); }
187  Builder& withNormal() { _flags.set(NORMAL); return (*this); }
188  Builder& withAlpha() { _flags.set(ALPHA); return (*this); }
189  Builder& withAlphaMask() { _flags.set(ALPHA_MASK); return (*this); }
190  };
191  Usage(const Builder& builder) : Usage(builder._flags) {}
192 
193  bool isColor() const { return _flags[COLOR]; }
194  bool isNormal() const { return _flags[NORMAL]; }
195 
196  bool isAlpha() const { return _flags[ALPHA]; }
197  bool isAlphaMask() const { return _flags[ALPHA_MASK]; }
198 
199  bool operator==(const Usage& usage) { return (_flags == usage._flags); }
200  bool operator!=(const Usage& usage) { return (_flags != usage._flags); }
201  };
202 
203  enum Type : uint8 {
204  TEX_1D = 0,
205  TEX_2D,
206  TEX_3D,
207  TEX_CUBE,
208 
209  NUM_TYPES,
210  };
211 
212  // Definition of the cube face name and layout
213  enum CubeFace {
214  CUBE_FACE_RIGHT_POS_X = 0,
215  CUBE_FACE_LEFT_NEG_X,
216  CUBE_FACE_TOP_POS_Y,
217  CUBE_FACE_BOTTOM_NEG_Y,
218  CUBE_FACE_BACK_POS_Z,
219  CUBE_FACE_FRONT_NEG_Z,
220 
221  NUM_CUBE_FACES, // Not a valid vace index
222  };
223 
224  // Lines of pixels are padded to be a multiple of "PACKING_SIZE" which is 4 bytes
225  static const uint32 PACKING_SIZE = 4;
226  static uint8 evalPaddingNumBytes(Size byteSize) { return (uint8) (3 - (byteSize + 3) % PACKING_SIZE); }
227  static Size evalPaddedSize(Size byteSize) { return byteSize + (Size) evalPaddingNumBytes(byteSize); }
228 
229 
230  using PixelsPointer = storage::StoragePointer;
231  class Storage {
232  public:
233  Storage() {}
234  virtual ~Storage() {}
235 
236  virtual void reset() = 0;
237  virtual PixelsPointer getMipFace(uint16 level, uint8 face = 0) const = 0;
238  virtual Size getMipFaceSize(uint16 level, uint8 face = 0) const = 0;
239  virtual void assignMipData(uint16 level, const storage::StoragePointer& storage) = 0;
240  virtual void assignMipFaceData(uint16 level, uint8 face, const storage::StoragePointer& storage) = 0;
241  virtual bool isMipAvailable(uint16 level, uint8 face = 0) const = 0;
242  virtual uint16 minAvailableMipLevel() const { return 0; }
243  Texture::Type getType() const { return _type; }
244 
245  Stamp getStamp() const { return _stamp; }
246  Stamp bumpStamp() { return ++_stamp; }
247 
248  void setFormat(const Element& format) { _format = format; }
249  Element getFormat() const { return _format; }
250 
251  private:
252  Stamp _stamp { 0 };
253  Element _format;
254  Texture::Type _type { Texture::TEX_2D }; // The type of texture is needed to know the number of faces to expect
255  Texture* _texture { nullptr }; // Points to the parent texture (not owned)
256  virtual void assignTexture(Texture* tex); // Texture storage is pointing to ONE corrresponding Texture.
257  const Texture* getTexture() const { return _texture; }
258  friend class Texture;
259  };
260 
261  class MemoryStorage : public Storage {
262  public:
263  void reset() override;
264  PixelsPointer getMipFace(uint16 level, uint8 face = 0) const override;
265  Size getMipFaceSize(uint16 level, uint8 face = 0) const override;
266  void assignMipData(uint16 level, const storage::StoragePointer& storage) override;
267  void assignMipFaceData(uint16 level, uint8 face, const storage::StoragePointer& storage) override;
268  bool isMipAvailable(uint16 level, uint8 face = 0) const override;
269 
270  protected:
271  void allocateMip(uint16 level);
272  std::vector<std::vector<PixelsPointer>> _mips; // an array of mips, each mip is an array of faces
273  };
274 
275  class KtxStorage : public Storage {
276  public:
277  KtxStorage(const storage::StoragePointer& storage);
278  KtxStorage(const std::string& filename);
279  KtxStorage(const cache::FilePointer& file);
280  PixelsPointer getMipFace(uint16 level, uint8 face = 0) const override;
281  Size getMipFaceSize(uint16 level, uint8 face = 0) const override;
282  bool isMipAvailable(uint16 level, uint8 face = 0) const override;
283  void assignMipData(uint16 level, const storage::StoragePointer& storage) override;
284  void assignMipFaceData(uint16 level, uint8 face, const storage::StoragePointer& storage) override;
285  uint16 minAvailableMipLevel() const override;
286 
287  void reset() override { }
288 
289  // Don't keep files open forever. We close them at the beginning of each frame (GLBackend::recycle)
290  static void releaseOpenKtxFiles();
291 
292  protected:
293  std::shared_ptr<storage::FileStorage> maybeOpenFile() const;
294 
295  mutable std::shared_ptr<std::mutex> _cacheFileMutex { std::make_shared<std::mutex>() };
296  mutable std::weak_ptr<storage::FileStorage> _cacheFile;
297 
298  static std::vector<std::pair<std::shared_ptr<storage::FileStorage>, std::shared_ptr<std::mutex>>> _cachedKtxFiles;
299  static std::mutex _cachedKtxFilesMutex;
300 
301  storage::StoragePointer _storage;
302  std::string _filename;
303  cache::FilePointer _cacheEntry;
304  std::atomic<uint8_t> _minMipLevelAvailable;
305  size_t _offsetToMinMipKV;
306 
307  ktx::KTXDescriptorPointer _ktxDescriptor;
308  friend class Texture;
309  friend class Serializer;
310  friend class Deserializer;
311  };
312 
313  uint16 minAvailableMipLevel() const { return _storage->minAvailableMipLevel(); };
314 
315  static const uint16 MAX_NUM_MIPS = 0;
316  static const uint16 SINGLE_MIP = 1;
317  static TexturePointer create1D(const Element& texelFormat, uint16 width, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler());
318  static TexturePointer create2D(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler());
319  static TexturePointer create2DArray(const Element& texelFormat, uint16 width, uint16 height, uint16 numSlices, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler());
320  static TexturePointer create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler());
321  static TexturePointer createCube(const Element& texelFormat, uint16 width, uint16 numMips = 1, const Sampler& sampler = Sampler());
322  static TexturePointer createRenderBuffer(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler());
323  static TexturePointer createRenderBufferMultisample(const Element& texelFormat, uint16 width, uint16 height, uint16 numSamples, const Sampler& sampler = Sampler());
324  static TexturePointer createRenderBufferArray(const Element& texelFormat, uint16 width, uint16 height, uint16 numSlices, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler());
325  static TexturePointer createRenderBufferMultisampleArray(const Element& texelFormat, uint16 width, uint16 height, uint16 numSlices, uint16 numSamples, const Sampler& sampler = Sampler());
326  static TexturePointer createStrict(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler());
327  static TexturePointer createExternal(const ExternalRecycler& recycler, const Sampler& sampler = Sampler());
328 
329  // After the texture has been created, it should be defined
330  bool isDefined() const { return _defined; }
331 
332  Texture(TextureUsageType usageType);
333  ~Texture();
334 
335  Stamp getStamp() const { return _stamp; }
336  Stamp getDataStamp() const { return _storage->getStamp(); }
337 
338  // The theoretical size in bytes of data stored in the texture
339  // For the primary (level) first level of mip
340  Size getSize() const override { return _size; }
341 
342  // Size and format
343  Type getType() const { return _type; }
344  TextureUsageType getUsageType() const { return _usageType; }
345 
346  bool isDepthStencilRenderTarget() const;
347 
348  Element getTexelFormat() const { return _texelFormat; }
349 
350  void setSize(int width, int height);
351  Vec3u getDimensions() const { return Vec3u(_width, _height, _depth); }
352  uint16 getWidth() const { return _width; }
353  uint16 getHeight() const { return _height; }
354  uint16 getDepth() const { return _depth; }
355 
356  void setOriginalSize(int width, int height);
357  int getOriginalWidth() const { return _originalWidth; }
358  int getOriginalHeight() const { return _originalHeight; }
359 
360  // The number of faces is mostly used for cube map, and maybe for stereo ? otherwise it's 1
361  // For cube maps, this means the pixels of the different faces are supposed to be packed back to back in a mip
362  // as if the height was NUM_FACES time bigger.
363  static uint8 NUM_FACES_PER_TYPE[NUM_TYPES];
364  uint8 getNumFaces() const { return NUM_FACES_PER_TYPE[getType()]; }
365 
366  // The texture is an array if the _numSlices is not 0.
367  // otherwise, if _numSLices is 0, then the texture is NOT an array
368  // The number of slices returned is 1 at the minimum (if not an array) or the actual _numSlices.
369  bool isArray() const { return _numSlices > 0; }
370  uint16 getNumSlices() const { return (isArray() ? _numSlices : 1); }
371 
372  uint16 getNumSamples() const { return _numSamples; }
373  // NumSamples can only have certain values based on the hw
374  static uint16 evalNumSamplesUsed(uint16 numSamplesTried);
375  bool isMultisample() const { return _numSamples > 1; }
376 
377  // max mip is in the range [ 0 if no sub mips, log2(max(width, height, depth))]
378  // It is defined at creation time (immutable)
379  uint16 getMaxMip() const { return _maxMipLevel; }
380  uint16 getNumMips() const { return _maxMipLevel + 1; }
381 
382  // Mips size evaluation
383 
384  // The number mips that a dimension could haves
385  // = 1 + log2(size)
386  static uint16 evalDimMaxNumMips(uint16 size);
387 
388  // The number mips that the texture could have if all existed
389  // = 1 + log2(max(width, height, depth))
390  uint16 evalMaxNumMips() const;
391  static uint16 evalMaxNumMips(const Vec3u& dimensions);
392 
393  // Check a num of mips requested against the maximum possible specified
394  // if passing -1 then answer the max
395  // simply does (askedNumMips == -1 ? maxMips : (numstd::min(askedNumMips, max))
396  static uint16 safeNumMips(uint16 askedNumMips, uint16 maxMips);
397 
398  // Same but applied to this texture's num max mips from evalNumMips()
399  uint16 safeNumMips(uint16 askedNumMips) const;
400 
401  // Eval the dimensions & sizes that the mips level SHOULD have
402  // not the one stored in the Texture
403 
404  // Dimensions
405  Vec3u evalMipDimensions(uint16 level) const;
406  uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); }
407  uint16 evalMipHeight(uint16 level) const { return std::max(_height >> level, 1); }
408  uint16 evalMipDepth(uint16 level) const { return std::max(_depth >> level, 1); }
409 
410  // The true size of an image line or surface depends on the format, tiling and padding rules
411  //
412  // Here are the static function to compute the different sizes from parametered dimensions and format
413  // Tile size must be a power of 2
414  static uint16 evalTiledPadding(uint16 length, int tile) { int tileMinusOne = (tile - 1); return (tileMinusOne - (length + tileMinusOne) % tile); }
415  static uint16 evalTiledLength(uint16 length, int tile) { return length / tile + (evalTiledPadding(length, tile) != 0); }
416  static uint16 evalTiledWidth(uint16 width, int tileX) { return evalTiledLength(width, tileX); }
417  static uint16 evalTiledHeight(uint16 height, int tileY) { return evalTiledLength(height, tileY); }
418  static Size evalLineSize(uint16 width, const Element& format) { return evalPaddedSize(evalTiledWidth(width, format.getTile().x) * format.getSize()); }
419  static Size evalSurfaceSize(uint16 width, uint16 height, const Element& format) { return evalLineSize(width, format) * evalTiledHeight(height, format.getTile().x); }
420 
421  // Compute the theorical size of the texture elements storage depending on the specified format
422  Size evalStoredMipLineSize(uint16 level, const Element& format) const { return evalLineSize(evalMipWidth(level), format); }
423  Size evalStoredMipSurfaceSize(uint16 level, const Element& format) const { return evalSurfaceSize(evalMipWidth(level), evalMipHeight(level), format); }
424  Size evalStoredMipFaceSize(uint16 level, const Element& format) const { return evalStoredMipSurfaceSize(level, format) * evalMipDepth(level); }
425  Size evalStoredMipSize(uint16 level, const Element& format) const { return evalStoredMipFaceSize(level, format) * getNumFaces(); }
426 
427  // For this texture's texel format and dimensions, compute the various mem sizes
428  Size evalMipLineSize(uint16 level) const { return evalStoredMipLineSize(level, getTexelFormat()); }
429  Size evalMipSurfaceSize(uint16 level) const { return evalStoredMipSurfaceSize(level, getTexelFormat()); }
430  Size evalMipFaceSize(uint16 level) const { return evalStoredMipFaceSize(level, getTexelFormat()); }
431  Size evalMipSize(uint16 level) const { return evalStoredMipSize(level, getTexelFormat()); }
432 
433  // Total size for all the mips of the texture
434  Size evalTotalSize(uint16 startingMip = 0) const;
435 
436  // Number of texels (not it s not directly proprtional to the size!
437  uint32 evalMipFaceNumTexels(uint16 level) const { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); }
438  uint32 evalMipNumTexels(uint16 level) const { return evalMipFaceNumTexels(level) * getNumFaces(); }
439 
440  // For convenience assign a source name
441  const std::string& source() const { return _source; }
442  void setSource(const std::string& source) { _source = source; }
443  const std::string& sourceHash() const { return _sourceHash; }
444  void setSourceHash(const std::string& sourceHash) { _sourceHash = sourceHash; }
445 
446  // Potentially change the minimum mip (mostly for debugging purpose)
447  bool setMinMip(uint16 newMinMip);
448  bool incremementMinMip(uint16 count = 1);
449  uint16 getMinMip() const { return _minMip; }
450  uint16 usedMipLevels() const { return (getNumMips() - _minMip); }
451 
452  // Generate the sub mips automatically for the texture
453  // If the storage version is not available (from CPU memory)
454  // Only works for the standard formats
455  void setAutoGenerateMips(bool enable);
456  bool isAutogenerateMips() const { return _autoGenerateMips; }
457 
458  // Managing Storage and mips
459 
460  // Mip storage format is constant across all mips
461  void setStoredMipFormat(const Element& format);
462  Element getStoredMipFormat() const;
463 
464  // Manually allocate the mips down until the specified maxMip
465  // this is just allocating the sysmem version of it
466  // in case autoGen is on, this doesn't allocate
467  // Explicitely assign mip data for a certain level
468  // If Bytes is NULL then simply allocate the space so mip sysmem can be accessed
469  void assignStoredMip(uint16 level, Size size, const Byte* bytes);
470  void assignStoredMipFace(uint16 level, uint8 face, Size size, const Byte* bytes);
471 
472  void assignStoredMip(uint16 level, storage::StoragePointer& storage);
473  void assignStoredMipFace(uint16 level, uint8 face, storage::StoragePointer& storage);
474 
475  // Access the stored mips and faces
476  const PixelsPointer accessStoredMipFace(uint16 level, uint8 face = 0) const { return _storage->getMipFace(level, face); }
477  bool isStoredMipFaceAvailable(uint16 level, uint8 face = 0) const;
478  Size getStoredMipFaceSize(uint16 level, uint8 face = 0) const { return _storage->getMipFaceSize(level, face); }
479  Size getStoredMipSize(uint16 level) const;
480  Size getStoredSize() const;
481 
482  void setStorage(std::unique_ptr<Storage>& newStorage);
483  void setKtxBacking(const storage::StoragePointer& storage);
484  void setKtxBacking(const std::string& filename);
485  void setKtxBacking(const cache::FilePointer& cacheEntry);
486 
487  // Usage is a a set of flags providing Semantic about the usage of the Texture.
488  void setUsage(const Usage& usage) { _usage = usage; }
489  Usage getUsage() const { return _usage; }
490 
491  // For Cube Texture, it's possible to generate the irradiance spherical harmonics and make them available with the texture
492  bool generateIrradiance(gpu::BackendTarget target);
493  const SHPointer& getIrradiance(uint16 slice = 0) const { return _irradiance; }
494  void overrideIrradiance(SHPointer irradiance) { _irradiance = irradiance; }
495  bool isIrradianceValid() const { return _isIrradianceValid; }
496 
497  // Own sampler
498  void setSampler(const Sampler& sampler);
499  const Sampler& getSampler() const { return _sampler; }
500  Stamp getSamplerStamp() const { return _samplerStamp; }
501 
502  void setFallbackTexture(const TexturePointer& fallback) { _fallback = fallback; }
503  TexturePointer getFallbackTexture() const { return _fallback.lock(); }
504 
505  void setExternalTexture(uint32 externalId, void* externalFence);
506  void setExternalRecycler(const ExternalRecycler& recycler);
507  ExternalRecycler getExternalRecycler() const;
508 
509  bool getImportant() const { return _important; }
510  void setImportant(bool important) { _important = important; }
511 
512  const GPUObjectPointer gpuObject {};
513 
514  ExternalUpdates getUpdates() const;
515 
516  // Serialize a texture into a KTX file
517  static ktx::KTXUniquePointer serialize(const Texture& texture, const glm::ivec2& originalSize);
518 
519  static std::pair<TexturePointer, glm::ivec2> build(const ktx::KTXDescriptor& descriptor);
520  static std::pair<TexturePointer, glm::ivec2> unserialize(const std::string& ktxFile);
521  static std::pair<TexturePointer, glm::ivec2> unserialize(const cache::FilePointer& cacheEntry, const std::string& source = std::string());
522 
523  static bool evalKTXFormat(const Element& mipFormat, const Element& texelFormat, ktx::Header& header);
524  static bool evalTextureFormat(const ktx::Header& header, Element& mipFormat, Element& texelFormat);
525  static bool getCompressedFormat(khronos::gl::texture::InternalFormat format, Element& elFormat);
526 
527 protected:
528  const TextureUsageType _usageType;
529 
530  // Should only be accessed internally or by the backend sync function
531  mutable Mutex _externalMutex;
532  mutable std::list<ExternalIdAndFence> _externalUpdates;
533  ExternalRecycler _externalRecycler;
534 
535 
536  std::weak_ptr<Texture> _fallback;
537  // Not strictly necessary, but incredibly useful for debugging
538  std::string _source;
539  std::string _sourceHash;
540  std::unique_ptr< Storage > _storage;
541 
542  Stamp _stamp { 0 };
543 
544  Sampler _sampler;
545  Stamp _samplerStamp { 0 };
546 
547  Size _size { 0 };
548  Element _texelFormat;
549 
550  uint16 _width { 1 };
551  uint16 _height { 1 };
552  uint16 _depth { 1 };
553  int _originalWidth { 0 };
554  int _originalHeight { 0 };
555 
556  uint16 _numSamples { 1 };
557 
558  // if _numSlices is 0, the texture is not an "Array", the getNumSlices reported is 1
559  uint16 _numSlices { 0 };
560 
561  // valid _maxMipLevel is in the range [ 0 if no sub mips, log2(max(width, height, depth) ]
562  // The num of mips returned is _maxMipLevel + 1
563  uint16 _maxMipLevel { 0 };
564 
565  uint16 _minMip { 0 };
566 
567  Type _type { TEX_1D };
568 
569  Usage _usage;
570 
571  SHPointer _irradiance;
572  bool _autoGenerateMips = false;
573  bool _isIrradianceValid = false;
574  bool _defined = false;
575  bool _important = false;
576 
577  static TexturePointer create(TextureUsageType usageType, Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, uint16 numMips, const Sampler& sampler);
578 
579  Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, uint16 numMips);
580 
581  friend class Serializer;
582  friend class Deserializer;
583 };
584 
585 typedef std::shared_ptr<Texture> TexturePointer;
586 typedef std::vector< TexturePointer > Textures;
587 
588  // TODO: For now TextureView works with Texture as a place holder for the Texture.
589  // The overall logic should be about the same except that the Texture will be a real GL Texture under the hood
590 class TextureView {
591 public:
592  typedef Resource::Size Size;
593 
594  TexturePointer _texture = TexturePointer(NULL);
595  uint16 _subresource = 0;
596  Element _element = Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
597 
598  TextureView() {};
599 
600  TextureView(const Element& element) :
601  _element(element)
602  {};
603 
604  // create the TextureView and own the Texture
605  TextureView(Texture* newTexture, const Element& element) :
606  _texture(newTexture),
607  _subresource(0),
608  _element(element)
609  {};
610  TextureView(const TexturePointer& texture, uint16 subresource, const Element& element) :
611  _texture(texture),
612  _subresource(subresource),
613  _element(element)
614  {};
615 
616  TextureView(const TexturePointer& texture, uint16 subresource, std::function<gpu::TexturePointer()> textureOperator = nullptr) :
617  _texture(texture),
618  _subresource(subresource),
619  _textureOperator(textureOperator)
620  {};
621 
622  ~TextureView() {}
623  TextureView(const TextureView& view) = default;
624  TextureView& operator=(const TextureView& view) = default;
625 
626  explicit operator bool() const { return bool(_texture); }
627  bool operator !() const { return (!_texture); }
628 
629  bool isValid() const { return bool(_texture); }
630 
631  bool isReference() const { return (bool)_textureOperator; }
632  std::function<gpu::TexturePointer()> getTextureOperator() const { return _textureOperator; }
633 
634 private:
635  std::function<gpu::TexturePointer()> _textureOperator { nullptr };
636 };
637 typedef std::vector<TextureView> TextureViews;
638 
639 // TextureSource is the bridge between a URL or a a way to produce an image and the final gpu::Texture that will be used to render it.
640 // It provides the mechanism to create a texture using a customizable TextureLoader
641 class TextureSource {
642 public:
643  TextureSource(const QUrl& url, int type = 0) : _imageUrl(url), _type(type) {}
644 
645  void setUrl(const QUrl& url) { _imageUrl = url; }
646  const QUrl& getUrl() const { return _imageUrl; }
647  const gpu::TexturePointer getGPUTexture() const;
648  void setType(int type) { _type = type; }
649  int getType() const { return _type; }
650 
651  void resetTexture(const gpu::TexturePointer& texture);
652  void resetTextureOperator(const std::function<gpu::TexturePointer()>& textureOperator);
653 
654  bool isDefined() const;
655  std::function<gpu::TexturePointer()> getTextureOperator() const { return _gpuTextureOperator; }
656 
657  void setSampler(const Sampler& sampler);
658 
659 protected:
660  gpu::TexturePointer _gpuTexture;
661  std::function<gpu::TexturePointer()> _gpuTextureOperator { nullptr };
662  mutable bool _locked { false };
663  QUrl _imageUrl;
664  int _type { 0 };
665 };
666 typedef std::shared_ptr< TextureSource > TextureSourcePointer;
667 
668 };
669 
670 Q_DECLARE_METATYPE(gpu::TexturePointer)
671 
672 #endif
RAII tracker of advance position.
Definition: SerDes.h:594
Data deserializer.
Definition: SerDes.h:573
RAII tracker of advance position.
Definition: SerDes.h:82
Data serializer.
Definition: SerDes.h:61
Base class for resources.
Definition: ResourceCache.h:415
A simple object wrapper for an OpenGL texture.
Definition: material-networking/src/material-networking/TextureCache.h:39