Skip to content

Commit e9378cf

Browse files
authored
Move the thread-safety release mechanism from Resource to the OpenGL backend only. (#952)
1 parent 8e53e1e commit e9378cf

File tree

125 files changed

+639
-736
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+639
-736
lines changed

include/tgfx/gpu/Context.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class Context {
4949
*/
5050
Context(Device* device, GPU* gpu);
5151

52-
virtual ~Context();
52+
~Context();
5353

5454
/**
5555
* Returns the associated device.
@@ -203,11 +203,6 @@ class Context {
203203
SlidingWindowTracker* _maxValueTracker = nullptr;
204204
AtlasManager* _atlasManager = nullptr;
205205
std::shared_ptr<CommandBuffer> commandBuffer = nullptr;
206-
207-
void releaseAll(bool releaseGPU);
208-
209-
friend class Device;
210-
friend class Resource;
211206
};
212207

213208
} // namespace tgfx

include/tgfx/gpu/Device.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,16 @@ class Device {
5555

5656
protected:
5757
std::mutex locker = {};
58+
GPU* _gpu = nullptr;
5859
Context* context = nullptr;
5960
std::weak_ptr<Device> weakThis;
6061

6162
explicit Device(std::unique_ptr<GPU> gpu);
62-
void releaseAll();
6363
virtual bool onLockContext();
6464
virtual void onUnlockContext();
6565

6666
private:
6767
uint32_t _uniqueID = 0;
68-
GPU* _gpu = nullptr;
6968
bool contextLocked = false;
7069

7170
friend class ResourceCache;

include/tgfx/gpu/RuntimeProgram.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,6 @@ class RuntimeProgram {
5050
private:
5151
Context* context = nullptr;
5252

53-
friend class RuntimeProgramWrapper;
53+
friend class GLRuntimeProgram;
5454
};
5555
} // namespace tgfx

include/tgfx/gpu/opengl/GLDevice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ class GLDevice : public Device {
6767

6868
GLDevice(std::unique_ptr<GPU> gpu, void* nativeHandle);
6969

70+
void releaseAll();
71+
7072
friend class GLContext;
7173
};
7274
} // namespace tgfx

include/tgfx/gpu/opengl/eagl/EAGLWindow.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ class EAGLWindow : public Window {
3232
static std::shared_ptr<EAGLWindow> MakeFrom(CAEAGLLayer* layer,
3333
std::shared_ptr<GLDevice> device = nullptr);
3434

35-
~EAGLWindow() override;
36-
3735
protected:
3836
std::shared_ptr<Surface> onCreateSurface(Context* context) override;
3937
void onPresent(Context* context, int64_t presentationTime) override;

src/core/AtlasManager.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,6 @@ void AtlasManager::postFlush() {
9696
}
9797
}
9898

99-
void AtlasManager::releaseAll() {
100-
for (auto& atlas : atlases) {
101-
atlas = nullptr;
102-
}
103-
}
10499
AtlasToken AtlasManager::nextFlushToken() const {
105100
return atlasTokenTracker.nextToken();
106101
}

src/core/AtlasManager.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ class AtlasManager : public AtlasGenerationCounter {
3939

4040
void postFlush();
4141

42-
void releaseAll();
43-
4442
AtlasToken nextFlushToken() const;
4543

4644
private:

src/gpu/resources/UnreferencedResourceQueue.cpp renamed to src/core/utils/ReturnQueue.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,34 @@
1515
// and limitations under the license.
1616
//
1717
/////////////////////////////////////////////////////////////////////////////////////////////////
18-
#include "UnreferencedResourceQueue.h"
19-
#include "gpu/resources/Resource.h"
18+
19+
#include "ReturnQueue.h"
20+
#include "core/utils/Log.h"
2021

2122
namespace tgfx {
23+
std::shared_ptr<ReturnQueue> ReturnQueue::Make() {
24+
auto queue = std::shared_ptr<ReturnQueue>(new ReturnQueue());
25+
queue->weakThis = queue;
26+
return queue;
27+
}
28+
29+
void ReturnQueue::NotifyReferenceReachedZero(ReturnNode* node) {
30+
DEBUG_ASSERT(node->unreferencedQueue != nullptr);
31+
node->unreferencedQueue->queue.enqueue(node);
32+
node->unreferencedQueue = nullptr;
33+
}
2234

23-
UnreferencedResourceQueue::~UnreferencedResourceQueue() {
24-
Resource* resource = nullptr;
25-
while (queue.try_dequeue(resource)) {
26-
delete resource;
35+
ReturnQueue::~ReturnQueue() {
36+
ReturnNode* node = nullptr;
37+
while (queue.try_dequeue(node)) {
38+
delete node;
2739
}
2840
}
2941

42+
std::shared_ptr<ReturnNode> ReturnQueue::makeShared(ReturnNode* node) {
43+
auto reference = std::shared_ptr<ReturnNode>(node, NotifyReferenceReachedZero);
44+
reference->unreferencedQueue = weakThis.lock();
45+
return reference;
46+
}
47+
3048
} // namespace tgfx

src/core/utils/ReturnQueue.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/////////////////////////////////////////////////////////////////////////////////////////////////
2+
//
3+
// Tencent is pleased to support the open source community by making tgfx available.
4+
//
5+
// Copyright (C) 2025 Tencent. All rights reserved.
6+
//
7+
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
8+
// in compliance with the License. You may obtain a copy of the License at
9+
//
10+
// https://opensource.org/licenses/BSD-3-Clause
11+
//
12+
// unless required by applicable law or agreed to in writing, software distributed under the
13+
// license is distributed on an "as is" basis, without warranties or conditions of any kind,
14+
// either express or implied. see the license for the specific language governing permissions
15+
// and limitations under the license.
16+
//
17+
/////////////////////////////////////////////////////////////////////////////////////////////////
18+
19+
#pragma once
20+
21+
#include <concurrentqueue.h>
22+
#include <memory>
23+
24+
namespace tgfx {
25+
class ReturnNode;
26+
27+
/**
28+
* A thread-safe queue for storing ReturnNode objects that are no longer referenced. When a
29+
* ReturnNode's reference count drops to zero, it is added to this queue for later processing.
30+
* Any returned nodes that are not processed will be deleted when the ReturnQueue is destroyed.
31+
*/
32+
class ReturnQueue {
33+
public:
34+
/**
35+
* Creates a new ReturnQueue instance.
36+
*/
37+
static std::shared_ptr<ReturnQueue> Make();
38+
39+
~ReturnQueue();
40+
41+
/**
42+
* Wraps a ReturnNode in a shared_ptr that will add the node to this queue when its reference
43+
* count reaches zero.
44+
*/
45+
std::shared_ptr<ReturnNode> makeShared(ReturnNode* node);
46+
47+
/**
48+
* Attempts to dequeue a ReturnNode from the queue. Returns nullptr if the queue is empty.
49+
*/
50+
ReturnNode* dequeue() {
51+
ReturnNode* node = nullptr;
52+
return queue.try_dequeue(node) ? node : nullptr;
53+
}
54+
55+
private:
56+
std::weak_ptr<ReturnQueue> weakThis;
57+
moodycamel::ConcurrentQueue<ReturnNode*> queue;
58+
59+
static void NotifyReferenceReachedZero(ReturnNode* node);
60+
61+
ReturnQueue() = default;
62+
};
63+
64+
/**
65+
* A base class for objects that can be managed by a ReturnQueue. When the reference count of a
66+
* ReturnNode reaches zero, it is added to its associated ReturnQueue.
67+
*/
68+
class ReturnNode {
69+
public:
70+
virtual ~ReturnNode() = default;
71+
72+
private:
73+
std::shared_ptr<ReturnQueue> unreferencedQueue = nullptr;
74+
75+
friend class ReturnQueue;
76+
};
77+
} // namespace tgfx

src/gpu/CommandEncoder.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,28 +49,29 @@ class CommandEncoder {
4949
* @param dstTexture The destination texture to copy to.
5050
* @param dstOffset The offset in the destination texture where the copied region will be placed.
5151
*/
52-
virtual void copyTextureToTexture(GPUTexture* srcTexture, const Rect& srcRect,
53-
GPUTexture* dstTexture, const Point& dstOffset) = 0;
52+
virtual void copyTextureToTexture(std::shared_ptr<GPUTexture> srcTexture, const Rect& srcRect,
53+
std::shared_ptr<GPUTexture> dstTexture,
54+
const Point& dstOffset) = 0;
5455

5556
/**
5657
* Encodes a command that generates mipmaps for the specified GPUTexture from the base level to
5758
* the highest level. This method only has an effect if the texture was created with mipmap
5859
* enabled.
5960
*/
60-
virtual void generateMipmapsForTexture(GPUTexture* texture) = 0;
61+
virtual void generateMipmapsForTexture(std::shared_ptr<GPUTexture> texture) = 0;
6162

6263
/**
6364
* Inserts a signal GPUFence into the command encoder. This is used to notify other
6465
* synchronization points once the preceding GPU commands have finished executing. Returns nullptr
6566
* if the GPUFence cannot be created or inserted.
6667
*/
67-
virtual std::unique_ptr<GPUFence> insertFence() = 0;
68+
virtual std::shared_ptr<GPUFence> insertFence() = 0;
6869

6970
/**
7071
* Makes subsequent commands added to the command encoder to wait until the specified GPUFence is
7172
* signaled.
7273
*/
73-
virtual void waitForFence(GPUFence* fence) = 0;
74+
virtual void waitForFence(std::shared_ptr<GPUFence> fence) = 0;
7475

7576
/**
7677
* Finalizes command encoding and returns a CommandBuffer with all recorded commands. You can then

0 commit comments

Comments
 (0)