Skip to content

Commit

Permalink
Add a FindRecycled() method to the Resource class. (#109)
Browse files Browse the repository at this point in the history
  • Loading branch information
domchen authored Jan 14, 2024
1 parent 0a22469 commit d864aee
Show file tree
Hide file tree
Showing 33 changed files with 113 additions and 94 deletions.
8 changes: 4 additions & 4 deletions include/tgfx/gpu/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,20 @@ class Context {
/**
* Purges GPU resources that haven't been used the passed in time.
* @param purgeTime A timestamp previously returned by Clock::Now().
* @param recyclableResourcesOnly If true, purgeable resources with external weak references are
* @param recycledResourcesOnly If true, purgeable resources with external weak references are
* spared. If false, all purgeable resources will be deleted.
*/
void purgeResourcesNotUsedSince(int64_t purgeTime, bool recyclableResourcesOnly = false);
void purgeResourcesNotUsedSince(int64_t purgeTime, bool recycledResourcesOnly = false);

/**
* Purge unreferenced resources from the cache until the provided bytesLimit has been reached, or
* we have purged all unreferenced resources. Returns true if the total resource bytes is not over
* the specified bytesLimit after purging.
* @param bytesLimit The desired number of bytes after puring.
* @param recyclableResourcesOnly If true, purgeable resources with external weak references are
* @param recycledResourcesOnly If true, purgeable resources with external weak references are
* spared. If false, all purgeable resources will be deleted.
*/
bool purgeResourcesUntilMemoryTo(size_t bytesLimit, bool recyclableResourcesOnly = false);
bool purgeResourcesUntilMemoryTo(size_t bytesLimit, bool recycledResourcesOnly = false);

/**
* Inserts a GPU semaphore that the current GPU-backed API must wait on before executing any more
Expand Down
8 changes: 4 additions & 4 deletions src/gpu/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ void Context::setCacheLimit(size_t bytesLimit) {
_resourceCache->setCacheLimit(bytesLimit);
}

void Context::purgeResourcesNotUsedSince(int64_t purgeTime, bool recyclableResourcesOnly) {
_resourceCache->purgeNotUsedSince(purgeTime, recyclableResourcesOnly);
void Context::purgeResourcesNotUsedSince(int64_t purgeTime, bool recycledResourcesOnly) {
_resourceCache->purgeNotUsedSince(purgeTime, recycledResourcesOnly);
}

bool Context::purgeResourcesUntilMemoryTo(size_t bytesLimit, bool recyclableResourcesOnly) {
return _resourceCache->purgeUntilMemoryTo(bytesLimit, recyclableResourcesOnly);
bool Context::purgeResourcesUntilMemoryTo(size_t bytesLimit, bool recycledResourcesOnly) {
return _resourceCache->purgeUntilMemoryTo(bytesLimit, recycledResourcesOnly);
}

void Context::releaseAll(bool releaseGPU) {
Expand Down
2 changes: 1 addition & 1 deletion src/gpu/ExternalTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ std::shared_ptr<Texture> ExternalTexture::MakeFrom(Context* context,
}
auto texture = new ExternalTexture(std::move(sampler), backendTexture.width(),
backendTexture.height(), origin, adopted);
return Resource::AddToContext(context, texture);
return Resource::AddToCache(context, texture);
}

ExternalTexture::ExternalTexture(std::unique_ptr<TextureSampler> sampler, int width, int height,
Expand Down
5 changes: 3 additions & 2 deletions src/gpu/ExternalTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ class ExternalTexture : public Texture {
return sampler.get();
}

protected:
void onReleaseGPU() override;

private:
std::unique_ptr<TextureSampler> sampler = {};
bool adopted = false;

ExternalTexture(std::unique_ptr<TextureSampler> sampler, int width, int height,
ImageOrigin origin, bool adopted);

void onReleaseGPU() override;
};
} // namespace tgfx
5 changes: 2 additions & 3 deletions src/gpu/PlainTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ std::shared_ptr<Texture> Texture::MakeFormat(Context* context, int width, int he
int maxMipmapLevel = mipMapped ? caps->getMaxMipmapLevel(width, height) : 0;
BytesKey recycleKey = {};
ComputeRecycleKey(&recycleKey, width, height, pixelFormat, maxMipmapLevel > 0);
auto texture = std::static_pointer_cast<Texture>(
context->resourceCache()->findRecyclableResource(recycleKey));
auto texture = Resource::FindRecycled<Texture>(context, recycleKey);
if (texture) {
texture->_origin = origin;
} else {
Expand All @@ -54,7 +53,7 @@ std::shared_ptr<Texture> Texture::MakeFormat(Context* context, int width, int he
return nullptr;
}
auto plainTexture = new PlainTexture(std::move(sampler), width, height, origin);
texture = Resource::AddToContext(context, plainTexture, recycleKey);
texture = Resource::AddToCache(context, plainTexture, recycleKey);
}
if (pixels != nullptr) {
context->gpu()->writePixels(texture->getSampler(), Rect::MakeWH(width, height), pixels,
Expand Down
5 changes: 3 additions & 2 deletions src/gpu/PlainTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ class PlainTexture : public Texture {
return sampler.get();
}

protected:
void onReleaseGPU() override;

private:
std::unique_ptr<TextureSampler> sampler = {};

void onReleaseGPU() override;

friend class Texture;
};
} // namespace tgfx
6 changes: 3 additions & 3 deletions src/gpu/Program.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ class Program {
protected:
Context* context = nullptr;

private:
BytesKey uniqueKey = {};

/**
* Overridden to free GPU resources in the backend API.
*/
virtual void onReleaseGPU() = 0;

private:
BytesKey uniqueKey = {};

friend class ProgramCache;
};
} // namespace tgfx
29 changes: 22 additions & 7 deletions src/gpu/Resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,32 @@ namespace tgfx {
*/
class Resource {
public:
/**
* A convenient method to add a resource to the cache.
*/
template <class T>
static std::shared_ptr<T> AddToContext(Context* context, T* resource,
const BytesKey& recycleKey = {}) {
static std::shared_ptr<T> AddToCache(Context* context, T* resource,
const BytesKey& recycleKey = {}) {
return std::static_pointer_cast<T>(context->resourceCache()->addResource(resource, recycleKey));
}

/**
* A convenient method to retrieve the corresponding resource in the cache by the specified
* ResourceKey.
*/
template <class T>
static std::shared_ptr<T> Get(Context* context, const ResourceKey& resourceKey) {
return std::static_pointer_cast<T>(context->resourceCache()->getResource(resourceKey));
}

/**
* A convenient method to retrieve a recycled resource in the cache by the specified recycle key.
*/
template <class T>
static std::shared_ptr<T> FindRecycled(Context* context, const BytesKey& recycleKey) {
return std::static_pointer_cast<T>(context->resourceCache()->findRecycledResource(recycleKey));
}

virtual ~Resource() = default;

/**
Expand Down Expand Up @@ -101,6 +116,11 @@ class Resource {
protected:
Context* context = nullptr;

/**
* Overridden to free GPU resources in the backend API.
*/
virtual void onReleaseGPU() = 0;

private:
std::shared_ptr<Resource> reference;
BytesKey recycleKey = {};
Expand All @@ -119,11 +139,6 @@ class Resource {

void release(bool releaseGPU);

/**
* Overridden to free GPU resources in the backend API.
*/
virtual void onReleaseGPU() = 0;

friend class ResourceCache;
};
} // namespace tgfx
14 changes: 7 additions & 7 deletions src/gpu/ResourceCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void ResourceCache::setCacheLimit(size_t bytesLimit) {
purgeUntilMemoryTo(maxBytes);
}

std::shared_ptr<Resource> ResourceCache::findRecyclableResource(const BytesKey& recycleKey) {
std::shared_ptr<Resource> ResourceCache::findRecycledResource(const BytesKey& recycleKey) {
auto result = recycleKeyMap.find(recycleKey);
if (result == recycleKeyMap.end()) {
return nullptr;
Expand Down Expand Up @@ -184,17 +184,17 @@ void ResourceCache::removeResource(Resource* resource) {
resource->release(true);
}

void ResourceCache::purgeNotUsedSince(int64_t purgeTime, bool recyclableResourcesOnly) {
purgeResourcesByLRU(recyclableResourcesOnly,
void ResourceCache::purgeNotUsedSince(int64_t purgeTime, bool recycledResourceOnly) {
purgeResourcesByLRU(recycledResourceOnly,
[&](Resource* resource) { return resource->lastUsedTime >= purgeTime; });
}

bool ResourceCache::purgeUntilMemoryTo(size_t bytesLimit, bool recyclableResourcesOnly) {
purgeResourcesByLRU(recyclableResourcesOnly, [&](Resource*) { return totalBytes <= bytesLimit; });
bool ResourceCache::purgeUntilMemoryTo(size_t bytesLimit, bool recycledResourceOnly) {
purgeResourcesByLRU(recycledResourceOnly, [&](Resource*) { return totalBytes <= bytesLimit; });
return totalBytes <= bytesLimit;
}

void ResourceCache::purgeResourcesByLRU(bool recyclableResourcesOnly,
void ResourceCache::purgeResourcesByLRU(bool recycledResourceOnly,
const std::function<bool(Resource*)>& satisfied) {
processUnreferencedResources();
std::vector<Resource*> needToPurge = {};
Expand All @@ -203,7 +203,7 @@ void ResourceCache::purgeResourcesByLRU(bool recyclableResourcesOnly,
if (satisfied(resource)) {
break;
}
if (!recyclableResourcesOnly || !resource->hasExternalReferences()) {
if (!recycledResourceOnly || !resource->hasExternalReferences()) {
needToPurge.push_back(resource);
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/gpu/ResourceCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ class ResourceCache {
void setCacheLimit(size_t bytesLimit);

/**
* Returns a recyclable resource in the cache by the specified recycle key.
* Returns a recycled resource in the cache by the specified recycle key.
*/
std::shared_ptr<Resource> findRecyclableResource(const BytesKey& recycleKey);
std::shared_ptr<Resource> findRecycledResource(const BytesKey& recycleKey);

/**
* Retrieves the corresponding resource in the cache by the specified ResourceKey.
Expand All @@ -83,20 +83,20 @@ class ResourceCache {
/**
* Purges GPU resources that haven't been used the passed in time.
* @param purgeTime A timestamp previously returned by Clock::Now().
* @param recyclableResourcesOnly If true, purgeable resources with external weak references are
* @param recycledResourceOnly If true, purgeable resources with external weak references are
* spared. If false, all purgeable resources will be deleted.
*/
void purgeNotUsedSince(int64_t purgeTime, bool recyclableResourcesOnly = false);
void purgeNotUsedSince(int64_t purgeTime, bool recycledResourceOnly = false);

/**
* Purge unreferenced resources from the cache until the provided bytesLimit has been reached,
* or we have purged all unreferenced resources. Returns true if the total resource bytes is not
* over the specified bytesLimit after purging.
* @param bytesLimit The desired number of bytes after puring.
* @param recyclableResourcesOnly If true, purgeable resources with external weak references are
* @param recycledResourceOnly If true, purgeable resources with external weak references are
* spared. If false, all purgeable resources will be deleted.
*/
bool purgeUntilMemoryTo(size_t bytesLimit, bool recyclableResourcesOnly = false);
bool purgeUntilMemoryTo(size_t bytesLimit, bool recycledResourceOnly = false);

private:
Context* context = nullptr;
Expand All @@ -117,7 +117,7 @@ class ResourceCache {
std::shared_ptr<Resource> addResource(Resource* resource, const BytesKey& recycleKey);
std::shared_ptr<Resource> refResource(Resource* resource);
void removeResource(Resource* resource);
void purgeResourcesByLRU(bool recyclableResourcesOnly,
void purgeResourcesByLRU(bool recycledResourceOnly,
const std::function<bool(Resource*)>& satisfied);

void changeResourceKey(Resource* resource, const ResourceKey& resourceKey);
Expand Down
14 changes: 6 additions & 8 deletions src/gpu/YUVTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ std::shared_ptr<Texture> Texture::MakeI420(Context* context, const YUVData* yuvD
PixelFormat::GRAY_8};
BytesKey recycleKey = {};
ComputeRecycleKey(&recycleKey, yuvData->width(), yuvData->height(), YUVPixelFormat::I420);
auto texture = std::static_pointer_cast<YUVTexture>(
context->resourceCache()->findRecyclableResource(recycleKey));
auto texture = Resource::FindRecycled<YUVTexture>(context, recycleKey);
if (texture == nullptr) {
auto texturePlanes = MakeTexturePlanes(context, yuvData, yuvFormats);
if (texturePlanes.empty()) {
Expand All @@ -84,8 +83,8 @@ std::shared_ptr<Texture> Texture::MakeI420(Context* context, const YUVData* yuvD
auto yuvTexture =
new YUVTexture(yuvData->width(), yuvData->height(), YUVPixelFormat::I420, colorSpace);
yuvTexture->samplers = std::move(texturePlanes);
texture = std::static_pointer_cast<YUVTexture>(
Resource::AddToContext(context, yuvTexture, recycleKey));
texture =
std::static_pointer_cast<YUVTexture>(Resource::AddToCache(context, yuvTexture, recycleKey));
}
SubmitYUVTexture(context, yuvData, &texture->samplers);
return texture;
Expand All @@ -100,8 +99,7 @@ std::shared_ptr<Texture> Texture::MakeNV12(Context* context, const YUVData* yuvD
PixelFormat yuvFormats[YUVData::NV12_PLANE_COUNT] = {PixelFormat::GRAY_8, PixelFormat::RG_88};
BytesKey recycleKey = {};
ComputeRecycleKey(&recycleKey, yuvData->width(), yuvData->height(), YUVPixelFormat::NV12);
auto texture = std::static_pointer_cast<YUVTexture>(
context->resourceCache()->findRecyclableResource(recycleKey));
auto texture = Resource::FindRecycled<YUVTexture>(context, recycleKey);
if (texture == nullptr) {
auto texturePlanes = MakeTexturePlanes(context, yuvData, yuvFormats);
if (texturePlanes.empty()) {
Expand All @@ -110,8 +108,8 @@ std::shared_ptr<Texture> Texture::MakeNV12(Context* context, const YUVData* yuvD
auto yuvTexture =
new YUVTexture(yuvData->width(), yuvData->height(), YUVPixelFormat::NV12, colorSpace);
yuvTexture->samplers = std::move(texturePlanes);
texture = std::static_pointer_cast<YUVTexture>(
Resource::AddToContext(context, yuvTexture, recycleKey));
texture =
std::static_pointer_cast<YUVTexture>(Resource::AddToCache(context, yuvTexture, recycleKey));
}
SubmitYUVTexture(context, yuvData, &texture->samplers);
return texture;
Expand Down
4 changes: 2 additions & 2 deletions src/gpu/YUVTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ class YUVTexture : public Texture {

YUVTexture(int width, int height, YUVPixelFormat pixelFormat, YUVColorSpace colorSpace);

void onReleaseGPU() override;

private:
YUVPixelFormat _pixelFormat = YUVPixelFormat::I420;
YUVColorSpace _colorSpace = YUVColorSpace::BT601_LIMITED;

void onReleaseGPU() override;

friend class Texture;
};
} // namespace tgfx
6 changes: 2 additions & 4 deletions src/opengl/GLBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,15 @@ std::shared_ptr<GpuBuffer> GpuBuffer::Make(Context* context, const void* buffer,
unsigned target = bufferType == BufferType::Index ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
BytesKey recycleKey = {};
ComputeRecycleKey(&recycleKey, bufferType);
auto glBuffer = std::static_pointer_cast<GLBuffer>(
context->resourceCache()->findRecyclableResource(recycleKey));
auto glBuffer = Resource::FindRecycled<GLBuffer>(context, recycleKey);
auto gl = GLFunctions::Get(context);
if (glBuffer == nullptr) {
unsigned bufferID = 0;
gl->genBuffers(1, &bufferID);
if (bufferID == 0) {
return nullptr;
}
glBuffer =
Resource::AddToContext(context, new GLBuffer(bufferType, size, bufferID), recycleKey);
glBuffer = Resource::AddToCache(context, new GLBuffer(bufferType, size, bufferID), recycleKey);
} else {
glBuffer->_sizeInBytes = size;
}
Expand Down
9 changes: 5 additions & 4 deletions src/opengl/GLBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@ class GLBuffer : public GpuBuffer {
return _bufferID;
}

protected:
void onReleaseGPU() override;

private:
unsigned _bufferID = 0;

GLBuffer(BufferType bufferType, size_t size, unsigned bufferID)
: GpuBuffer(bufferType, size), _bufferID(bufferID) {
}

void onReleaseGPU() override;

unsigned _bufferID = 0;

friend class GpuBuffer;
};
} // namespace tgfx
5 changes: 3 additions & 2 deletions src/opengl/GLProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ class GLProgram : public Program {
return attributes;
}

protected:
void onReleaseGPU() override;

private:
struct RenderTargetState {
std::optional<int> width;
Expand All @@ -73,8 +76,6 @@ class GLProgram : public Program {

void setRenderTargetState(const GLRenderTarget* renderTarget);

void onReleaseGPU() override;

RenderTargetState renderTargetState;
unsigned programId = 0;
std::unique_ptr<GLUniformBuffer> uniformBuffer = nullptr;
Expand Down
Loading

0 comments on commit d864aee

Please sign in to comment.