vt.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * Copyright 2018 Ales Mlakar. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
  4. */
  5. /*
  6. * Reference(s):
  7. * - Sparse Virtual Textures by Sean Barrett
  8. * http://web.archive.org/web/20190103162611/http://silverspaceship.com/src/svt/
  9. * - Based on Virtual Texture Demo by Brad Blanchard
  10. * http://web.archive.org/web/20190103162638/http://linedef.com/virtual-texture-demo.html
  11. * - Mars texture
  12. * http://web.archive.org/web/20190103162730/http://www.celestiamotherlode.net/catalog/mars.php
  13. */
  14. #pragma once
  15. #include <bimg/decode.h>
  16. #include <tinystl/allocator.h>
  17. #include <tinystl/unordered_set.h>
  18. #include <tinystl/vector.h>
  19. #include <functional>
  20. #include "common.h"
  21. #include "bgfx_utils.h"
  22. #include <stdio.h> // FILE
  23. namespace vt
  24. {
  25. // Forward declarations
  26. class PageCache;
  27. class TextureAtlas;
  28. class TileDataFile;
  29. // Point
  30. struct Point
  31. {
  32. int m_x, m_y;
  33. };
  34. // Rect
  35. struct Rect
  36. {
  37. int minX() const
  38. {
  39. return m_x;
  40. }
  41. int minY() const
  42. {
  43. return m_y;
  44. }
  45. int maxX() const
  46. {
  47. return m_x + m_width;
  48. }
  49. int maxY() const
  50. {
  51. return m_y + m_height;
  52. }
  53. bool contains(const Point& p) const
  54. {
  55. return p.m_x >= minX() && p.m_y >= minY() && p.m_x < maxX() && p.m_y < maxY();
  56. }
  57. int m_x, m_y, m_width, m_height;
  58. };
  59. // Color
  60. struct Color
  61. {
  62. uint8_t m_r, m_g, m_b, m_a;
  63. };
  64. // Page
  65. struct Page
  66. {
  67. operator size_t() const;
  68. int m_x;
  69. int m_y;
  70. int m_mip;
  71. };
  72. // PageCount
  73. struct PageCount
  74. {
  75. Page m_page;
  76. int m_count;
  77. PageCount(Page _page, int _count);
  78. int compareTo(const PageCount& other) const;
  79. };
  80. // VirtualTextureInfo
  81. struct VirtualTextureInfo
  82. {
  83. VirtualTextureInfo();
  84. int GetPageSize() const;
  85. int GetPageTableSize() const;
  86. int m_virtualTextureSize = 0;
  87. int m_tileSize = 0;
  88. int m_borderSize = 0;
  89. };
  90. // StagingPool
  91. class StagingPool
  92. {
  93. public:
  94. StagingPool(int _width, int _height, int _count, bool _readBack);
  95. ~StagingPool();
  96. void grow(int count);
  97. bgfx::TextureHandle getTexture();
  98. void next();
  99. private:
  100. tinystl::vector<bgfx::TextureHandle> m_stagingTextures;
  101. int m_stagingTextureIndex;
  102. int m_width;
  103. int m_height;
  104. uint64_t m_flags;
  105. };
  106. // PageIndexer
  107. struct PageIndexer
  108. {
  109. public:
  110. PageIndexer(VirtualTextureInfo* _info);
  111. int getIndexFromPage(Page page);
  112. Page getPageFromIndex(int index);
  113. bool isValid(Page page);
  114. int getCount() const;
  115. int getMipCount() const;
  116. private:
  117. VirtualTextureInfo* m_info;
  118. int m_mipcount;
  119. int m_count;
  120. tinystl::vector<int> m_offsets; // This stores the offsets to the first page of the start of a mipmap level
  121. tinystl::vector<int> m_sizes; // This stores the sizes of various mip levels
  122. tinystl::vector<Page> m_reverse;
  123. };
  124. // SimpleImage
  125. struct SimpleImage
  126. {
  127. SimpleImage(int _width, int _height, int _channelCount, uint8_t _clearValue = 0);
  128. SimpleImage(int _width, int _height, int _channelCount, tinystl::vector<uint8_t>& _data);
  129. void copy(Point dest_offset, SimpleImage& src, Rect src_rect);
  130. void clear(uint8_t clearValue = 0);
  131. void fill(Rect rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
  132. static void mipmap(uint8_t* source, int size, int channels, uint8_t* dest);
  133. int m_width = 0;
  134. int m_height = 0;
  135. int m_channelCount = 0;
  136. tinystl::vector<uint8_t> m_data;
  137. };
  138. // Quadtree
  139. struct Quadtree
  140. {
  141. Quadtree(Rect _rect, int _level);
  142. ~Quadtree();
  143. void add(Page request, Point mapping);
  144. void remove(Page request);
  145. void write(SimpleImage& image, int miplevel);
  146. Rect getRectangle(int index);
  147. void write(Quadtree* node, SimpleImage& image, int miplevel);
  148. static Quadtree* findPage(Quadtree* node, Page request, int* index);
  149. Rect m_rectangle;
  150. int m_level;
  151. Point m_mapping;
  152. Quadtree* m_children[4];
  153. };
  154. // PageTable
  155. class PageTable
  156. {
  157. public:
  158. PageTable(PageCache* _cache, VirtualTextureInfo* _info, PageIndexer* _indexer);
  159. ~PageTable();
  160. void update(bgfx::ViewId blitViewId);
  161. bgfx::TextureHandle getTexture();
  162. private:
  163. VirtualTextureInfo* m_info;
  164. bgfx::TextureHandle m_texture;
  165. PageIndexer* m_indexer;
  166. Quadtree* m_quadtree;
  167. bool m_quadtreeDirty;
  168. tinystl::vector<SimpleImage*> m_images;
  169. tinystl::vector<bgfx::TextureHandle> m_stagingTextures;
  170. };
  171. // PageLoader
  172. class PageLoader
  173. {
  174. public:
  175. struct ReadState
  176. {
  177. Page m_page;
  178. tinystl::vector<uint8_t> m_data;
  179. };
  180. PageLoader(TileDataFile* _tileDataFile, PageIndexer* _indexer, VirtualTextureInfo* _info);
  181. void submit(Page request);
  182. void loadPage(ReadState& state);
  183. void onPageLoadComplete(ReadState& state);
  184. void copyBorder(uint8_t* image);
  185. void copyColor(uint8_t* image, Page request);
  186. std::function<void(Page, uint8_t*)> loadComplete;
  187. bool m_colorMipLevels;
  188. bool m_showBorders;
  189. private:
  190. TileDataFile* m_tileDataFile;
  191. PageIndexer* m_indexer;
  192. VirtualTextureInfo* m_info;
  193. };
  194. // PageCache
  195. class PageCache
  196. {
  197. public:
  198. PageCache(TextureAtlas* _atlas, PageLoader* _loader, int _count);
  199. bool touch(Page page);
  200. bool request(Page request, bgfx::ViewId blitViewId);
  201. void clear();
  202. void loadComplete(Page page, uint8_t* data);
  203. // These callbacks are used to notify the other systems
  204. std::function<void(Page, Point)> removed;
  205. std::function<void(Page, Point)> added;
  206. private:
  207. TextureAtlas* m_atlas;
  208. PageLoader* m_loader;
  209. int m_count;
  210. struct LruPage
  211. {
  212. Page m_page;
  213. Point m_point;
  214. bool operator==(const Page& other) const
  215. {
  216. return m_page == other;
  217. }
  218. };
  219. int m_current; // This is used for generating the texture atlas indices before the lru is full
  220. tinystl::unordered_set<Page> m_lru_used;
  221. tinystl::vector<LruPage> m_lru;
  222. tinystl::unordered_set<Page> m_loading;
  223. bgfx::ViewId m_blitViewId;
  224. };
  225. // TextureAtlas
  226. class TextureAtlas
  227. {
  228. public:
  229. TextureAtlas(VirtualTextureInfo* _info, int count, int uploadsperframe);
  230. ~TextureAtlas();
  231. void setUploadsPerFrame(int count);
  232. void uploadPage(Point pt, uint8_t* data, bgfx::ViewId blitViewId);
  233. bgfx::TextureHandle getTexture();
  234. private:
  235. VirtualTextureInfo* m_info;
  236. bgfx::TextureHandle m_texture;
  237. StagingPool m_stagingPool;
  238. };
  239. // FeedbackBuffer
  240. class FeedbackBuffer
  241. {
  242. public:
  243. FeedbackBuffer(VirtualTextureInfo* _info, int _width, int _height);
  244. ~FeedbackBuffer();
  245. void clear();
  246. void copy(bgfx::ViewId viewId);
  247. void download();
  248. // This function validates the pages and adds the page's parents
  249. // We do this so that we can fall back to them if we run out of memory
  250. void addRequestAndParents(Page request);
  251. const tinystl::vector<int>& getRequests() const;
  252. bgfx::FrameBufferHandle getFrameBuffer();
  253. int getWidth() const;
  254. int getHeight() const;
  255. private:
  256. VirtualTextureInfo* m_info;
  257. PageIndexer* m_indexer;
  258. int m_width = 0;
  259. int m_height = 0;
  260. StagingPool m_stagingPool;
  261. bgfx::TextureHandle m_lastStagingTexture;
  262. bgfx::FrameBufferHandle m_feedbackFrameBuffer;
  263. // This stores the pages by index. The int value is number of requests.
  264. tinystl::vector<int> m_requests;
  265. tinystl::vector<uint8_t> m_downloadBuffer;
  266. };
  267. // VirtualTexture
  268. class VirtualTexture
  269. {
  270. public:
  271. VirtualTexture(TileDataFile* _tileDataFile, VirtualTextureInfo* _info, int _atlassize, int _uploadsperframe, int _mipBias = 4);
  272. ~VirtualTexture();
  273. int getMipBias() const;
  274. void setMipBias(int value);
  275. void setUploadsPerFrame(int count);
  276. int getUploadsPerFrame() const;
  277. void enableShowBoarders(bool enable);
  278. bool isShowBoardersEnabled() const;
  279. void enableColorMipLevels(bool enable);
  280. bool isColorMipLevelsEnabled() const;
  281. bgfx::TextureHandle getAtlastTexture();
  282. bgfx::TextureHandle getPageTableTexture();
  283. void clear();
  284. void update(const tinystl::vector<int>& requests, bgfx::ViewId blitViewId);
  285. void setUniforms();
  286. static void setAllocator(bx::AllocatorI* allocator);
  287. static bx::AllocatorI* getAllocator();
  288. private:
  289. TileDataFile* m_tileDataFile;
  290. VirtualTextureInfo* m_info;
  291. PageIndexer* m_indexer;
  292. PageTable* m_pageTable;
  293. TextureAtlas* m_atlas;
  294. PageLoader* m_loader;
  295. PageCache* m_cache;
  296. int m_atlasCount;
  297. int m_uploadsPerFrame;
  298. tinystl::vector<PageCount> m_pagesToLoad;
  299. int m_mipBias;
  300. bgfx::UniformHandle u_vt_settings_1;
  301. bgfx::UniformHandle u_vt_settings_2;
  302. bgfx::UniformHandle s_vt_page_table;
  303. bgfx::UniformHandle s_vt_texture_atlas;
  304. static bx::AllocatorI* s_allocator;
  305. };
  306. // TileDataFile
  307. class TileDataFile
  308. {
  309. public:
  310. TileDataFile(const bx::FilePath& filename, VirtualTextureInfo* _info, bool _readWrite = false);
  311. ~TileDataFile();
  312. void readInfo();
  313. void writeInfo();
  314. void readPage(int index, uint8_t* data);
  315. void writePage(int index, uint8_t* data);
  316. private:
  317. VirtualTextureInfo* m_info;
  318. int m_size;
  319. FILE* m_file;
  320. };
  321. // TileGenerator
  322. class TileGenerator
  323. {
  324. public:
  325. TileGenerator(VirtualTextureInfo* _info);
  326. ~TileGenerator();
  327. bool generate(const bx::FilePath& filename);
  328. private:
  329. void CopyTile(SimpleImage& image, Page request);
  330. private:
  331. VirtualTextureInfo* m_info;
  332. PageIndexer* m_indexer;
  333. TileDataFile* m_tileDataFile;
  334. int m_tilesize;
  335. int m_pagesize;
  336. bimg::ImageContainer* m_sourceImage;
  337. SimpleImage* m_page1Image;
  338. SimpleImage* m_page2Image;
  339. SimpleImage* m_2xtileImage;
  340. SimpleImage* m_4xtileImage;
  341. SimpleImage* m_tileImage;
  342. };
  343. } // namespace vt