Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace RasterOverlayTileProvider cache with SharedAssetDepot #987

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Cesium3DTilesSelection/src/EmptyRasterOverlayTileProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ EmptyRasterOverlayTileProvider::EmptyRasterOverlayTileProvider(
CesiumGeospatial::GeographicProjection(),
CesiumGeometry::Rectangle()) {}

CesiumAsync::Future<CesiumRasterOverlays::LoadedRasterOverlayImage>
CesiumAsync::Future<CesiumUtility::ResultPointer<
CesiumRasterOverlays::LoadedRasterOverlayImage>>
EmptyRasterOverlayTileProvider::loadTileImage(
CesiumRasterOverlays::RasterOverlayTile& /*overlayTile*/) {
return this->getAsyncSystem()
.createResolvedFuture<CesiumRasterOverlays::LoadedRasterOverlayImage>({});
return this->getAsyncSystem().createResolvedFuture(
CesiumUtility::ResultPointer<LoadedRasterOverlayImage>{nullptr});
}

} // namespace Cesium3DTilesSelection
5 changes: 4 additions & 1 deletion Cesium3DTilesSelection/src/EmptyRasterOverlayTileProvider.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once

#include <CesiumAsync/Future.h>
#include <CesiumRasterOverlays/RasterOverlayTileProvider.h>
#include <CesiumUtility/Result.h>

namespace Cesium3DTilesSelection {

Expand All @@ -13,7 +15,8 @@ class EmptyRasterOverlayTileProvider
const CesiumAsync::AsyncSystem& asyncSystem) noexcept;

protected:
virtual CesiumAsync::Future<CesiumRasterOverlays::LoadedRasterOverlayImage>
virtual CesiumAsync::Future<CesiumUtility::ResultPointer<
CesiumRasterOverlays::LoadedRasterOverlayImage>>
loadTileImage(CesiumRasterOverlays::RasterOverlayTile& overlayTile) override;
};

Expand Down
15 changes: 8 additions & 7 deletions Cesium3DTilesSelection/test/TestTilesetContentManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1296,7 +1296,7 @@ TEST_CASE("Test the tileset content manager's post processing for gltf") {
projection,
coverageRectangle) {}

CesiumAsync::Future<LoadedRasterOverlayImage>
CesiumAsync::Future<ResultPointer<LoadedRasterOverlayImage>>
loadTileImage(RasterOverlayTile& overlayTile) override {
CesiumUtility::IntrusivePointer<CesiumGltf::ImageAsset> pImage;
CesiumGltf::ImageAsset& image = pImage.emplace();
Expand All @@ -1306,13 +1306,14 @@ TEST_CASE("Test the tileset content manager's post processing for gltf") {
image.bytesPerChannel = 1;
image.pixelData.resize(1, std::byte(255));

CesiumUtility::IntrusivePointer<LoadedRasterOverlayImage> pResult;
pResult.emplace();
pResult->pImage = std::move(pImage);
pResult->rectangle = overlayTile.getRectangle();
pResult->moreDetailAvailable = true;

return this->getAsyncSystem().createResolvedFuture(
LoadedRasterOverlayImage{
std::move(pImage),
overlayTile.getRectangle(),
{},
{},
true});
ResultPointer<LoadedRasterOverlayImage>{pResult});
}
};

Expand Down
13 changes: 13 additions & 0 deletions CesiumGeometry/include/CesiumGeometry/Rectangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,19 @@ struct CESIUMGEOMETRY_API Rectangle final {
* @return The union rectangle, which fully contains both rectangles.
*/
Rectangle computeUnion(const Rectangle& other) const noexcept;

/**
* Compares this rectangle against another rectangle and returns true if the
* two rectangles are exactly the same.
*/
bool operator==(const Rectangle& rhs) const noexcept {
return this->minimumX == rhs.minimumX && this->maximumX == rhs.maximumX &&
this->minimumY == rhs.minimumY && this->maximumY == rhs.maximumY;
}
};

} // namespace CesiumGeometry

template <> struct std::hash<CesiumGeometry::Rectangle> {
std::size_t operator()(const CesiumGeometry::Rectangle& key) const noexcept;
};
13 changes: 13 additions & 0 deletions CesiumGeometry/src/Rectangle.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "CesiumGeometry/Rectangle.h"

#include "CesiumUtility/Hash.h"

#include <glm/common.hpp>
#include <glm/geometric.hpp>

Expand Down Expand Up @@ -66,3 +68,14 @@ Rectangle Rectangle::computeUnion(const Rectangle& other) const noexcept {
}

} // namespace CesiumGeometry

std::size_t std::hash<CesiumGeometry::Rectangle>::operator()(
const CesiumGeometry::Rectangle& key) const noexcept {
std::hash<double> baseHash{};

size_t result = baseHash(key.minimumX);
result = CesiumUtility::Hash::combine(result, baseHash(key.maximumX));
result = CesiumUtility::Hash::combine(result, baseHash(key.minimumY));
result = CesiumUtility::Hash::combine(result, baseHash(key.maximumY));
return result;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#pragma once

#include <CesiumAsync/Future.h>
#include <CesiumAsync/NetworkAssetDescriptor.h>
#include <CesiumGeometry/QuadtreeTileID.h>
#include <CesiumGltf/Ktx2TranscodeTargets.h>
#include <CesiumRasterOverlays/RasterOverlayTileProvider.h>
#include <CesiumUtility/IntrusivePointer.h>
#include <CesiumUtility/Result.h>

#include <memory>
#include <optional>

namespace CesiumAsync {
class AsyncSystem;
}

namespace CesiumRasterOverlays {

struct LoadedQuadtreeImage {
CesiumUtility::IntrusivePointer<LoadedRasterOverlayImage> pLoaded = nullptr;
std::optional<CesiumGeometry::Rectangle> subset = std::nullopt;
};

/**
* @brief A description of an image that is part of a raster overlay that can be
* loaded from the network and stored in a `SharedAssetDepot`. It contains the
* URL, headers, KTX2 transcode targets, and any options specified.
*/
struct NetworkRasterOverlayImageAssetDescriptor
: public CesiumAsync::NetworkAssetDescriptor {
/**
* @brief The supported GPU texture formats used for KTX2 decoding.
*/
CesiumGltf::Ktx2TranscodeTargets ktx2TranscodeTargets{};

/**
* @brief Options such as the rectangle of this raster overlay image and any
* credits to attach.
*/
CesiumRasterOverlays::LoadTileImageFromUrlOptions loadTileOptions;

/**
* @brief Determines if this descriptor is identical to another one.
*/
bool operator==(
const NetworkRasterOverlayImageAssetDescriptor& rhs) const noexcept;

/**
* @brief Request this asset from the network using the provided asset
* accessor and return the loaded {@link ImageAsset}.
*
* @param asyncSystem The async system.
* @param pAssetAccessor The asset accessor.
* @return A future that resolves to the image asset once the request is
* complete.
*/
CesiumAsync::Future<CesiumUtility::ResultPointer<LoadedRasterOverlayImage>>
load(
const CesiumAsync::AsyncSystem& asyncSystem,
const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor) const;
};

} // namespace CesiumRasterOverlays

template <>
struct std::hash<
CesiumRasterOverlays::NetworkRasterOverlayImageAssetDescriptor> {
std::size_t operator()(
const CesiumRasterOverlays::NetworkRasterOverlayImageAssetDescriptor& key)
const noexcept;
};

template <>
struct std::hash<CesiumRasterOverlays::LoadTileImageFromUrlOptions> {
std::size_t
operator()(const CesiumRasterOverlays::LoadTileImageFromUrlOptions& key)
const noexcept;
};
Original file line number Diff line number Diff line change
Expand Up @@ -101,22 +101,24 @@ class CESIUMRASTEROVERLAYS_API QuadtreeRasterOverlayTileProvider
* @brief Asynchronously loads a tile in the quadtree.
*
* @param tileID The ID of the quadtree tile to load.
* @return A Future that resolves to the loaded image data or error
* @return A Future that resolves to the loaded image data and error
* information.
*/
virtual CesiumAsync::Future<LoadedRasterOverlayImage>
virtual CesiumAsync::SharedFuture<
CesiumUtility::ResultPointer<LoadedRasterOverlayImage>>
loadQuadtreeTileImage(const CesiumGeometry::QuadtreeTileID& tileID) const = 0;

private:
virtual CesiumAsync::Future<LoadedRasterOverlayImage>
virtual CesiumAsync::Future<
CesiumUtility::ResultPointer<LoadedRasterOverlayImage>>
loadTileImage(RasterOverlayTile& overlayTile) override final;

struct LoadedQuadtreeImage {
std::shared_ptr<LoadedRasterOverlayImage> pLoaded = nullptr;
CesiumUtility::ResultPointer<LoadedRasterOverlayImage> pLoaded = nullptr;
std::optional<CesiumGeometry::Rectangle> subset = std::nullopt;
};

CesiumAsync::SharedFuture<LoadedQuadtreeImage>
CesiumAsync::Future<LoadedQuadtreeImage>
getQuadtreeTile(const CesiumGeometry::QuadtreeTileID& tileID);

/**
Expand All @@ -129,13 +131,12 @@ class CESIUMRASTEROVERLAYS_API QuadtreeRasterOverlayTileProvider
* data that is required to cover the rectangle with the given geometric
* error.
*/
std::vector<CesiumAsync::SharedFuture<LoadedQuadtreeImage>>
std::vector<CesiumAsync::Future<
QuadtreeRasterOverlayTileProvider::LoadedQuadtreeImage>>
mapRasterTilesToGeometryTile(
const CesiumGeometry::Rectangle& geometryRectangle,
const glm::dvec2 targetScreenPixels);

void unloadCachedTiles();

struct CombinedImageMeasurements {
CesiumGeometry::Rectangle rectangle;
int32_t widthPixels;
Expand All @@ -148,7 +149,7 @@ class CESIUMRASTEROVERLAYS_API QuadtreeRasterOverlayTileProvider
const CesiumGeometry::Rectangle& targetRectangle,
const std::vector<LoadedQuadtreeImage>& images);

static LoadedRasterOverlayImage combineImages(
static CesiumUtility::ResultPointer<LoadedRasterOverlayImage> combineImages(
const CesiumGeometry::Rectangle& targetRectangle,
const CesiumGeospatial::Projection& projection,
std::vector<LoadedQuadtreeImage>&& images);
Expand All @@ -158,23 +159,5 @@ class CESIUMRASTEROVERLAYS_API QuadtreeRasterOverlayTileProvider
uint32_t _imageWidth;
uint32_t _imageHeight;
CesiumGeometry::QuadtreeTilingScheme _tilingScheme;

struct CacheEntry {
CesiumGeometry::QuadtreeTileID tileID;
CesiumAsync::SharedFuture<LoadedQuadtreeImage> future;
};

// Tiles at the beginning of this list are the least recently used (oldest),
// while the tiles at the end are most recently used (newest).
using TileLeastRecentlyUsedList = std::list<CacheEntry>;
TileLeastRecentlyUsedList _tilesOldToRecent;

// Allows a Future to be looked up by quadtree tile ID.
std::unordered_map<
CesiumGeometry::QuadtreeTileID,
TileLeastRecentlyUsedList::iterator>
_tileLookup;

std::atomic<int64_t> _cachedBytes;
};
} // namespace CesiumRasterOverlays
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,37 @@
#include "Library.h"

#include <CesiumAsync/IAssetAccessor.h>
#include <CesiumAsync/SharedAssetDepot.h>
#include <CesiumGeospatial/Projection.h>
#include <CesiumGltfReader/GltfReader.h>
#include <CesiumUtility/Assert.h>
#include <CesiumUtility/CreditSystem.h>
#include <CesiumUtility/ErrorList.h>
#include <CesiumUtility/IntrusivePointer.h>
#include <CesiumUtility/ReferenceCounted.h>
#include <CesiumUtility/Result.h>
#include <CesiumUtility/SharedAsset.h>
#include <CesiumUtility/Tracing.h>

#include <spdlog/fwd.h>

#include <memory>
#include <optional>

namespace CesiumRasterOverlays {

class RasterOverlay;
class RasterOverlayTile;
class IPrepareRasterOverlayRendererResources;
class NetworkRasterOverlayImageAssetDescriptor;

/**
* @brief Summarizes the result of loading an image of a {@link RasterOverlay}.
*/
struct CESIUMRASTEROVERLAYS_API LoadedRasterOverlayImage {
struct CESIUMRASTEROVERLAYS_API LoadedRasterOverlayImage
: public CesiumUtility::SharedAsset<LoadedRasterOverlayImage> {
/**
* @brief The loaded image.
*
* This will be an empty optional if the loading failed. In this case,
* the `errors` vector will contain the corresponding error messages.
*/
CesiumUtility::IntrusivePointer<CesiumGltf::ImageAsset> pImage{nullptr};

Expand All @@ -47,20 +50,24 @@ struct CESIUMRASTEROVERLAYS_API LoadedRasterOverlayImage {
* are required when using the image.
*/
std::vector<CesiumUtility::Credit> credits{};

/**
* @brief Errors and warnings from loading the image.
*
* If the image was loaded successfully, there should not be any errors (but
* there may be warnings).
*/
CesiumUtility::ErrorList errorList{};

/**
* @brief Whether more detailed data, beyond this image, is available within
* the bounds of this image.
*/
bool moreDetailAvailable = false;

/**
* @brief Returns the size of this `LoadedRasterOverlayImage` in bytes.
*/
size_t getSizeBytes() const {
int64_t accum = 0;
accum += sizeof(LoadedRasterOverlayImage);
accum += this->credits.capacity() * sizeof(CesiumUtility::Credit);
if (this->pImage) {
accum += this->pImage->getSizeBytes();
}
return accum;
}
};

/**
Expand Down Expand Up @@ -105,6 +112,12 @@ struct LoadTileImageFromUrlOptions {
* not available.
*/
bool allowEmptyImages = false;

bool operator==(const LoadTileImageFromUrlOptions& rhs) const noexcept {
return this->rectangle == rhs.rectangle && this->credits == rhs.credits &&
this->moreDetailAvailable == rhs.moreDetailAvailable &&
this->allowEmptyImages == rhs.allowEmptyImages;
}
};

class RasterOverlayTileProvider;
Expand Down Expand Up @@ -356,7 +369,8 @@ class CESIUMRASTEROVERLAYS_API RasterOverlayTileProvider
* @param overlayTile The overlay tile for which to load the image.
* @return A future that resolves to the image or error information.
*/
virtual CesiumAsync::Future<LoadedRasterOverlayImage>
virtual CesiumAsync::Future<
CesiumUtility::ResultPointer<LoadedRasterOverlayImage>>
loadTileImage(RasterOverlayTile& overlayTile) = 0;

/**
Expand All @@ -369,7 +383,9 @@ class CESIUMRASTEROVERLAYS_API RasterOverlayTileProvider
* @param options Additional options for the load process.
* @return A future that resolves to the image or error information.
*/
CesiumAsync::Future<LoadedRasterOverlayImage> loadTileImageFromUrl(
CesiumAsync::SharedFuture<
CesiumUtility::ResultPointer<LoadedRasterOverlayImage>>
loadTileImageFromUrl(
const std::string& url,
const std::vector<CesiumAsync::IAssetAccessor::THeader>& headers = {},
LoadTileImageFromUrlOptions&& options = {}) const;
Expand Down Expand Up @@ -414,5 +430,9 @@ class CESIUMRASTEROVERLAYS_API RasterOverlayTileProvider
CESIUM_TRACE_DECLARE_TRACK_SET(
_loadingSlots,
"Raster Overlay Tile Loading Slot");
CesiumUtility::IntrusivePointer<CesiumAsync::SharedAssetDepot<
LoadedRasterOverlayImage,
NetworkRasterOverlayImageAssetDescriptor>>
_pRasterOverlayImageDepot;
};
} // namespace CesiumRasterOverlays
3 changes: 2 additions & 1 deletion CesiumRasterOverlays/src/BingMapsRasterOverlay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ class BingMapsTileProvider final : public QuadtreeRasterOverlayTileProvider {
virtual ~BingMapsTileProvider() {}

protected:
virtual CesiumAsync::Future<LoadedRasterOverlayImage> loadQuadtreeTileImage(
virtual CesiumAsync::SharedFuture<ResultPointer<LoadedRasterOverlayImage>>
loadQuadtreeTileImage(
const CesiumGeometry::QuadtreeTileID& tileID) const override {
std::string url = CesiumUtility::Uri::substituteTemplateParameters(
this->_urlTemplate,
Expand Down
Loading
Loading