summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/examples/40-svt/vt.h
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/examples/40-svt/vt.h')
-rw-r--r--3rdparty/bgfx/examples/40-svt/vt.h441
1 files changed, 441 insertions, 0 deletions
diff --git a/3rdparty/bgfx/examples/40-svt/vt.h b/3rdparty/bgfx/examples/40-svt/vt.h
new file mode 100644
index 00000000000..7e2d6b5eddb
--- /dev/null
+++ b/3rdparty/bgfx/examples/40-svt/vt.h
@@ -0,0 +1,441 @@
+/*
+ * Copyright 2018 Ales Mlakar. All rights reserved.
+ * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
+ */
+
+ /*
+ * Reference(s):
+ * - Sparse Virtual Textures by Sean Barrett
+ * http://web.archive.org/web/20190103162611/http://silverspaceship.com/src/svt/
+ * - Based on Virtual Texture Demo by Brad Blanchard
+ * http://web.archive.org/web/20190103162638/http://linedef.com/virtual-texture-demo.html
+ * - Mars texture
+ * http://web.archive.org/web/20190103162730/http://www.celestiamotherlode.net/catalog/mars.php
+ */
+
+#pragma once
+
+#include <bimg/decode.h>
+#include <tinystl/allocator.h>
+#include <tinystl/unordered_set.h>
+#include <tinystl/vector.h>
+#include <functional>
+
+#include "common.h"
+#include "bgfx_utils.h"
+
+namespace vt
+{
+
+// Forward declarations
+class PageCache;
+class TextureAtlas;
+class TileDataFile;
+
+// Point
+struct Point
+{
+ int m_x, m_y;
+};
+
+// Rect
+struct Rect
+{
+ int minX() const
+ {
+ return m_x;
+ }
+
+ int minY() const
+ {
+ return m_y;
+ }
+
+ int maxX() const
+ {
+ return m_x + m_width;
+ }
+
+ int maxY() const
+ {
+ return m_y + m_height;
+ }
+
+ bool contains(const Point& p) const
+ {
+ return p.m_x >= minX() && p.m_y >= minY() && p.m_x < maxX() && p.m_y < maxY();
+ }
+
+ int m_x, m_y, m_width, m_height;
+};
+
+// Color
+struct Color
+{
+ uint8_t m_r, m_g, m_b, m_a;
+};
+
+// Page
+struct Page
+{
+ operator size_t() const;
+
+ int m_x;
+ int m_y;
+ int m_mip;
+};
+
+// PageCount
+struct PageCount
+{
+ Page m_page;
+ int m_count;
+
+ PageCount(Page _page, int _count);
+
+ int compareTo(const PageCount& other) const;
+};
+
+// VirtualTextureInfo
+struct VirtualTextureInfo
+{
+ VirtualTextureInfo();
+ int GetPageSize() const;
+ int GetPageTableSize() const;
+
+ int m_virtualTextureSize = 0;
+ int m_tileSize = 0;
+ int m_borderSize = 0;
+};
+
+// StagingPool
+class StagingPool
+{
+public:
+ StagingPool(int _width, int _height, int _count, bool _readBack);
+ ~StagingPool();
+
+ void grow(int count);
+
+ bgfx::TextureHandle getTexture();
+ void next();
+
+private:
+ tinystl::vector<bgfx::TextureHandle> m_stagingTextures;
+
+ int m_stagingTextureIndex;
+ int m_width;
+ int m_height;
+ uint64_t m_flags;
+};
+
+// PageIndexer
+struct PageIndexer
+{
+public:
+ PageIndexer(VirtualTextureInfo* _info);
+
+ int getIndexFromPage(Page page);
+ Page getPageFromIndex(int index);
+
+ bool isValid(Page page);
+ int getCount() const;
+ int getMipCount() const;
+
+private:
+ VirtualTextureInfo* m_info;
+ int m_mipcount;
+ int m_count;
+
+ tinystl::vector<int> m_offsets; // This stores the offsets to the first page of the start of a mipmap level
+ tinystl::vector<int> m_sizes; // This stores the sizes of various mip levels
+ tinystl::vector<Page> m_reverse;
+};
+
+// SimpleImage
+struct SimpleImage
+{
+ SimpleImage(int _width, int _height, int _channelCount, uint8_t _clearValue = 0);
+ SimpleImage(int _width, int _height, int _channelCount, tinystl::vector<uint8_t>& _data);
+
+ void copy(Point dest_offset, SimpleImage& src, Rect src_rect);
+ void clear(uint8_t clearValue = 0);
+ void fill(Rect rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
+
+ static void mipmap(uint8_t* source, int size, int channels, uint8_t* dest);
+
+ int m_width = 0;
+ int m_height = 0;
+ int m_channelCount = 0;
+
+ tinystl::vector<uint8_t> m_data;
+};
+
+// Quadtree
+struct Quadtree
+{
+ Quadtree(Rect _rect, int _level);
+ ~Quadtree();
+
+ void add(Page request, Point mapping);
+ void remove(Page request);
+ void write(SimpleImage& image, int miplevel);
+ Rect getRectangle(int index);
+
+ void write(Quadtree* node, SimpleImage& image, int miplevel);
+ static Quadtree* findPage(Quadtree* node, Page request, int* index);
+
+ Rect m_rectangle;
+ int m_level;
+ Point m_mapping;
+ Quadtree* m_children[4];
+};
+
+// PageTable
+class PageTable
+{
+public:
+ PageTable(PageCache* _cache, VirtualTextureInfo* _info, PageIndexer* _indexer);
+ ~PageTable();
+
+ void update(bgfx::ViewId blitViewId);
+ bgfx::TextureHandle getTexture();
+
+private:
+ VirtualTextureInfo* m_info;
+ bgfx::TextureHandle m_texture;
+ PageIndexer* m_indexer;
+ Quadtree* m_quadtree;
+ bool m_quadtreeDirty;
+
+ tinystl::vector<SimpleImage*> m_images;
+ tinystl::vector<bgfx::TextureHandle> m_stagingTextures;
+};
+
+// PageLoader
+class PageLoader
+{
+public:
+ struct ReadState
+ {
+ Page m_page;
+ tinystl::vector<uint8_t> m_data;
+ };
+
+ PageLoader(TileDataFile* _tileDataFile, PageIndexer* _indexer, VirtualTextureInfo* _info);
+ void submit(Page request);
+ void loadPage(ReadState& state);
+ void onPageLoadComplete(ReadState& state);
+ void copyBorder(uint8_t* image);
+ void copyColor(uint8_t* image, Page request);
+
+ std::function<void(Page, uint8_t*)> loadComplete;
+
+ bool m_colorMipLevels;
+ bool m_showBorders;
+
+private:
+ TileDataFile* m_tileDataFile;
+ PageIndexer* m_indexer;
+ VirtualTextureInfo* m_info;
+};
+
+// PageCache
+class PageCache
+{
+public:
+ PageCache(TextureAtlas* _atlas, PageLoader* _loader, int _count);
+ bool touch(Page page);
+ bool request(Page request, bgfx::ViewId blitViewId);
+ void clear();
+ void loadComplete(Page page, uint8_t* data);
+
+ // These callbacks are used to notify the other systems
+ std::function<void(Page, Point)> removed;
+ std::function<void(Page, Point)> added;
+
+private:
+ TextureAtlas* m_atlas;
+ PageLoader* m_loader;
+
+ int m_count;
+
+ struct LruPage
+ {
+ Page m_page;
+ Point m_point;
+
+ bool operator==(const Page& other) const
+ {
+ return m_page == other;
+ }
+ };
+
+ int m_current; // This is used for generating the texture atlas indices before the lru is full
+
+ tinystl::unordered_set<Page> m_lru_used;
+ tinystl::vector<LruPage> m_lru;
+ tinystl::unordered_set<Page> m_loading;
+
+ bgfx::ViewId m_blitViewId;
+};
+
+// TextureAtlas
+class TextureAtlas
+{
+public:
+ TextureAtlas(VirtualTextureInfo* _info, int count, int uploadsperframe);
+ ~TextureAtlas();
+
+ void setUploadsPerFrame(int count);
+ void uploadPage(Point pt, uint8_t* data, bgfx::ViewId blitViewId);
+
+ bgfx::TextureHandle getTexture();
+
+private:
+ VirtualTextureInfo* m_info;
+ bgfx::TextureHandle m_texture;
+ StagingPool m_stagingPool;
+};
+
+// FeedbackBuffer
+class FeedbackBuffer
+{
+public:
+ FeedbackBuffer(VirtualTextureInfo* _info, int _width, int _height);
+ ~FeedbackBuffer();
+
+ void clear();
+
+ void copy(bgfx::ViewId viewId);
+ void download();
+
+ // This function validates the pages and adds the page's parents
+ // We do this so that we can fall back to them if we run out of memory
+ void addRequestAndParents(Page request);
+
+ const tinystl::vector<int>& getRequests() const;
+ bgfx::FrameBufferHandle getFrameBuffer();
+
+ int getWidth() const;
+ int getHeight() const;
+
+private:
+ VirtualTextureInfo* m_info;
+ PageIndexer* m_indexer;
+
+ int m_width = 0;
+ int m_height = 0;
+
+ StagingPool m_stagingPool;
+ bgfx::TextureHandle m_lastStagingTexture;
+ bgfx::FrameBufferHandle m_feedbackFrameBuffer;
+
+ // This stores the pages by index. The int value is number of requests.
+ tinystl::vector<int> m_requests;
+ tinystl::vector<uint8_t> m_downloadBuffer;
+};
+
+// VirtualTexture
+class VirtualTexture
+{
+public:
+ VirtualTexture(TileDataFile* _tileDataFile, VirtualTextureInfo* _info, int _atlassize, int _uploadsperframe, int _mipBias = 4);
+ ~VirtualTexture();
+
+ int getMipBias() const;
+ void setMipBias(int value);
+
+ void setUploadsPerFrame(int count);
+ int getUploadsPerFrame() const;
+
+ void enableShowBoarders(bool enable);
+ bool isShowBoardersEnabled() const;
+
+ void enableColorMipLevels(bool enable);
+ bool isColorMipLevelsEnabled() const;
+
+ bgfx::TextureHandle getAtlastTexture();
+ bgfx::TextureHandle getPageTableTexture();
+
+ void clear();
+ void update(const tinystl::vector<int>& requests, bgfx::ViewId blitViewId);
+
+ void setUniforms();
+
+ static void setAllocator(bx::AllocatorI* allocator);
+ static bx::AllocatorI* getAllocator();
+
+private:
+ TileDataFile* m_tileDataFile;
+ VirtualTextureInfo* m_info;
+ PageIndexer* m_indexer;
+ PageTable* m_pageTable;
+ TextureAtlas* m_atlas;
+ PageLoader* m_loader;
+ PageCache* m_cache;
+
+ int m_atlasCount;
+ int m_uploadsPerFrame;
+
+ tinystl::vector<PageCount> m_pagesToLoad;
+
+ int m_mipBias;
+
+ bgfx::UniformHandle u_vt_settings_1;
+ bgfx::UniformHandle u_vt_settings_2;
+ bgfx::UniformHandle s_vt_page_table;
+ bgfx::UniformHandle s_vt_texture_atlas;
+
+ static bx::AllocatorI* s_allocator;
+};
+
+// TileDataFile
+class TileDataFile
+{
+public:
+ TileDataFile(const bx::FilePath& filename, VirtualTextureInfo* _info, bool _readWrite = false);
+ ~TileDataFile();
+
+ void readInfo();
+ void writeInfo();
+
+ void readPage(int index, uint8_t* data);
+ void writePage(int index, uint8_t* data);
+
+private:
+ VirtualTextureInfo* m_info;
+ int m_size;
+ FILE* m_file;
+};
+
+// TileGenerator
+class TileGenerator
+{
+public:
+ TileGenerator(VirtualTextureInfo* _info);
+ ~TileGenerator();
+
+ bool generate(const bx::FilePath& filename);
+
+private:
+ void CopyTile(SimpleImage& image, Page request);
+
+private:
+ VirtualTextureInfo* m_info;
+ PageIndexer* m_indexer;
+ TileDataFile* m_tileDataFile;
+
+ int m_tilesize;
+ int m_pagesize;
+
+ bimg::ImageContainer* m_sourceImage;
+
+ SimpleImage* m_page1Image;
+ SimpleImage* m_page2Image;
+ SimpleImage* m_2xtileImage;
+ SimpleImage* m_4xtileImage;
+ SimpleImage* m_tileImage;
+};
+
+} // namespace vt