Skip to content

Commit b281f6f

Browse files
committed
Add threaded GLTF loading using worker thread pool
1 parent 4ee6eb8 commit b281f6f

File tree

2 files changed

+23
-34
lines changed

2 files changed

+23
-34
lines changed

mirror-godot-app/scripts/net/file_cache.gd

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
class_name FileCache
22
extends Node
33

4-
signal threaded_model_loaded(cache_key: String, node: Node)
5-
64
const _STORAGE_CACHE_FILENAME: String = "cache.json"
75

86
var _storage_cache: Dictionary = {}
@@ -22,18 +20,6 @@ func _init() -> void:
2220
_setup_storage_directory()
2321

2422

25-
26-
func _process(_delta: float) -> void:
27-
_manage_queue()
28-
29-
30-
## Manages the threaded model loading queue.
31-
func _manage_queue() -> void:
32-
if _model_load_queue.size() == 0:
33-
return
34-
_thread_load_model(_model_load_queue.pop_front())
35-
36-
3723
## Returns true if the cache file exists on the disk.
3824
func cached_file_exists(cache_key: String) -> bool:
3925
cache_key = cache_key.uri_decode()
@@ -96,6 +82,8 @@ func _save_stored_files_cache() -> void:
9682

9783
## Saves a bytes file to the cache location on disk and adds it to the cache library.
9884
func save_bytes_file_to_cache(cache_key: String, file_name: String, file_data: PackedByteArray) -> void:
85+
if FileAccess.file_exists(file_name):
86+
return
9987
var saved = save_bytes_file(file_name, file_data)
10088
if not saved:
10189
return
@@ -141,36 +129,37 @@ func try_load_cached_file(cache_key: String) -> Variant:
141129
return null
142130

143131

144-
func load_model_threaded(cache_key: String) -> Promise:
132+
var _cached_pairs = {}
133+
134+
func load_gltf_thread_task(cache_key: String) -> Promise:
145135
for m in _model_load_queue:
146136
if m.key == cache_key:
147137
return m.promise
148138
var pair = KeyPromisePair.new()
149139
pair.key = cache_key
150140
pair.promise = Promise.new()
151141

152-
# TODO: Fix multithreaded model loading, newer engine versions
153-
# complain about this not being on the main thread.
154-
# queue for later when needed
155-
if cached_file_exists(pair.key):
156-
_model_load_queue.append(pair)
157-
return pair.promise
158-
159-
# _model_load_thread.start(_thread_load_model.bind(pair))
160-
_thread_load_model(pair)
161-
return pair.promise
162-
163-
164-
func _thread_load_model(pair: KeyPromisePair) -> void:
165142
if not cached_file_exists(pair.key):
166143
pair.promise.set_error("File does not exists, cannot load.")
167144
return
168145
var file_name: String = _storage_cache.get(pair.key, "")
169146
var file_path: String = get_file_path(file_name)
170-
var node = TMFileUtil.load_gltf_file_as_node(file_path, Zone.is_host())
171-
_model_loaded.call_deferred(pair, node)
172147

148+
var task_id = WorkerThreadPool.add_task(func():
149+
Thread.set_thread_safety_checks_enabled(false)
150+
var node = TMFileUtil.load_gltf_file_as_node(file_path, Zone.is_host())
151+
call_thread_safe("_cached_file_is_loaded", pair, node)
152+
)
153+
_cached_pairs[task_id]
173154

174-
func _model_loaded(pair: KeyPromisePair, node: Node) -> void:
175-
threaded_model_loaded.emit(pair.key, node)
155+
156+
return pair.promise
157+
158+
## THIS MUST BE ON THE MAIN THREAD
159+
func _cached_file_is_loaded(pair, node):
160+
print("Node name: ", node.get_name())
161+
if node == null:
162+
push_error("Can't load GLTF")
163+
pair.promise.set_error("Failed to load mesh, ignoring and skipping")
164+
return
176165
pair.promise.set_result(node)

mirror-godot-app/scripts/net/file_client.gd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func get_file(url: String, priority: Enums.DownloadPriority = Enums.DownloadPrio
8383
promise.set_result(files.get(url))
8484
return promise
8585
if Util.path_is_model(url) and _file_cache.cached_file_exists(url):
86-
var promise = _file_cache.load_model_threaded(url)
86+
var promise = _file_cache.load_gltf_thread_task(url)
8787
promise.connect_func_to_fulfill(_on_loaded_model_threaded.bind(url, promise))
8888
return promise
8989
var cached_file = _file_cache.try_load_cached_file(url)
@@ -119,7 +119,7 @@ func get_file(url: String, priority: Enums.DownloadPriority = Enums.DownloadPrio
119119
## so the model gets uniquely generated from a GLTFDocument.
120120
## TODO: Assess storing GLTFDocument in memory and generating node from that instead of entire file read.
121121
func get_model_instance_promise(url: String) -> Promise:
122-
return _file_cache.load_model_threaded(url)
122+
return _file_cache.load_gltf_thread_task(url)
123123

124124

125125
func _promise_fulfill_successful(request: Dictionary, promise: Promise) -> void:

0 commit comments

Comments
 (0)