Multiple-threads loading (#425)

Add Multiple-threads loading demo
This commit is contained in:
Vitaliy
2020-03-15 12:25:18 +04:00
committed by GitHub
parent f3c8885d8f
commit 5f7072a18d
49 changed files with 525 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
# Multiple-threads loading demo
This demo shows how you can organize background loading using multiple threads.
Language: GDScript
Renderer: GLES 2
## How does it work?
[Official documentation - Using multiple threads](http://docs.godotengine.org/en/3.2/tutorials/io/background_loading.html#using-multiple-threads)
## Screenshots
![Screenshot](screenshots/screenshot.png)

View File

@@ -0,0 +1,18 @@
[gd_resource type="Environment" load_steps=2 format=2]
[sub_resource type="ProceduralSky" id=1]
radiance_size = 4
sky_top_color = Color( 0.0470588, 0.454902, 0.976471, 1 )
sky_horizon_color = Color( 0.556863, 0.823529, 0.909804, 1 )
sky_curve = 0.25
ground_bottom_color = Color( 0.101961, 0.145098, 0.188235, 1 )
ground_horizon_color = Color( 0.482353, 0.788235, 0.952941, 1 )
ground_curve = 0.01
sun_energy = 16.0
[resource]
background_mode = 2
background_sky = SubResource( 1 )
fog_height_min = 0.0
fog_height_max = 100.0
ssao_quality = 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -0,0 +1,219 @@
[gd_scene load_steps=41 format=2]
[ext_resource path="res://images/icon_1.png" type="Texture" id=1]
[ext_resource path="res://images/icon_2.png" type="Texture" id=2]
[ext_resource path="res://images/icon_3.png" type="Texture" id=3]
[ext_resource path="res://images/icon_4.png" type="Texture" id=4]
[ext_resource path="res://images/icon_5.png" type="Texture" id=5]
[ext_resource path="res://images/icon_6.png" type="Texture" id=6]
[ext_resource path="res://images/icon_7.png" type="Texture" id=7]
[ext_resource path="res://images/icon_8.png" type="Texture" id=8]
[ext_resource path="res://images/icon_9.png" type="Texture" id=9]
[ext_resource path="res://images/icon_10.png" type="Texture" id=10]
[ext_resource path="res://images/icon_11.png" type="Texture" id=11]
[ext_resource path="res://images/icon_12.png" type="Texture" id=12]
[ext_resource path="res://images/icon_13.png" type="Texture" id=13]
[ext_resource path="res://images/icon_14.png" type="Texture" id=14]
[ext_resource path="res://images/icon_15.png" type="Texture" id=15]
[ext_resource path="res://images/icon_16.png" type="Texture" id=16]
[ext_resource path="res://images/icon_17.png" type="Texture" id=17]
[ext_resource path="res://images/icon_18.png" type="Texture" id=18]
[ext_resource path="res://images/icon_19.png" type="Texture" id=19]
[ext_resource path="res://images/icon_20.png" type="Texture" id=20]
[ext_resource path="res://images/icon_21.png" type="Texture" id=21]
[ext_resource path="res://images/icon_22.png" type="Texture" id=22]
[ext_resource path="res://images/icon_23.png" type="Texture" id=23]
[ext_resource path="res://images/icon_24.png" type="Texture" id=24]
[ext_resource path="res://images/icon_25.png" type="Texture" id=25]
[ext_resource path="res://images/icon_26.png" type="Texture" id=26]
[ext_resource path="res://images/icon_27.png" type="Texture" id=27]
[ext_resource path="res://images/icon_28.png" type="Texture" id=28]
[ext_resource path="res://images/icon_29.png" type="Texture" id=29]
[ext_resource path="res://images/icon_30.png" type="Texture" id=30]
[ext_resource path="res://images/icon_31.png" type="Texture" id=31]
[ext_resource path="res://images/icon_32.png" type="Texture" id=32]
[ext_resource path="res://images/icon_33.png" type="Texture" id=33]
[ext_resource path="res://images/icon_34.png" type="Texture" id=34]
[ext_resource path="res://images/icon_35.png" type="Texture" id=35]
[ext_resource path="res://images/icon_36.png" type="Texture" id=36]
[ext_resource path="res://images/icon_37.png" type="Texture" id=37]
[ext_resource path="res://images/icon_38.png" type="Texture" id=38]
[ext_resource path="res://images/icon_39.png" type="Texture" id=39]
[ext_resource path="res://images/icon_40.png" type="Texture" id=40]
[node name="Node" type="Node"]
[node name="ColorRect" type="ColorRect" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
color = Color( 0, 0, 0, 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="."]
margin_left = 452.0
margin_top = 272.0
margin_right = 572.0
margin_bottom = 286.0
text = "Main scene loaded"
[node name="Sprite1" type="Sprite" parent="."]
visible = false
texture = ExtResource( 1 )
[node name="Sprite2" type="Sprite" parent="."]
visible = false
texture = ExtResource( 2 )
[node name="Sprite3" type="Sprite" parent="."]
visible = false
texture = ExtResource( 3 )
[node name="Sprite4" type="Sprite" parent="."]
visible = false
texture = ExtResource( 4 )
[node name="Sprite5" type="Sprite" parent="."]
visible = false
texture = ExtResource( 5 )
[node name="Sprite6" type="Sprite" parent="."]
visible = false
texture = ExtResource( 6 )
[node name="Sprite7" type="Sprite" parent="."]
visible = false
texture = ExtResource( 7 )
[node name="Sprite8" type="Sprite" parent="."]
visible = false
texture = ExtResource( 8 )
[node name="Sprite9" type="Sprite" parent="."]
visible = false
texture = ExtResource( 9 )
[node name="Sprite10" type="Sprite" parent="."]
visible = false
texture = ExtResource( 10 )
[node name="Sprite11" type="Sprite" parent="."]
visible = false
texture = ExtResource( 11 )
[node name="Sprite12" type="Sprite" parent="."]
visible = false
texture = ExtResource( 12 )
[node name="Sprite13" type="Sprite" parent="."]
visible = false
texture = ExtResource( 13 )
[node name="Sprite14" type="Sprite" parent="."]
visible = false
texture = ExtResource( 14 )
[node name="Sprite15" type="Sprite" parent="."]
visible = false
texture = ExtResource( 15 )
[node name="Sprite16" type="Sprite" parent="."]
visible = false
texture = ExtResource( 16 )
[node name="Sprite17" type="Sprite" parent="."]
visible = false
texture = ExtResource( 17 )
[node name="Sprite18" type="Sprite" parent="."]
visible = false
texture = ExtResource( 18 )
[node name="Sprite19" type="Sprite" parent="."]
visible = false
texture = ExtResource( 19 )
[node name="Sprite20" type="Sprite" parent="."]
visible = false
texture = ExtResource( 20 )
[node name="Sprite21" type="Sprite" parent="."]
visible = false
texture = ExtResource( 21 )
[node name="Sprite22" type="Sprite" parent="."]
visible = false
texture = ExtResource( 22 )
[node name="Sprite23" type="Sprite" parent="."]
visible = false
texture = ExtResource( 23 )
[node name="Sprite24" type="Sprite" parent="."]
visible = false
texture = ExtResource( 24 )
[node name="Sprite25" type="Sprite" parent="."]
visible = false
texture = ExtResource( 25 )
[node name="Sprite26" type="Sprite" parent="."]
visible = false
texture = ExtResource( 26 )
[node name="Sprite27" type="Sprite" parent="."]
visible = false
texture = ExtResource( 27 )
[node name="Sprite28" type="Sprite" parent="."]
visible = false
texture = ExtResource( 28 )
[node name="Sprite29" type="Sprite" parent="."]
visible = false
texture = ExtResource( 29 )
[node name="Sprite30" type="Sprite" parent="."]
visible = false
texture = ExtResource( 30 )
[node name="Sprite31" type="Sprite" parent="."]
visible = false
texture = ExtResource( 31 )
[node name="Sprite32" type="Sprite" parent="."]
visible = false
texture = ExtResource( 32 )
[node name="Sprite33" type="Sprite" parent="."]
visible = false
texture = ExtResource( 33 )
[node name="Sprite34" type="Sprite" parent="."]
visible = false
texture = ExtResource( 34 )
[node name="Sprite35" type="Sprite" parent="."]
visible = false
texture = ExtResource( 35 )
[node name="Sprite36" type="Sprite" parent="."]
visible = false
texture = ExtResource( 36 )
[node name="Sprite37" type="Sprite" parent="."]
visible = false
texture = ExtResource( 37 )
[node name="Sprite38" type="Sprite" parent="."]
visible = false
texture = ExtResource( 38 )
[node name="Sprite39" type="Sprite" parent="."]
visible = false
texture = ExtResource( 39 )
[node name="Sprite40" type="Sprite" parent="."]
visible = false
texture = ExtResource( 40 )

View File

@@ -0,0 +1,33 @@
extends Node
var Queue
func _ready():
# Initialize
Queue = preload("res://resource_queue.gd").new()
# Call after you instance the class to start the thread.
Queue.start()
func _process(_delta):
# Returns true if a resource is done loading and ready to be retrieved
if Queue.is_ready("res://main.tscn"):
set_process(false)
# Returns the fully loaded resource
var next_scene = Queue.get_resource("res://main.tscn").instance()
get_node("/root").add_child(next_scene)
get_node("/root").remove_child(self)
queue_free()
else:
# Get the progress of a resource
var progress = round(Queue.get_progress("res://main.tscn")*100)
get_node("ProgressBar").set_value(progress)
func _on_Button_button_up():
get_node("Button").hide()
set_process(true)
# Queue a resource
Queue.queue_resource("res://main.tscn", true)

View File

@@ -0,0 +1,70 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://preload.gd" type="Script" id=1]
[sub_resource type="GDScript" id=1]
script/source = "extends LinkButton
func _on_LinkButton_button_up():
OS.shell_open(\"http://docs.godotengine.org/en/3.2/tutorials/io/background_loading.html#using-multiple-threads\")
"
[node name="Node" type="Node"]
script = ExtResource( 1 )
[node name="ColorRect" type="ColorRect" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
color = Color( 0.00390625, 0, 0, 1 )
[node name="ProgressBar" type="ProgressBar" parent="."]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -225.0
margin_top = -66.0
margin_right = 225.0
margin_bottom = 66.0
step = 1.0
[node name="Button" type="Button" parent="."]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -223.0
margin_top = -193.0
margin_right = 224.0
margin_bottom = -84.0
text = "Load next scene"
[node name="Label" type="Label" parent="."]
anchor_left = 0.5
anchor_right = 0.5
margin_left = -267.0
margin_top = 12.0
margin_right = 267.0
margin_bottom = 82.0
text = "Multiple-treads loading demo
The next scene contains 40 resource files. Loading is done using multiple threads.
The download speed depends on the performance of your device.
For more information, see:"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="LinkButton" type="LinkButton" parent="."]
anchor_left = 0.5
anchor_right = 0.5
margin_left = -233.0
margin_top = 80.0
margin_right = 233.0
margin_bottom = 94.0
text = "http://docs.godotengine.org/en/3.2/tutorials/io/background_loading.html"
script = SubResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[connection signal="button_up" from="Button" to="." method="_on_Button_button_up"]
[connection signal="button_up" from="LinkButton" to="LinkButton" method="_on_LinkButton_button_up"]

View File

@@ -0,0 +1,25 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=4
_global_script_classes=[ ]
_global_script_class_icons={
}
[application]
config/name="Multiple threads loading"
run/main_scene="res://preload.tscn"
config/icon="res://icon.png"
[rendering]
quality/driver/driver_name="GLES2"
environment/default_environment="res://default_env.tres"

View File

@@ -0,0 +1,145 @@
var thread
var mutex
var sem
var time_max = 100 # Milliseconds.
var queue = []
var pending = {}
func _lock(_caller):
mutex.lock()
func _unlock(_caller):
mutex.unlock()
func _post(_caller):
sem.post()
func _wait(_caller):
sem.wait()
func queue_resource(path, p_in_front = false):
_lock("queue_resource")
if path in pending:
_unlock("queue_resource")
return
elif ResourceLoader.has_cached(path):
var res = ResourceLoader.load(path)
pending[path] = res
_unlock("queue_resource")
return
else:
var res = ResourceLoader.load_interactive(path)
res.set_meta("path", path)
if p_in_front:
queue.insert(0, res)
else:
queue.push_back(res)
pending[path] = res
_post("queue_resource")
_unlock("queue_resource")
return
func cancel_resource(path):
_lock("cancel_resource")
if path in pending:
if pending[path] is ResourceInteractiveLoader:
queue.erase(pending[path])
pending.erase(path)
_unlock("cancel_resource")
func get_progress(path):
_lock("get_progress")
var ret = -1
if path in pending:
if pending[path] is ResourceInteractiveLoader:
ret = float(pending[path].get_stage()) / float(pending[path].get_stage_count())
else:
ret = 1.0
_unlock("get_progress")
return ret
func is_ready(path):
var ret
_lock("is_ready")
if path in pending:
ret = !(pending[path] is ResourceInteractiveLoader)
else:
ret = false
_unlock("is_ready")
return ret
func _wait_for_resource(res, path):
_unlock("wait_for_resource")
while true:
VisualServer.sync()
OS.delay_usec(16000) # Wait approximately 1 frame.
_lock("wait_for_resource")
if queue.size() == 0 || queue[0] != res:
return pending[path]
_unlock("wait_for_resource")
func get_resource(path):
_lock("get_resource")
if path in pending:
if pending[path] is ResourceInteractiveLoader:
var res = pending[path]
if res != queue[0]:
var pos = queue.find(res)
queue.remove(pos)
queue.insert(0, res)
res = _wait_for_resource(res, path)
pending.erase(path)
_unlock("return")
return res
else:
var res = pending[path]
pending.erase(path)
_unlock("return")
return res
else:
_unlock("return")
return ResourceLoader.load(path)
func thread_process():
_wait("thread_process")
_lock("process")
while queue.size() > 0:
var res = queue[0]
_unlock("process_poll")
var ret = res.poll()
_lock("process_check_queue")
if ret == ERR_FILE_EOF || ret != OK:
var path = res.get_meta("path")
if path in pending: # Else, it was already retrieved.
pending[res.get_meta("path")] = res.get_resource()
# Something might have been put at the front of the queue while
# we polled, so use erase instead of remove.
queue.erase(res)
_unlock("process")
func thread_func(_u):
while true:
thread_process()
func start():
mutex = Mutex.new()
sem = Semaphore.new()
thread = Thread.new()
thread.start(self, "thread_func", 0)

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB