└── addons └── compute_worker ├── compute_worker_icon.png ├── gpu_uniforms ├── gpu_uniform_icon.png ├── gpu_uniform.tres ├── gpu_float.tres ├── gpu_struct.tres ├── gpu_vector3.tres ├── gpu_vector3i.tres ├── gpu_integer.tres ├── gpu_boolean.tres ├── gpu_packed_float64_array.tres ├── gpu_packed_vector3_array.tres ├── gpu_packed_byte_array.tres ├── gpu_struct_array.tres ├── gpu_color.tres ├── gpu_vector2.tres ├── gpu_vector4.tres ├── gpu_image.tres ├── gpu_texture_2d_array.tres ├── gpu_uniform_icon.png.import ├── gpu_integer.gd ├── gpu_packed_byte_array.gd ├── gpu_boolean.gd ├── gpu_color.gd ├── gpu_float.gd ├── gpu_vector4.gd ├── gpu_vector3.gd ├── gpu_vector3i.gd ├── gpu_vector2.gd ├── gpu_struct_array.gd ├── gpu_packed_vector3_array.gd ├── gpu_image.gd ├── gpu_packed_float64_array.gd ├── gpu_texture_2d_array.gd ├── gpu_struct.gd └── gpu_uniform.gd ├── uniform_sets ├── uniform_set_icon.png ├── uniform_set_icon.png.import └── uniform_set.gd ├── plugin.cfg ├── plugin.gd ├── compute_worker.tscn ├── example ├── test_glsl.glsl.import ├── test_glsl.glsl ├── example_uniform_set.tres ├── compute_example.gd └── compute_example.tscn ├── compute_worker_icon.png.import └── compute_worker.gd /addons/compute_worker/compute_worker_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardensdev/ComputeWorker/HEAD/addons/compute_worker/compute_worker_icon.png -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_uniform_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardensdev/ComputeWorker/HEAD/addons/compute_worker/gpu_uniforms/gpu_uniform_icon.png -------------------------------------------------------------------------------- /addons/compute_worker/uniform_sets/uniform_set_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardensdev/ComputeWorker/HEAD/addons/compute_worker/uniform_sets/uniform_set_icon.png -------------------------------------------------------------------------------- /addons/compute_worker/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="ComputeWorker" 4 | description="An abstraction of Godot's RenderingDevice compute API that provides a UI for creating compute pipelines." 5 | author="Aaron Icenhour" 6 | version="1.2" 7 | script="plugin.gd" 8 | -------------------------------------------------------------------------------- /addons/compute_worker/plugin.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends EditorPlugin 3 | 4 | 5 | func _enter_tree() -> void: 6 | # Initialization of the plugin goes here. 7 | pass 8 | 9 | 10 | func _exit_tree() -> void: 11 | # Clean-up of the plugin goes here. 12 | pass 13 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_uniform.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_uniform.gd" id="1_tjkvb"] 4 | 5 | [resource] 6 | script = ExtResource("1_tjkvb") 7 | -------------------------------------------------------------------------------- /addons/compute_worker/compute_worker.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://mjjoyr6m3r66"] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/compute_worker.gd" id="1_jx8p5"] 4 | 5 | [node name="ComputeWorker" type="Node"] 6 | script = ExtResource("1_jx8p5") 7 | uniforms = [] 8 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_float.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_float.gd" id="1_8vtds"] 4 | 5 | [resource] 6 | script = ExtResource("1_8vtds") 7 | data = 0.0 8 | binding = 0 9 | uniform_type = 0 10 | alias = "" 11 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_struct.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_struct.gd" id="1_3o4qa"] 4 | 5 | [resource] 6 | script = ExtResource("1_3o4qa") 7 | struct_data = null 8 | binding = 0 9 | uniform_type = 1 10 | alias = "" 11 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_vector3.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_vector3.gd" id="1_64thl"] 4 | 5 | [resource] 6 | script = ExtResource("1_64thl") 7 | data = Vector3(0, 0, 0) 8 | binding = 0 9 | uniform_type = 0 10 | alias = "" 11 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_vector3i.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_vector3i.gd" id="1_2od2j"] 4 | 5 | [resource] 6 | resource_local_to_scene = true 7 | script = ExtResource("1_2od2j") 8 | data = Vector3i(0, 0, 0) 9 | binding = 0 10 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_integer.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://ilxhjl8o6e6c"] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_integer.gd" id="1_qo6gq"] 4 | 5 | [resource] 6 | script = ExtResource("1_qo6gq") 7 | data = 0 8 | binding = 0 9 | uniform_type = 0 10 | alias = "" 11 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_boolean.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3 uid="uid://cr1yw8ip7qq4b"] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_boolean.gd" id="1_upsvg"] 4 | 5 | [resource] 6 | script = ExtResource("1_upsvg") 7 | data = false 8 | binding = 0 9 | uniform_type = 0 10 | alias = "" 11 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_packed_float64_array.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_packed_float64_array.gd" id="1_7h8xe"] 4 | 5 | [resource] 6 | script = ExtResource("1_7h8xe") 7 | data = [0.0] 8 | binding = 0 9 | uniform_type = 0 10 | alias = "" 11 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_packed_vector3_array.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_packed_vector3_array.gd" id="1_jcakp"] 4 | 5 | [resource] 6 | script = ExtResource("1_jcakp") 7 | data = null 8 | binding = 0 9 | uniform_type = 0 10 | alias = "" 11 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_packed_byte_array.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_packed_byte_array.gd" id="1_0ll82"] 4 | 5 | [resource] 6 | script = ExtResource("1_0ll82") 7 | data = PackedByteArray(0) 8 | binding = 0 9 | uniform_type = 0 10 | alias = "" 11 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_struct_array.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_struct_array.gd" id="1_lih0g"] 4 | 5 | [resource] 6 | script = ExtResource("1_lih0g") 7 | struct_array = null 8 | struct_data = null 9 | binding = 0 10 | uniform_type = 1 11 | alias = "" 12 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_color.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=2 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_color.gd" id="1_uy6r7"] 4 | 5 | [resource] 6 | resource_local_to_scene = true 7 | script = ExtResource("1_uy6r7") 8 | data = Color(0, 0, 0, 1) 9 | binding = 2 10 | uniform_type = 1 11 | alias = "color" 12 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_vector2.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="GPU_Vector2" load_steps=2 format=3 uid="uid://veemm371itsg"] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_vector2.gd" id="1_45tnd"] 4 | 5 | [resource] 6 | script = ExtResource("1_45tnd") 7 | data = Vector2(0, 0) 8 | binding = 0 9 | uniform_type = 0 10 | alias = "" 11 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_vector4.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="GPU_Vector4" load_steps=2 format=3 uid="uid://bq6cskr03y5ah"] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_vector4.gd" id="1_nk4m7"] 4 | 5 | [resource] 6 | script = ExtResource("1_nk4m7") 7 | data = Vector4(0, 0, 0, 0) 8 | binding = 0 9 | uniform_type = 0 10 | alias = "" 11 | -------------------------------------------------------------------------------- /addons/compute_worker/example/test_glsl.glsl.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="glsl" 4 | type="RDShaderFile" 5 | uid="uid://c5mtrei2xsp1w" 6 | path="res://.godot/imported/test_glsl.glsl-de9866e2f7da8ddc1d2ee2e95de82d21.res" 7 | 8 | [deps] 9 | 10 | source_file="res://addons/compute_worker/example/test_glsl.glsl" 11 | dest_files=["res://.godot/imported/test_glsl.glsl-de9866e2f7da8ddc1d2ee2e95de82d21.res"] 12 | 13 | [params] 14 | 15 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_image.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=3 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_image.gd" id="1_rdf03"] 4 | 5 | [sub_resource type="Image" id="Image_7uu5t"] 6 | 7 | [resource] 8 | resource_local_to_scene = true 9 | script = ExtResource("1_rdf03") 10 | data = SubResource("Image_7uu5t") 11 | image_size = null 12 | binding = null 13 | image_format = null 14 | alias = "" 15 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_texture_2d_array.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=3 format=3] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_texture_2d_array.gd" id="1_cmdef"] 4 | 5 | [sub_resource type="Texture2DArray" id="Texture2DArray_f7hlw"] 6 | 7 | [resource] 8 | resource_local_to_scene = true 9 | script = ExtResource("1_cmdef") 10 | data = SubResource("Texture2DArray_f7hlw") 11 | texture_array_size = Vector3i(5, 5, 5) 12 | binding = 0 13 | image_format = 108 14 | -------------------------------------------------------------------------------- /addons/compute_worker/compute_worker_icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bks4tj4wktdx7" 6 | path="res://.godot/imported/compute_worker_icon.png-d4caf552b037531d7ae1239ac0a9376c.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/compute_worker/compute_worker_icon.png" 14 | dest_files=["res://.godot/imported/compute_worker_icon.png-d4caf552b037531d7ae1239ac0a9376c.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_uniform_icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://b4jad856qhwhs" 6 | path="res://.godot/imported/gpu_uniform_icon.png-0e10104c3f71dc84e00a0c86654386ca.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/compute_worker/gpu_uniforms/gpu_uniform_icon.png" 14 | dest_files=["res://.godot/imported/gpu_uniform_icon.png-0e10104c3f71dc84e00a0c86654386ca.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/compute_worker/uniform_sets/uniform_set_icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dlhonrqe46tlw" 6 | path="res://.godot/imported/uniform_set_icon.png-534a10de97005421149d27af8a2c917b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/compute_worker/uniform_sets/uniform_set_icon.png" 14 | dest_files=["res://.godot/imported/uniform_set_icon.png-534a10de97005421149d27af8a2c917b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/compute_worker/uniform_sets/uniform_set.gd: -------------------------------------------------------------------------------- 1 | @icon("res://addons/compute_worker/uniform_sets/uniform_set_icon.png") 2 | 3 | extends Resource 4 | class_name UniformSet 5 | 6 | ## The list of GPUUniforms to be bound to the shader 7 | @export var uniforms: Array[GPUUniform] = [] 8 | ## The set id as defined in the shader 9 | @export var set_id: int = 0 10 | 11 | var uniform_set_rid: RID = RID() 12 | 13 | 14 | func initialize(rd: RenderingDevice, shader: RID) -> void: 15 | 16 | var uniform_set = [] 17 | 18 | for i in range(uniforms.size()): 19 | 20 | var uniform = uniforms[i].initialize(rd) 21 | uniform_set.push_back(uniform) 22 | 23 | uniform_set_rid = rd.uniform_set_create(uniform_set, shader, set_id) 24 | 25 | 26 | func destroy(rd: RenderingDevice) -> void: 27 | 28 | # Must free the uniform set before the uniforms themselves, else the uniform_set RID will become invalid. 29 | # Not sure if it's because it is freed when it becomes invalid, but we clean it up anyway. 30 | rd.free_rid(uniform_set_rid) 31 | 32 | for uniform in uniforms: 33 | 34 | rd.free_rid(uniform.data_rid) 35 | uniform.uniform.clear_ids() 36 | 37 | 38 | -------------------------------------------------------------------------------- /addons/compute_worker/example/test_glsl.glsl: -------------------------------------------------------------------------------- 1 | #[compute] 2 | 3 | #version 450 4 | 5 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 6 | 7 | 8 | struct Object{ 9 | dvec4 position; 10 | dvec4 velocity; 11 | double mass; 12 | int radius; 13 | double effector; 14 | }; 15 | 16 | layout(set = 0, binding = 0, std140) uniform Time{ 17 | double time; 18 | }; 19 | 20 | layout(set = 0, binding = 1, std430) buffer TestStructArray{ 21 | Object obj_arr[10]; 22 | }; 23 | 24 | layout(set = 0, binding = 2, std430) buffer TestVector{ 25 | dvec4 test_vector; 26 | }; 27 | 28 | layout(set = 0, binding = 3, std430) buffer LookupResult{ 29 | dvec4 result; 30 | }; 31 | 32 | layout(set = 0, binding = 4, std140) uniform TestInteger{ 33 | int test_int; 34 | }; 35 | 36 | layout(set = 1, binding = 0, std430) buffer TestFloat{ 37 | double test_float; 38 | }; 39 | 40 | layout(set = 1, binding = 1, std140) uniform TestFloatArr{ 41 | double[100] fl_arr; 42 | }; 43 | 44 | layout(set = 1, binding = 2, std430) buffer TestVecArr{ 45 | vec4[] vec_arr; 46 | }; 47 | 48 | layout(set = 0, binding = 5, std430) buffer TestVec2{ 49 | dvec4 test_vec; 50 | }; 51 | 52 | void main() { 53 | result.xy = test_vector.xy; 54 | result.z = test_float; 55 | result.w = time; 56 | 57 | test_vec.x += 1.0; 58 | } -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_integer.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `int` 2 | 3 | extends GPUUniform 4 | class_name GPU_Integer 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The initial data supplied to the uniform 12 | @export var data: int = 0 13 | ## The shader binding for this uniform 14 | @export var binding: int = 0 15 | ## Type of uniform to create. `UNIFORM_BUFFER`s cannot be altered from within the shader 16 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.UNIFORM_BUFFER 17 | 18 | var data_rid: RID = RID() 19 | var uniform: RDUniform = RDUniform.new() 20 | 21 | 22 | func initialize(rd: RenderingDevice) -> RDUniform: 23 | 24 | # Create the buffer using our initial data 25 | data_rid = create_rid(rd) 26 | 27 | # Create RDUniform object using the provided binding id and data 28 | return create_uniform() 29 | 30 | 31 | func create_uniform() -> RDUniform: 32 | 33 | match uniform_type: 34 | UNIFORM_TYPES.UNIFORM_BUFFER: 35 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 36 | UNIFORM_TYPES.STORAGE_BUFFER: 37 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 38 | 39 | uniform.binding = binding 40 | uniform.add_id(data_rid) 41 | 42 | return uniform 43 | 44 | 45 | func create_rid(rd: RenderingDevice) -> RID: 46 | 47 | var bytes = int_to_byte_array(data) 48 | 49 | var buffer: RID = RID() 50 | 51 | match uniform_type: 52 | UNIFORM_TYPES.UNIFORM_BUFFER: 53 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 54 | UNIFORM_TYPES.STORAGE_BUFFER: 55 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 56 | 57 | return buffer 58 | 59 | 60 | func get_uniform_data(rd: RenderingDevice) -> int: 61 | var out := rd.buffer_get_data(data_rid) 62 | return byte_array_to_int(out) 63 | 64 | 65 | func set_uniform_data(rd: RenderingDevice, num: int) -> void: 66 | var sb_data = int_to_byte_array(num) 67 | rd.buffer_update(data_rid, 0 , sb_data.size(), sb_data) 68 | 69 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_packed_byte_array.gd: -------------------------------------------------------------------------------- 1 | # Standard buffer object, can be used for custom encoding 2 | 3 | extends GPUUniform 4 | class_name GPU_PackedByteArray 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The initial data supplied to the uniform 12 | @export var data: PackedByteArray = PackedByteArray() 13 | ## The shader binding for this uniform 14 | @export var binding: int = 0 15 | ## Type of uniform to create. `UNIFORM_BUFFER`s cannot be altered from within the shader 16 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.UNIFORM_BUFFER 17 | 18 | var data_rid: RID = RID() 19 | var uniform: RDUniform = RDUniform.new() 20 | 21 | 22 | func initialize(rd: RenderingDevice) -> RDUniform: 23 | 24 | # Create the buffer using our initial data 25 | data_rid = create_rid(rd) 26 | 27 | # Create RDUniform object using the provided binding id and data 28 | return create_uniform() 29 | 30 | 31 | func create_uniform() -> RDUniform: 32 | 33 | match uniform_type: 34 | UNIFORM_TYPES.UNIFORM_BUFFER: 35 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 36 | UNIFORM_TYPES.STORAGE_BUFFER: 37 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 38 | 39 | uniform.binding = binding 40 | uniform.add_id(data_rid) 41 | 42 | return uniform 43 | 44 | 45 | func create_rid(rd: RenderingDevice) -> RID: 46 | 47 | var bytes = data 48 | 49 | var buffer: RID = RID() 50 | 51 | match uniform_type: 52 | UNIFORM_TYPES.UNIFORM_BUFFER: 53 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 54 | UNIFORM_TYPES.STORAGE_BUFFER: 55 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 56 | 57 | return buffer 58 | 59 | 60 | func get_uniform_data(rd: RenderingDevice) -> PackedByteArray: 61 | var out := rd.buffer_get_data(data_rid) 62 | return out 63 | 64 | 65 | func set_uniform_data(rd: RenderingDevice, array: PackedByteArray) -> void: 66 | rd.buffer_update(data_rid, 0 , array.size(), array) 67 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_boolean.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `bool` 2 | 3 | extends GPUUniform 4 | class_name GPU_Boolean 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The initial data supplied to the uniform 12 | @export var data: bool = false 13 | ## The shader binding for this uniform 14 | @export var binding: int = 0 15 | ## Type of uniform to create. `UNIFORM_BUFFER`s cannot be altered from within the shader 16 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.UNIFORM_BUFFER 17 | 18 | var data_rid: RID = RID() 19 | var uniform: RDUniform = RDUniform.new() 20 | 21 | 22 | func initialize(rd: RenderingDevice) -> RDUniform: 23 | 24 | # Create the buffer using our initial data 25 | data_rid = create_rid(rd) 26 | 27 | # Create RDUniform object using the provided binding id and data 28 | return create_uniform() 29 | 30 | 31 | func create_uniform() -> RDUniform: 32 | 33 | match uniform_type: 34 | UNIFORM_TYPES.UNIFORM_BUFFER: 35 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 36 | UNIFORM_TYPES.STORAGE_BUFFER: 37 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 38 | 39 | uniform.binding = binding 40 | uniform.add_id(data_rid) 41 | 42 | return uniform 43 | 44 | 45 | func create_rid(rd: RenderingDevice) -> RID: 46 | 47 | var bytes = bool_to_byte_array(data) 48 | 49 | var buffer: RID = RID() 50 | 51 | match uniform_type: 52 | UNIFORM_TYPES.UNIFORM_BUFFER: 53 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 54 | UNIFORM_TYPES.STORAGE_BUFFER: 55 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 56 | 57 | return buffer 58 | 59 | 60 | func get_uniform_data(rd: RenderingDevice) -> bool: 61 | var out := rd.buffer_get_data(data_rid) 62 | return byte_array_to_bool(out) 63 | 64 | 65 | func set_uniform_data(rd: RenderingDevice, value: bool) -> void: 66 | var sb_data = bool_to_byte_array(value) 67 | rd.buffer_update(data_rid, 0, sb_data.size(), sb_data) 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_color.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `dvec4` 2 | 3 | extends GPUUniform 4 | class_name GPU_Color 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The initial data supplied to the uniform 12 | @export var data: Color = Color() 13 | ## The shader binding for this uniform 14 | @export var binding: int = 0 15 | ## Type of uniform to create. `UNIFORM_BUFFER`s cannot be altered from within the shader 16 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.STORAGE_BUFFER 17 | 18 | var data_rid: RID = RID() 19 | var uniform: RDUniform = RDUniform.new() 20 | 21 | 22 | func initialize(rd: RenderingDevice) -> RDUniform: 23 | 24 | # Create the buffer using our initial data 25 | data_rid = create_rid(rd) 26 | 27 | # Create RDUniform object using the provided binding id and data 28 | return create_uniform() 29 | 30 | 31 | func create_uniform() -> RDUniform: 32 | 33 | match uniform_type: 34 | UNIFORM_TYPES.UNIFORM_BUFFER: 35 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 36 | UNIFORM_TYPES.STORAGE_BUFFER: 37 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 38 | 39 | uniform.binding = binding 40 | uniform.add_id(data_rid) 41 | 42 | return uniform 43 | 44 | 45 | func create_rid(rd: RenderingDevice) -> RID: 46 | 47 | var bytes = color_to_byte_array(data) 48 | var buffer: RID = RID() 49 | 50 | match uniform_type: 51 | UNIFORM_TYPES.UNIFORM_BUFFER: 52 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 53 | UNIFORM_TYPES.STORAGE_BUFFER: 54 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 55 | 56 | return buffer 57 | 58 | 59 | func get_uniform_data(rd: RenderingDevice) -> Color: 60 | var out := rd.buffer_get_data(data_rid) 61 | return byte_array_to_color(out) 62 | 63 | 64 | func set_uniform_data(rd: RenderingDevice, color: Color) -> void: 65 | var sb_data = color_to_byte_array(color) 66 | rd.buffer_update(data_rid, 0 , sb_data.size(), sb_data) 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_float.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `double`, `float` 2 | 3 | extends GPUUniform 4 | class_name GPU_Float 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The initial data supplied to the uniform 12 | @export var data: float = 0.0 13 | ## The shader binding for this uniform 14 | @export var binding: int = 0 15 | ## Type of uniform to create. `UNIFORM_BUFFER`s cannot be altered from within the shader 16 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.UNIFORM_BUFFER 17 | 18 | var data_rid: RID = RID() 19 | var uniform: RDUniform = RDUniform.new() 20 | 21 | 22 | func initialize(rd: RenderingDevice) -> RDUniform: 23 | 24 | # Create the buffer using our initial data 25 | data_rid = create_rid(rd) 26 | 27 | # Create RDUniform object using the provided binding id and data 28 | return create_uniform() 29 | 30 | 31 | func create_uniform() -> RDUniform: 32 | 33 | match uniform_type: 34 | UNIFORM_TYPES.UNIFORM_BUFFER: 35 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 36 | UNIFORM_TYPES.STORAGE_BUFFER: 37 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 38 | 39 | uniform.binding = binding 40 | uniform.add_id(data_rid) 41 | 42 | return uniform 43 | 44 | 45 | func create_rid(rd: RenderingDevice) -> RID: 46 | 47 | var bytes = float_to_byte_array(data) 48 | 49 | var buffer: RID = RID() 50 | 51 | match uniform_type: 52 | UNIFORM_TYPES.UNIFORM_BUFFER: 53 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 54 | UNIFORM_TYPES.STORAGE_BUFFER: 55 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 56 | 57 | return buffer 58 | 59 | 60 | func get_uniform_data(rd: RenderingDevice) -> float: 61 | var out := rd.buffer_get_data(data_rid) 62 | return byte_array_to_float(out) 63 | 64 | 65 | func set_uniform_data(rd: RenderingDevice, num: float) -> void: 66 | var sb_data = float_to_byte_array(num) 67 | rd.buffer_update(data_rid, 0 , sb_data.size(), sb_data) 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_vector4.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `dvec3`, `dvec4` 2 | 3 | extends GPUUniform 4 | class_name GPU_Vector4 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The initial data supplied to the uniform 12 | @export var data: Vector4 = Vector4() 13 | ## The shader binding for this uniform 14 | @export var binding: int = 0 15 | ## Type of uniform to create. `UNIFORM_BUFFER`s cannot be altered from within the shader 16 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.UNIFORM_BUFFER 17 | 18 | var data_rid: RID = RID() 19 | var uniform: RDUniform = RDUniform.new() 20 | 21 | 22 | func initialize(rd: RenderingDevice) -> RDUniform: 23 | 24 | # Create the buffer using our initial data 25 | data_rid = create_rid(rd) 26 | 27 | # Create RDUniform object using the provided binding id and data 28 | return create_uniform() 29 | 30 | 31 | func create_uniform() -> RDUniform: 32 | 33 | match uniform_type: 34 | UNIFORM_TYPES.UNIFORM_BUFFER: 35 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 36 | UNIFORM_TYPES.STORAGE_BUFFER: 37 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 38 | 39 | uniform.binding = binding 40 | uniform.add_id(data_rid) 41 | 42 | return uniform 43 | 44 | 45 | func create_rid(rd: RenderingDevice) -> RID: 46 | 47 | var bytes = vec4_to_byte_array(data) 48 | 49 | var buffer: RID = RID() 50 | 51 | match uniform_type: 52 | UNIFORM_TYPES.UNIFORM_BUFFER: 53 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 54 | UNIFORM_TYPES.STORAGE_BUFFER: 55 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 56 | 57 | return buffer 58 | 59 | 60 | func get_uniform_data(rd: RenderingDevice) -> Vector4: 61 | var out := rd.buffer_get_data(data_rid) 62 | return byte_array_to_vec4(out) 63 | 64 | 65 | func set_uniform_data(rd: RenderingDevice, vector: Vector4) -> void: 66 | var sb_data = vec4_to_byte_array(vector) 67 | rd.buffer_update(data_rid, 0 , sb_data.size(), sb_data) 68 | 69 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_vector3.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `dvec3`, `dvec4` 2 | 3 | extends GPUUniform 4 | class_name GPU_Vector3 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The initial data supplied to the uniform 12 | @export var data: Vector3 = Vector3() 13 | ## The shader binding for this uniform 14 | @export var binding: int = 0 15 | ## Type of uniform to create. `UNIFORM_BUFFER`s cannot be altered from within the shader 16 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.UNIFORM_BUFFER 17 | 18 | var data_rid: RID = RID() 19 | var uniform: RDUniform = RDUniform.new() 20 | 21 | 22 | func initialize(rd: RenderingDevice) -> RDUniform: 23 | 24 | # Create the buffer using our initial data 25 | data_rid = create_rid(rd) 26 | 27 | # Create RDUniform object using the provided binding id and data 28 | return create_uniform() 29 | 30 | 31 | func create_uniform() -> RDUniform: 32 | 33 | match uniform_type: 34 | UNIFORM_TYPES.UNIFORM_BUFFER: 35 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 36 | UNIFORM_TYPES.STORAGE_BUFFER: 37 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 38 | 39 | uniform.binding = binding 40 | uniform.add_id(data_rid) 41 | 42 | return uniform 43 | 44 | 45 | func create_rid(rd: RenderingDevice) -> RID: 46 | 47 | var bytes = vec3_to_byte_array(data) 48 | 49 | var buffer: RID = RID() 50 | 51 | match uniform_type: 52 | UNIFORM_TYPES.UNIFORM_BUFFER: 53 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 54 | UNIFORM_TYPES.STORAGE_BUFFER: 55 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 56 | 57 | return buffer 58 | 59 | 60 | func get_uniform_data(rd: RenderingDevice) -> Vector3: 61 | var out := rd.buffer_get_data(data_rid) 62 | return byte_array_to_vec3(out) 63 | 64 | 65 | func set_uniform_data(rd: RenderingDevice, vector: Vector3) -> void: 66 | var sb_data = vec3_to_byte_array(vector) 67 | rd.buffer_update(data_rid, 0 , sb_data.size(), sb_data) 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_vector3i.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `ivec3`, `ivec4` 2 | 3 | extends GPUUniform 4 | class_name GPU_Vector3i 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The initial data supplied to the uniform 12 | @export var data: Vector3i = Vector3i() 13 | ## The shader binding for this uniform 14 | @export var binding: int = 0 15 | ## Type of uniform to create. `UNIFORM_BUFFER`s cannot be altered from within the shader 16 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.UNIFORM_BUFFER 17 | 18 | var data_rid: RID = RID() 19 | var uniform: RDUniform = RDUniform.new() 20 | 21 | 22 | func initialize(rd: RenderingDevice) -> RDUniform: 23 | 24 | # Create the buffer using our initial data 25 | data_rid = create_rid(rd) 26 | 27 | # Create RDUniform object using the provided binding id and data 28 | return create_uniform() 29 | 30 | 31 | func create_uniform() -> RDUniform: 32 | 33 | match uniform_type: 34 | UNIFORM_TYPES.UNIFORM_BUFFER: 35 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 36 | UNIFORM_TYPES.STORAGE_BUFFER: 37 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 38 | 39 | uniform.binding = binding 40 | uniform.add_id(data_rid) 41 | 42 | return uniform 43 | 44 | 45 | func create_rid(rd: RenderingDevice) -> RID: 46 | 47 | var bytes = vec3i_to_byte_array(data) 48 | 49 | var buffer: RID = RID() 50 | 51 | match uniform_type: 52 | UNIFORM_TYPES.UNIFORM_BUFFER: 53 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 54 | UNIFORM_TYPES.STORAGE_BUFFER: 55 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 56 | 57 | return buffer 58 | 59 | 60 | func get_uniform_data(rd: RenderingDevice) -> Vector3: 61 | var out := rd.buffer_get_data(data_rid) 62 | return byte_array_to_vec3(out) 63 | 64 | 65 | func set_uniform_data(rd: RenderingDevice, vector: Vector3i) -> void: 66 | var sb_data = vec3i_to_byte_array(vector) 67 | rd.buffer_update(data_rid, 0 , sb_data.size(), sb_data) 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_vector2.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `dvec2` 2 | 3 | extends GPUUniform 4 | class_name GPU_Vector2 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The initial data supplied to the uniform 12 | @export var data: Vector2 = Vector2() 13 | ## The shader binding for this uniform 14 | @export var binding: int = 0 15 | ## Type of uniform to create. `UNIFORM_BUFFER`s cannot be altered from within the shader 16 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.UNIFORM_BUFFER 17 | 18 | var data_rid: RID = RID() 19 | var uniform: RDUniform = RDUniform.new() 20 | 21 | 22 | func initialize(rd: RenderingDevice) -> RDUniform: 23 | 24 | # Create the buffer using our initial data 25 | data_rid = create_rid(rd) 26 | 27 | # Create RDUniform object using the provided binding id and data 28 | return create_uniform() 29 | 30 | 31 | func create_uniform() -> RDUniform: 32 | 33 | match uniform_type: 34 | UNIFORM_TYPES.UNIFORM_BUFFER: 35 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 36 | UNIFORM_TYPES.STORAGE_BUFFER: 37 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 38 | 39 | uniform.binding = binding 40 | uniform.add_id(data_rid) 41 | 42 | return uniform 43 | 44 | 45 | func create_rid(rd: RenderingDevice) -> RID: 46 | 47 | var bytes = vec3_to_byte_array(Vector3(data.x, data.y, 0.0)) 48 | 49 | var buffer: RID = RID() 50 | 51 | match uniform_type: 52 | UNIFORM_TYPES.UNIFORM_BUFFER: 53 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 54 | UNIFORM_TYPES.STORAGE_BUFFER: 55 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 56 | 57 | return buffer 58 | 59 | 60 | func get_uniform_data(rd: RenderingDevice) -> Vector2: 61 | var out := rd.buffer_get_data(data_rid) 62 | return byte_array_to_vec2(out) 63 | 64 | 65 | func set_uniform_data(rd: RenderingDevice, vector: Vector2) -> void: 66 | var sb_data = vec2_to_byte_array(vector) 67 | rd.buffer_update(data_rid, 0 , sb_data.size(), sb_data) 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /addons/compute_worker/example/example_uniform_set.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="UniformSet" load_steps=12 format=3 uid="uid://bnnlrvnl455uy"] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/uniform_sets/uniform_set.gd" id="1_x4fkk"] 4 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_float.gd" id="2_53uf0"] 5 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_struct_array.gd" id="3_hq3h4"] 6 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_vector3.gd" id="4_bku60"] 7 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_color.gd" id="5_7nelv"] 8 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_integer.gd" id="6_prb52"] 9 | 10 | [sub_resource type="Resource" id="Resource_ntob8"] 11 | script = ExtResource("2_53uf0") 12 | data = 0.0 13 | binding = 0 14 | uniform_type = 1 15 | alias = "time" 16 | 17 | [sub_resource type="Resource" id="Resource_n5517"] 18 | script = ExtResource("3_hq3h4") 19 | array_size = 10 20 | struct_data = [Vector3(0, 0, 0), Vector3(0, 0, 0), 0.0, 0, 0.0] 21 | binding = 1 22 | uniform_type = 1 23 | alias = "obj_arr" 24 | 25 | [sub_resource type="Resource" id="Resource_3jhqj"] 26 | script = ExtResource("4_bku60") 27 | data = Vector3(0, 0, 0) 28 | binding = 2 29 | uniform_type = 1 30 | alias = "test_vector" 31 | 32 | [sub_resource type="Resource" id="Resource_4orwy"] 33 | script = ExtResource("5_7nelv") 34 | data = Color(0, 0, 0, 1) 35 | binding = 3 36 | uniform_type = 1 37 | alias = "result" 38 | 39 | [sub_resource type="Resource" id="Resource_civi2"] 40 | script = ExtResource("6_prb52") 41 | data = 0 42 | binding = 4 43 | uniform_type = 1 44 | alias = "test_int" 45 | 46 | [resource] 47 | script = ExtResource("1_x4fkk") 48 | uniforms = Array[Resource("res://addons/compute_worker/GPUUniforms/GPUUniform.gd")]([SubResource("Resource_ntob8"), SubResource("Resource_n5517"), SubResource("Resource_3jhqj"), SubResource("Resource_4orwy"), SubResource("Resource_civi2")]) 49 | set_id = 0 50 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_struct_array.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `struct[]` 2 | 3 | extends GPU_Struct 4 | class_name GPU_StructArray 5 | 6 | ## The size of the Struct array defined in the shader. 7 | @export var array_size: int = 1 8 | 9 | 10 | func initialize(rd: RenderingDevice) -> RDUniform: 11 | 12 | var arr: PackedByteArray = PackedByteArray() 13 | 14 | for i in range(array_size): 15 | var by = encode_struct(struct_data.duplicate()) 16 | arr.append_array(by) 17 | 18 | bytes = arr 19 | 20 | @warning_ignore("integer_division") 21 | byte_length = arr.size() / array_size 22 | 23 | data_rid = create_rid(rd) 24 | return create_uniform() 25 | 26 | func create_uniform() -> RDUniform: 27 | 28 | match uniform_type: 29 | UNIFORM_TYPES.UNIFORM_BUFFER: 30 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 31 | UNIFORM_TYPES.STORAGE_BUFFER: 32 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 33 | 34 | uniform.binding = binding 35 | uniform.add_id(data_rid) 36 | 37 | return uniform 38 | 39 | 40 | func create_rid(rd: RenderingDevice) -> RID: 41 | 42 | var buffer: RID = RID() 43 | 44 | match uniform_type: 45 | UNIFORM_TYPES.UNIFORM_BUFFER: 46 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 47 | UNIFORM_TYPES.STORAGE_BUFFER: 48 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 49 | 50 | return buffer 51 | 52 | 53 | func get_uniform_data(rd: RenderingDevice) -> Array[Array]: 54 | 55 | var out := rd.buffer_get_data(data_rid) 56 | 57 | var arr: Array = [] 58 | 59 | @warning_ignore("integer_division") 60 | var num_arr_elements = out.size() / byte_length 61 | 62 | for i in range(num_arr_elements): 63 | 64 | var i_bytes = out.slice(i * byte_length, (i * byte_length) + byte_length) 65 | var st = decode_struct(i_bytes) 66 | arr.push_back(st) 67 | 68 | return arr 69 | 70 | 71 | func set_uniform_data(rd: RenderingDevice, data: Array[Array]) -> void: 72 | 73 | var i_bytes: PackedByteArray = PackedByteArray() 74 | 75 | for i in range(data.size()): 76 | var by = encode_struct(data[i], true) 77 | i_bytes.append_array(by) 78 | 79 | rd.buffer_update(data_rid, 0 , i_bytes.size(), i_bytes) 80 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_packed_vector3_array.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `vec4[]`, `vec3[]` 2 | 3 | extends GPUUniform 4 | class_name GPU_PackedVector3Array 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The initial data supplied to the uniform 12 | @export var data: PackedVector3Array = PackedVector3Array() 13 | ## The size of the array as defined in the shader. Only used if `data` is not defined. 14 | @export var array_size: int = 0 15 | ## The shader binding for this uniform 16 | @export var binding: int = 0 17 | ## Type of uniform to create. `UNIFORM_BUFFER`s cannot be altered from within the shader 18 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.UNIFORM_BUFFER 19 | 20 | var data_rid: RID = RID() 21 | var uniform: RDUniform = RDUniform.new() 22 | 23 | 24 | func initialize(rd: RenderingDevice) -> RDUniform: 25 | 26 | if data.is_empty(): 27 | 28 | assert(array_size > 0, "You must define the uniform's `data` or `array_size`.") 29 | 30 | if array_size > 0: 31 | data.resize(array_size) 32 | 33 | # Create the buffer using our initial data 34 | data_rid = create_rid(rd) 35 | 36 | # Create RDUniform object using the provided binding id and data 37 | return create_uniform() 38 | 39 | 40 | func create_uniform() -> RDUniform: 41 | 42 | match uniform_type: 43 | UNIFORM_TYPES.UNIFORM_BUFFER: 44 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 45 | UNIFORM_TYPES.STORAGE_BUFFER: 46 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 47 | 48 | uniform.binding = binding 49 | uniform.add_id(data_rid) 50 | 51 | return uniform 52 | 53 | 54 | func create_rid(rd: RenderingDevice) -> RID: 55 | 56 | var bytes = vec3_array_to_byte_array(data) 57 | 58 | var buffer: RID = RID() 59 | 60 | match uniform_type: 61 | UNIFORM_TYPES.UNIFORM_BUFFER: 62 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 63 | UNIFORM_TYPES.STORAGE_BUFFER: 64 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 65 | 66 | return buffer 67 | 68 | 69 | func get_uniform_data(rd: RenderingDevice) -> PackedVector3Array: 70 | var out := rd.buffer_get_data(data_rid) 71 | return byte_array_to_vec3_array(out) 72 | 73 | 74 | func set_uniform_data(rd: RenderingDevice, array: PackedVector3Array) -> void: 75 | var sb_data = vec3_array_to_byte_array(array) 76 | rd.buffer_update(data_rid, 0 , sb_data.size(), sb_data) 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_image.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `image2D` 2 | 3 | extends GPUUniform 4 | class_name GPU_Image 5 | 6 | ## The initial data supplied to the uniform 7 | @export var data: Image = Image.new() 8 | ## The image dimensions to initialize the uniform with 9 | @export var image_size: Vector2i = Vector2i(1,1) 10 | ## The shader binding for this uniform 11 | @export var binding: int = 0 12 | ## RenderingDevice DATA_FORMAT enum values only 13 | @export var image_format: int = RenderingDevice.DATA_FORMAT_R32G32B32A32_SFLOAT 14 | 15 | 16 | var data_rid: RID = RID() 17 | var uniform: RDUniform = RDUniform.new() 18 | 19 | var texture_type = RenderingDevice.TEXTURE_TYPE_2D 20 | var uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE 21 | 22 | 23 | func initialize(rd: RenderingDevice) -> RDUniform: 24 | 25 | # Generate the initial Image using the provided `image_size` 26 | data.create(image_size.x, image_size.y, false, Image.FORMAT_RGBAF) 27 | 28 | # Create the texture using our initial data 29 | data_rid = create_rid(rd) 30 | 31 | # Create RDUniform object using the provided binding id and data 32 | return create_uniform() 33 | 34 | 35 | func create_rid(rd: RenderingDevice) -> RID: 36 | 37 | var texture_format = RDTextureFormat.new() 38 | 39 | texture_format.texture_type = texture_type 40 | texture_format.format = image_format 41 | 42 | texture_format.width = data.get_width() 43 | texture_format.height = data.get_height() 44 | 45 | texture_format.usage_bits = RenderingDevice.TEXTURE_USAGE_STORAGE_BIT | RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT | RenderingDevice.TEXTURE_USAGE_CAN_UPDATE_BIT | RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT 46 | 47 | var image_data: PackedByteArray = data.get_data() 48 | 49 | var tex = rd.texture_create(texture_format, RDTextureView.new(), [image_data]) 50 | 51 | return tex 52 | 53 | 54 | func create_uniform() -> RDUniform: 55 | 56 | uniform.uniform_type = uniform_type 57 | uniform.binding = binding 58 | uniform.add_id(data_rid) 59 | 60 | return uniform 61 | 62 | 63 | func get_uniform_data(rd: RenderingDevice) -> Image: 64 | 65 | var t_data = rd.texture_get_data(data_rid, 0) 66 | var image = Image.new() 67 | image.create_from_data(data.get_width(), data.get_height(), false, Image.FORMAT_RGBAF, t_data) 68 | 69 | return image 70 | 71 | 72 | func set_uniform_data(rd: RenderingDevice, image: Image) -> void: 73 | 74 | var layer_data = image.get_data() 75 | rd.texture_update(data_rid, 0, layer_data) 76 | 77 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_packed_float64_array.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `double[]` 2 | 3 | extends GPUUniform 4 | class_name GPU_PackedFloat64Array 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The initial data supplied to the uniform 12 | @export var data: PackedFloat64Array = PackedFloat64Array() 13 | ## The size of the array as defined in the shader. Only used if `data` is not defined. 14 | @export var array_size: int = 0 15 | ## The shader binding for this uniform 16 | @export var binding: int = 0 17 | ## Type of uniform to create. `UNIFORM_BUFFER`s cannot be altered from within the shader 18 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.UNIFORM_BUFFER 19 | 20 | var data_rid: RID = RID() 21 | var uniform: RDUniform = RDUniform.new() 22 | 23 | 24 | func initialize(rd: RenderingDevice) -> RDUniform: 25 | 26 | if data.is_empty(): 27 | if array_size > 0: 28 | data.resize(array_size) 29 | else: 30 | printerr("You must define the uniform's `data` or `array_size`.") 31 | return 32 | 33 | # Create the buffer using our initial data 34 | data_rid = create_rid(rd) 35 | 36 | # Create RDUniform object using the provided binding id and data 37 | return create_uniform() 38 | 39 | 40 | func create_uniform() -> RDUniform: 41 | 42 | match uniform_type: 43 | UNIFORM_TYPES.UNIFORM_BUFFER: 44 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 45 | UNIFORM_TYPES.STORAGE_BUFFER: 46 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 47 | 48 | uniform.binding = binding 49 | uniform.add_id(data_rid) 50 | 51 | return uniform 52 | 53 | 54 | func create_rid(rd: RenderingDevice) -> RID: 55 | 56 | var bytes = data.to_byte_array() 57 | 58 | var buffer: RID = RID() 59 | 60 | match uniform_type: 61 | UNIFORM_TYPES.UNIFORM_BUFFER: 62 | bytes = pad_byte_array_std140(bytes) 63 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 64 | UNIFORM_TYPES.STORAGE_BUFFER: 65 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 66 | 67 | return buffer 68 | 69 | 70 | func get_uniform_data(rd: RenderingDevice) -> PackedFloat64Array: 71 | var out := rd.buffer_get_data(data_rid) 72 | return out.to_float64_array() 73 | 74 | 75 | func set_uniform_data(rd: RenderingDevice, array: PackedFloat64Array) -> void: 76 | var sb_data = array.to_byte_array() 77 | rd.buffer_update(data_rid, 0 , sb_data.size(), sb_data) 78 | 79 | 80 | func pad_byte_array_std140(arr: PackedByteArray) -> PackedByteArray: 81 | 82 | arr.resize(arr.size() * 2) 83 | var next_offset = 0 84 | 85 | for i in range(arr.size()): 86 | if next_offset + 8 > arr.size(): 87 | break 88 | arr.encode_double(next_offset + 8, 0.0) 89 | next_offset += 16 90 | 91 | return arr 92 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_texture_2d_array.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `image2DArray` 2 | 3 | extends GPUUniform 4 | class_name GPU_Texture2DArray 5 | 6 | ## The initial data supplied to the uniform 7 | @export var data: Texture2DArray = Texture2DArray.new() 8 | ## The dimensions to initialize the texture array with 9 | @export var texture_array_size: Vector3i = Vector3i(1,1,1) 10 | ## The shader binding for this uniform 11 | @export var binding: int = 0 12 | ## Image.FORMAT_* enum values only 13 | @export var image_format: int = Image.FORMAT_RGBAF 14 | 15 | var raw_data: Array[PackedByteArray] = [] 16 | 17 | var data_rid: RID = RID() 18 | var uniform: RDUniform = RDUniform.new() 19 | 20 | var uniform_texture_format = RenderingDevice.DATA_FORMAT_R32G32B32A32_SFLOAT 21 | var texture_type = RenderingDevice.TEXTURE_TYPE_2D_ARRAY 22 | var uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE 23 | 24 | 25 | func initialize(rd: RenderingDevice) -> RDUniform: 26 | 27 | # Generate the initial Texture2DArray using the provided `texture_array_size` 28 | var images = [] 29 | for layer in texture_array_size.z: 30 | 31 | var image = Image.new() 32 | 33 | var empty = PackedByteArray() 34 | empty.resize(16 * texture_array_size.x * texture_array_size.y) 35 | 36 | image.set_data(texture_array_size.x, texture_array_size.y, false, Image.FORMAT_RGBAF, empty) 37 | images.push_back(image) 38 | 39 | data.create_from_images(images) 40 | 41 | # Create the texture using our initial data 42 | data_rid = create_rid(rd) 43 | 44 | # Create RDUniform object using the provided binding id and data 45 | return create_uniform() 46 | 47 | 48 | func create_rid(rd: RenderingDevice) -> RID: 49 | 50 | var texture_format = RDTextureFormat.new() 51 | 52 | texture_format.texture_type = texture_type 53 | texture_format.format = uniform_texture_format 54 | 55 | texture_format.width = data.get_width() 56 | texture_format.height = data.get_height() 57 | texture_format.array_layers = data.get_layers() 58 | 59 | texture_format.usage_bits = RenderingDevice.TEXTURE_USAGE_STORAGE_BIT | RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT | RenderingDevice.TEXTURE_USAGE_CAN_UPDATE_BIT | RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT 60 | 61 | var images = [] 62 | for layer in range(data.get_layers()): 63 | images.push_back(data.get_layer_data(layer).get_data()) 64 | 65 | 66 | var tex = rd.texture_create(texture_format, RDTextureView.new(), images) 67 | 68 | return tex 69 | 70 | 71 | func create_uniform() -> RDUniform: 72 | 73 | uniform.uniform_type = uniform_type 74 | uniform.binding = binding 75 | uniform.add_id(data_rid) 76 | 77 | return uniform 78 | 79 | 80 | func get_uniform_data(rd: RenderingDevice) -> Texture2DArray: 81 | 82 | var images = [] 83 | 84 | for layer in range(data.get_layers()): 85 | 86 | var t_data = rd.texture_get_data(data_rid, layer) 87 | var image = Image.create_from_data(data.get_width(), data.get_height(), false, image_format, t_data) 88 | images.push_back(image) 89 | 90 | var tex_arr = Texture2DArray.new() 91 | tex_arr.create_from_images(images) 92 | 93 | return tex_arr 94 | 95 | 96 | func set_uniform_data(rd: RenderingDevice, image: Texture2DArray) -> void: 97 | 98 | var images = [] 99 | for layer in range(image.get_layers()): 100 | 101 | var layer_data = image.get_layer_data(layer).get_data() 102 | images.push_back(layer_data) 103 | rd.texture_update(data_rid, layer, layer_data) 104 | 105 | -------------------------------------------------------------------------------- /addons/compute_worker/example/compute_example.gd: -------------------------------------------------------------------------------- 1 | extends Node3D 2 | 3 | # This simple example demonstrates setting intial uniform data, 4 | # and the setting and getting of uniform data, including Structs. 5 | 6 | @export var test_vector: Vector3 = Vector3(0, 0, 0) 7 | var test_shader_file = preload("res://addons/compute_worker/example/test_glsl.glsl") 8 | 9 | 10 | func _ready(): 11 | 12 | # Example of setting uniform data before calling `initialize()` 13 | var test_vector_uniform: GPU_Vector3 = $ComputeWorker.get_uniform_by_alias("test_vector") 14 | test_vector_uniform.data = test_vector 15 | 16 | 17 | # The float array is defined as a uniform buffer in our shader, 18 | # and thus can't be dynamically sized. So it's good practice to 19 | # use the `array_size` value from the Uniform object that was set in the editor. 20 | var float_arr: PackedFloat64Array = PackedFloat64Array() 21 | var float_arr_uniform: GPU_PackedFloat64Array = $ComputeWorker.get_uniform_by_alias("fl_arr", 1) 22 | 23 | float_arr.resize(float_arr_uniform.array_size) 24 | float_arr_uniform.data = float_arr 25 | 26 | 27 | # The vector array is defined as a storage buffer, 28 | # and thus is dynamically sized (because it's last in the storage block). 29 | # We can pass in whatever size array we want here. 30 | var vec_arr: PackedVector3Array = PackedVector3Array() 31 | vec_arr.resize(200) 32 | 33 | var vec_arr_uniform: GPU_PackedVector3Array = $ComputeWorker.get_uniform_by_alias("vec_arr", 1) 34 | vec_arr_uniform.data = vec_arr 35 | 36 | 37 | $ComputeWorker.initialize() 38 | 39 | 40 | func _process(delta): 41 | 42 | var dispatch = false 43 | 44 | # An example of how to restart the ComputeWorker with a new shader. 45 | if Input.is_key_pressed(KEY_SPACE): 46 | 47 | $ComputeWorker.destroy() 48 | $ComputeWorker.shader_file = test_shader_file 49 | $ComputeWorker.initialize() 50 | 51 | 52 | if $ComputeWorker.initialized: 53 | 54 | # Here we add `delta` to the time uniform's current data to get an accumulated time inside the shader. 55 | var gpu_time: float = $ComputeWorker.get_uniform_data_by_alias("time") 56 | $ComputeWorker.set_uniform_data_by_alias(gpu_time + delta, "time", 0, dispatch) 57 | 58 | 59 | # Grab a list of struct objects matching the struct's format, and pass it into the shader. 60 | var obj_arr: Array[Array] = get_obj_array() 61 | $ComputeWorker.set_uniform_data_by_alias(obj_arr, "obj_arr", 0, dispatch) 62 | 63 | 64 | # Note that we didn't dispatch the shader until this point. This is for multiple reasons: 65 | # 1. We don't want to wait for the shader to execute multiple times in a single frame. 66 | # 2. We want to make sure the shader has all the data necessary for computation before executing. 67 | dispatch = true 68 | 69 | # Assign a random value to `test_float` in set 1, and dispatch. 70 | var rand_float: float = randf() * 100 71 | $ComputeWorker.set_uniform_data_by_alias(rand_float, "test_float", 1, dispatch) 72 | 73 | # Poll the result of the shader execution. (result == Color(test_vector.xy, test_float, time)) 74 | var result: Color = $ComputeWorker.get_uniform_data_by_alias("result") 75 | print(result) 76 | 77 | 78 | # Generates a list of struct objects to pass into the shader. 79 | # The array must be the same length as defined in the uniform. 80 | func get_obj_array() -> Array[Array]: 81 | 82 | # Here we get the StructArray uniform and grab its `struct_data` 83 | # to use as a template for our array elements. 84 | var uniform: GPU_StructArray = $ComputeWorker.get_uniform_by_alias("obj_arr") 85 | var structure: Array = uniform.struct_data 86 | 87 | var obj_arr: Array[Array] = [] 88 | 89 | for i in range(uniform.array_size): 90 | 91 | var struct: Array = structure.duplicate() 92 | obj_arr.push_back(struct) 93 | 94 | return obj_arr 95 | -------------------------------------------------------------------------------- /addons/compute_worker/example/compute_example.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=22 format=3 uid="uid://lq0tmmd28v6m"] 2 | 3 | [ext_resource type="Script" path="res://addons/compute_worker/example/compute_example.gd" id="1_gwibe"] 4 | [ext_resource type="Script" path="res://addons/compute_worker/compute_worker.gd" id="2_gcuhr"] 5 | [ext_resource type="RDShaderFile" uid="uid://c5mtrei2xsp1w" path="res://addons/compute_worker/example/test_glsl.glsl" id="3_jfdic"] 6 | [ext_resource type="Script" path="res://addons/compute_worker/uniform_sets/uniform_set.gd" id="4_em563"] 7 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_float.gd" id="5_yan8m"] 8 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_struct_array.gd" id="6_fog47"] 9 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_vector3.gd" id="7_g7edq"] 10 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_color.gd" id="8_w6a5r"] 11 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_integer.gd" id="9_vk2pb"] 12 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_packed_float64_array.gd" id="10_sttq2"] 13 | [ext_resource type="Script" path="res://addons/compute_worker/gpu_uniforms/gpu_packed_vector3_array.gd" id="11_bchfq"] 14 | 15 | [sub_resource type="Resource" id="Resource_ntob8"] 16 | script = ExtResource("5_yan8m") 17 | data = 0.0 18 | binding = 0 19 | uniform_type = 0 20 | alias = "time" 21 | 22 | [sub_resource type="Resource" id="Resource_n5517"] 23 | script = ExtResource("6_fog47") 24 | array_size = 10 25 | struct_data = [Vector3(0, 0, 0), Vector3(0, 0, 0), 0.0, 0, 0.0] 26 | binding = 1 27 | uniform_type = 1 28 | alias = "obj_arr" 29 | 30 | [sub_resource type="Resource" id="Resource_3jhqj"] 31 | script = ExtResource("7_g7edq") 32 | data = Vector3(0, 0, 0) 33 | binding = 2 34 | uniform_type = 1 35 | alias = "test_vector" 36 | 37 | [sub_resource type="Resource" id="Resource_4orwy"] 38 | script = ExtResource("8_w6a5r") 39 | data = Color(0, 0, 0, 1) 40 | binding = 3 41 | uniform_type = 1 42 | alias = "result" 43 | 44 | [sub_resource type="Resource" id="Resource_civi2"] 45 | script = ExtResource("9_vk2pb") 46 | data = 0 47 | binding = 4 48 | uniform_type = 0 49 | alias = "test_int" 50 | 51 | [sub_resource type="Resource" id="Resource_x6x0r"] 52 | script = ExtResource("4_em563") 53 | uniforms = Array[Resource("res://addons/compute_worker/gpu_uniforms/gpu_uniform.gd")]([SubResource("Resource_ntob8"), SubResource("Resource_n5517"), SubResource("Resource_3jhqj"), SubResource("Resource_4orwy"), SubResource("Resource_civi2")]) 54 | set_id = 0 55 | 56 | [sub_resource type="Resource" id="Resource_213ay"] 57 | script = ExtResource("5_yan8m") 58 | data = 10.0 59 | binding = 0 60 | uniform_type = 1 61 | alias = "test_float" 62 | 63 | [sub_resource type="Resource" id="Resource_kq8sp"] 64 | script = ExtResource("10_sttq2") 65 | data = null 66 | array_size = 100 67 | binding = 1 68 | uniform_type = 0 69 | alias = "fl_arr" 70 | 71 | [sub_resource type="Resource" id="Resource_seqiu"] 72 | script = ExtResource("11_bchfq") 73 | data = null 74 | array_size = 100 75 | binding = 2 76 | uniform_type = 1 77 | alias = "vec_arr" 78 | 79 | [sub_resource type="Resource" id="Resource_fxcho"] 80 | script = ExtResource("4_em563") 81 | uniforms = Array[Resource("res://addons/compute_worker/gpu_uniforms/gpu_uniform.gd")]([SubResource("Resource_213ay"), SubResource("Resource_kq8sp"), SubResource("Resource_seqiu")]) 82 | set_id = 1 83 | 84 | [node name="ComputeExample" type="Node3D"] 85 | script = ExtResource("1_gwibe") 86 | test_vector = Vector3(2.02, 3, 300) 87 | 88 | [node name="ComputeWorker" type="Node" parent="."] 89 | script = ExtResource("2_gcuhr") 90 | shader_file = ExtResource("3_jfdic") 91 | uniform_sets = Array[ExtResource("4_em563")]([SubResource("Resource_x6x0r"), SubResource("Resource_fxcho")]) 92 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_struct.gd: -------------------------------------------------------------------------------- 1 | # GLSL data type encoding: `struct` 2 | 3 | extends GPUUniform 4 | class_name GPU_Struct 5 | 6 | enum UNIFORM_TYPES{ 7 | UNIFORM_BUFFER, 8 | STORAGE_BUFFER 9 | } 10 | 11 | ## The structure of the Struct defined inside the shader. 12 | ## Add data types to the array that correspond to the data types defined in the shader, in the same order. 13 | @export var struct_data: Array = [] 14 | @export var binding: int = 0 15 | @export var uniform_type: UNIFORM_TYPES = UNIFORM_TYPES.STORAGE_BUFFER 16 | 17 | var uniform: RDUniform = RDUniform.new() 18 | var data_rid: RID = RID() 19 | 20 | var bytes: PackedByteArray = PackedByteArray() 21 | var byte_length: int = 0 22 | 23 | 24 | func initialize(rd: RenderingDevice) -> RDUniform: 25 | 26 | bytes = encode_struct(struct_data, true) 27 | byte_length = bytes.size() 28 | 29 | data_rid = create_rid(rd) 30 | return create_uniform() 31 | 32 | func create_uniform() -> RDUniform: 33 | 34 | match uniform_type: 35 | UNIFORM_TYPES.UNIFORM_BUFFER: 36 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER 37 | UNIFORM_TYPES.STORAGE_BUFFER: 38 | uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER 39 | 40 | uniform.binding = binding 41 | uniform.add_id(data_rid) 42 | 43 | return uniform 44 | 45 | 46 | func create_rid(rd: RenderingDevice) -> RID: 47 | 48 | var buffer: RID = RID() 49 | 50 | match uniform_type: 51 | UNIFORM_TYPES.UNIFORM_BUFFER: 52 | buffer = rd.uniform_buffer_create(bytes.size(), bytes) 53 | UNIFORM_TYPES.STORAGE_BUFFER: 54 | buffer = rd.storage_buffer_create(bytes.size(), bytes) 55 | 56 | return buffer 57 | 58 | 59 | func get_uniform_data(rd: RenderingDevice): 60 | var out := rd.buffer_get_data(data_rid) 61 | return decode_struct(out) 62 | 63 | 64 | 65 | 66 | func set_uniform_data(rd: RenderingDevice, data: Array) -> void: 67 | var sb_data = encode_struct(data) 68 | rd.buffer_update(data_rid, 0 , sb_data.size(), sb_data) 69 | 70 | 71 | ## Encode the contents of the passed in `data` Array to PackedByteArray. 72 | ## Contents of `data` must match the order and data types defined in `struct_data`. 73 | func encode_struct(data: Array, init: bool = false) -> PackedByteArray: 74 | 75 | var arr: PackedByteArray = PackedByteArray() 76 | var data_index = 0 77 | 78 | for type_obj in struct_data: 79 | 80 | match typeof(type_obj): 81 | TYPE_VECTOR3I: 82 | arr.append_array(vec3i_to_byte_array(data[data_index])) 83 | TYPE_COLOR: 84 | arr.append_array(color_to_byte_array(data[data_index])) 85 | TYPE_VECTOR3: 86 | arr.append_array(vec3_to_byte_array(data[data_index])) 87 | TYPE_FLOAT: 88 | arr.append_array(float_to_byte_array_8(data[data_index])) 89 | TYPE_INT: 90 | arr.append_array(int_to_byte_array_4(data[data_index])) 91 | 92 | data_index += 1 93 | 94 | if !init: 95 | if pad_byte_array(arr).size() != byte_length && uniform.uniform_type == RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER: 96 | printerr("Data for uniform: " + str(alias) + " does not match struct requirements. Needs: " + str(byte_length) + " was given: " + str(arr.size())) 97 | 98 | return pad_byte_array(arr) 99 | 100 | 101 | ## Per the alignment spec for SPIR-V structs, struct alignments must be rounded to a multiple of 16. 102 | func pad_byte_array(arr: PackedByteArray): 103 | 104 | var copy = arr.duplicate() 105 | while copy.size() % 16 != 0: 106 | copy.append(0) 107 | return copy 108 | 109 | 110 | ## Decode the contents of the passed in PackedByteArray to an Array matching 111 | ## the order and data types defined in `struct_data`. 112 | func decode_struct(data: PackedByteArray) -> Array: 113 | 114 | var arr: Array = [] 115 | 116 | var offset: int = 0 117 | 118 | for i in range(struct_data.size()): 119 | 120 | match typeof(struct_data[i]): 121 | TYPE_VECTOR3I: 122 | var vec = byte_array_to_vec3(data.slice(offset, offset + 32)) 123 | arr.push_back(vec) 124 | offset += 32 125 | TYPE_COLOR: 126 | var col = byte_array_to_color(data.slice(offset, offset + 32)) 127 | arr.push_back(col) 128 | offset += 32 129 | TYPE_VECTOR3: 130 | var vec = byte_array_to_vec3(data.slice(offset, offset + 32)) 131 | arr.push_back(vec) 132 | offset += 32 133 | TYPE_FLOAT: 134 | var flo = byte_array_to_float(data.slice(offset, offset + 8)) 135 | arr.push_back(flo) 136 | offset += 8 137 | TYPE_INT: 138 | var integer = byte_array_to_int(data.slice(offset, offset + 4)) 139 | arr.push_back(integer) 140 | offset += 4 141 | 142 | return arr 143 | -------------------------------------------------------------------------------- /addons/compute_worker/gpu_uniforms/gpu_uniform.gd: -------------------------------------------------------------------------------- 1 | @icon("res://addons/compute_worker/gpu_uniforms/gpu_uniform_icon.png") 2 | 3 | extends Resource 4 | class_name GPUUniform 5 | 6 | 7 | ## Base class for uniforms used with ComputeWorker. 8 | ## Contains functions used for serializing Godot data types to and from GLSL equivalents. 9 | 10 | ## User-defined name for the uniform. Used for accessing the GPUUniform object via ComputeWorker. 11 | @export var alias: String = "" 12 | 13 | 14 | ## Set up uniform buffer and register with RenderingDevice. Returns the resulting RDUniform. 15 | func initialize(_rd: RenderingDevice): pass 16 | ## Set uniform type (Uniform or Storage Buffer), register buffer RID and binding with RDUniform. 17 | func create_uniform(): pass 18 | ## Determine size of buffer based on initial data provided, and register with RenderingDevice. Returns buffer RID. 19 | func create_rid(_rd: RenderingDevice): pass 20 | ## Retrieves and decodes the data that is currently in the uniform/storage buffer. 21 | func get_uniform_data(_rd: RenderingDevice): pass 22 | ## Encodes and sets the data in the uniform/storage buffer. 23 | func set_uniform_data(_rd: RenderingDevice, _value): pass 24 | 25 | 26 | func bool_to_byte_array(value: bool) -> PackedByteArray: 27 | var arr = PackedByteArray() 28 | if value: 29 | arr.encode_u32(0, 1) 30 | return arr 31 | else: 32 | arr.encode_u32(0, 0) 33 | return arr 34 | 35 | 36 | func byte_array_to_bool(array: PackedByteArray) -> bool: 37 | var num = array.decode_u32(0) 38 | if num != 0: 39 | return true 40 | else: 41 | return false 42 | 43 | 44 | ## Convert Vector4 to GLSL equivalent `dvec4` 45 | func vec4_to_byte_array(vector: Vector4) -> PackedByteArray: 46 | return PackedFloat64Array([vector.x, vector.y, vector.z, vector.w]).to_byte_array() 47 | 48 | 49 | ## Convert GLSL `dvec4` to Vector4 50 | func byte_array_to_vec4(array: PackedByteArray) -> Vector4: 51 | var vec = Vector4() 52 | vec.x = array.decode_double(0) 53 | vec.y = array.decode_double(8) 54 | vec.z = array.decode_double(16) 55 | vec.w = array.decode_double(24) 56 | return vec 57 | 58 | 59 | ## Convert Color to GLSL equivalent `dvec4` 60 | func color_to_byte_array(color: Color) -> PackedByteArray: 61 | return PackedFloat64Array([color.r, color.g, color.b, color.a]).to_byte_array() 62 | 63 | 64 | ## Convert GLSL `dvec4` to Color 65 | func byte_array_to_color(array: PackedByteArray) -> Color: 66 | var col = Color() 67 | col.r = array.decode_double(0) 68 | col.g = array.decode_double(8) 69 | col.b = array.decode_double(16) 70 | col.a = array.decode_double(24) 71 | return col 72 | 73 | 74 | ## Convert a float to GLSL equivalent `double` format without padding. For use inside structs 75 | func float_to_byte_array_8(num: float) -> PackedByteArray: 76 | return PackedFloat64Array([num]).to_byte_array() 77 | 78 | 79 | ## Convert a float to GLSL equivalent `double` format 80 | func float_to_byte_array(num: float) -> PackedByteArray: 81 | return PackedFloat64Array([num, 0.0]).to_byte_array() 82 | 83 | 84 | ## Convert GLSL `double, float` to float 85 | func byte_array_to_float(array: PackedByteArray) -> float: 86 | return array.decode_double(0) 87 | 88 | 89 | ## Convert an int to GLSL equivalent `int` format 90 | ## Note the loss of precision here. GLSL integers are 32bit, while Godot's are 64bit 91 | func int_to_byte_array(num: int) -> PackedByteArray: 92 | return PackedInt32Array([num, 0, 0, 0]).to_byte_array() 93 | 94 | 95 | ## Convert an int to GLSL equivalent `int` format without padding. For use inside structs 96 | func int_to_byte_array_4(num: int) -> PackedByteArray: 97 | return PackedInt32Array([num]).to_byte_array() 98 | 99 | 100 | ## Convert GLSL `int` to int 101 | func byte_array_to_int(array: PackedByteArray) -> int: 102 | return array.decode_s32(0) 103 | 104 | 105 | func byte_array_to_uint(array: PackedByteArray) -> int: 106 | return array.decode_u32(0) 107 | 108 | 109 | ## Convert GLSL `dvec2` to Vector2 110 | func byte_array_to_vec2(array: PackedByteArray) -> Vector2: 111 | 112 | var dup = array.duplicate() 113 | 114 | dup.to_float64_array() 115 | var vec = Vector2() 116 | vec.x = dup.decode_double(0) 117 | vec.y = dup.decode_double(8) 118 | 119 | return vec 120 | 121 | 122 | ## Convert a Vector2 to GLSL equivalent `dvec2` 123 | func vec2_to_byte_array(vec: Vector2) -> PackedByteArray: 124 | return PackedFloat64Array([vec.x, vec.y]).to_byte_array() 125 | 126 | 127 | ## Convert GLSL `vec3, ivec3` to Vector3 128 | func byte_array_to_vec3(array: PackedByteArray) -> Vector3: 129 | 130 | var dup = array.duplicate() 131 | 132 | dup.to_float64_array() 133 | var vec = Vector3() 134 | vec.x = dup.decode_double(0) 135 | vec.y = dup.decode_double(8) 136 | vec.z = dup.decode_double(16) 137 | 138 | return vec 139 | 140 | 141 | ## Convert a Vector3 to GLSL equivalent `dvec3, dvec4` format 142 | func vec3_to_byte_array(vector: Vector3) -> PackedByteArray: 143 | 144 | return PackedFloat64Array([vector.x, vector.y, vector.z, 0.0]).to_byte_array() 145 | 146 | 147 | ## Convert a Vector3i to GLSL equivalent `ivec3, ivec4` format 148 | func vec3i_to_byte_array(vector: Vector3i) -> PackedByteArray: 149 | 150 | # We have to add a value for the "w" field for the vector, 151 | # because the alignment spec for GLSL vec3s requires 16bytes 152 | return PackedInt32Array([vector.x, vector.y, vector.z, 0]).to_byte_array() 153 | 154 | 155 | ## Convert an array of Vector3s to GLSL equivalent `vec3[], vec4[]` format 156 | func vec3_array_to_byte_array(array: PackedVector3Array): 157 | 158 | var bytes: PackedByteArray = PackedByteArray() 159 | 160 | for vector in array: 161 | var vec: Vector4 = Vector4() 162 | 163 | vec.x = vector.x 164 | vec.y = vector.y 165 | vec.z = vector.z 166 | vec.w = 0.0 167 | 168 | # We have to add a value for the "w" field for the vector, 169 | # because the alignment spec for GLSL vec3s requires 16bytes 170 | var float_arr = PackedFloat32Array([vector.x, vector.y, vector.z, 0.0]).to_byte_array() 171 | bytes.append_array(float_arr) 172 | 173 | return bytes 174 | 175 | 176 | ## Convert GLSL `vec3[]` to an Array of Vector3s 177 | func byte_array_to_vec3_array(bytes: PackedByteArray) -> PackedVector3Array: 178 | 179 | var arr: PackedVector3Array = PackedVector3Array() 180 | 181 | for v in range(bytes.size() / 16.0): 182 | 183 | var vec = Vector3() 184 | 185 | vec.x = bytes.decode_float(0 + (v * 16)) 186 | vec.y = bytes.decode_float(4 + (v * 16)) 187 | vec.z = bytes.decode_float(8 + (v * 16)) 188 | 189 | arr.append(vec) 190 | 191 | return arr 192 | 193 | 194 | ## Convert an array of Floats to GLSL equivalent `double[]` 195 | func float_array_to_byte_array_64(array: Array[float]) -> PackedByteArray: 196 | var bytes = PackedFloat64Array(array).to_byte_array() 197 | return bytes 198 | 199 | 200 | ## Convert a GLSL `double[]` to an Array of Floats 201 | func byte_array_64_to_float_array(array: PackedByteArray) -> Array[float]: 202 | return Array(array.to_float64_array()) 203 | 204 | -------------------------------------------------------------------------------- /addons/compute_worker/compute_worker.gd: -------------------------------------------------------------------------------- 1 | @icon("res://addons/compute_worker/compute_worker_icon.png") 2 | 3 | extends Node 4 | class_name ComputeWorker 5 | 6 | 7 | ## The GLSL shader file to execute 8 | @export var shader_file: RDShaderFile = null 9 | ## The uniform sets to bind to the compute pipeline. Must be UniformSet resources. 10 | @export var uniform_sets: Array[UniformSet] = [] 11 | ## The size of the global work group to dispatch. 12 | @export var work_group_size: Vector3i = Vector3i(1, 1, 1) 13 | ## If `true`, the worker will use the global rendering pipeline. 14 | @export var use_global_device: bool = false 15 | 16 | var rd: RenderingDevice = null 17 | 18 | var compute_pipeline: RID = RID() 19 | var shader_rid: RID = RID() 20 | 21 | var initialized = false 22 | 23 | 24 | signal compute_begin 25 | signal compute_end 26 | 27 | 28 | ## Call this to initialize and dispatch the compute list. 29 | ## Initial uniform data can be set by getting the uniform using `get_uniform_by_binding()` or `get_uniform_by_alias()`, 30 | ## and setting the uniform data directly before calling this. 31 | func initialize() -> void: 32 | 33 | if !rd: 34 | if use_global_device: 35 | rd = RenderingServer.get_rendering_device() 36 | else: 37 | rd = RenderingServer.create_local_rendering_device() 38 | 39 | # Load GLSL shader 40 | var shader_spirv: RDShaderSPIRV = shader_file.get_spirv() 41 | shader_rid = rd.shader_create_from_spirv(shader_spirv) 42 | 43 | # Generate uniform set from provided `GPU_*.tres` uniforms 44 | for i in range(uniform_sets.size()): 45 | uniform_sets[i].initialize(rd, shader_rid) 46 | 47 | # Create the RenderingDevice compute pipeline 48 | compute_pipeline = _create_compute_pipeline(shader_rid) 49 | 50 | # Bind uniform set and pipeline to compute list and dispatch 51 | dispatch_compute_list() 52 | 53 | initialized = true 54 | 55 | 56 | ## Fetch the data from a uniform by binding id 57 | func get_uniform_data(binding: int, set_id: int = 0) -> Variant: 58 | 59 | if !initialized: 60 | printerr("ComputeWorker must be initialized before accessing uniform data") 61 | return 62 | 63 | var uniform = get_uniform_by_binding(binding, set_id) 64 | 65 | if !uniform: 66 | printerr("Uniform at binding `" + str(binding) + "` not found in set " + str(set_id) + ".") 67 | return 68 | 69 | return uniform.get_uniform_data(rd) 70 | 71 | 72 | ## Fetch the data from a uniform by alias 73 | func get_uniform_data_by_alias(alias: String, set_id: int = 0) -> Variant: 74 | 75 | if !initialized: 76 | printerr("ComputeWorker must be initialized before accessing uniform data") 77 | return 78 | 79 | var uniform = get_uniform_by_alias(alias, set_id) 80 | 81 | if !uniform: 82 | printerr("Uniform `" + alias + "` not found in set " + str(set_id) + ".") 83 | return 84 | 85 | return uniform.get_uniform_data(rd) 86 | 87 | 88 | ## Set the data of a uniform by binding. If `dispatch` is true, the shader is executed and uniforms are updated immediately. 89 | ## `initialize()` must be called before setting uniform data with this function. 90 | ## To set uniform data before `initialized()` is called, 91 | ## get the GPU_* uniform object with `get_uniform_by_*()` and set the data directly. 92 | func set_uniform_data(data: Variant, binding: int, set_id: int = 0, dispatch: bool = true) -> void: 93 | 94 | if !initialized: 95 | printerr("ComputeWorker must be initialized before accessing uniform data") 96 | return 97 | 98 | var uniform = get_uniform_by_binding(binding, set_id) 99 | 100 | uniform.set_uniform_data(rd, data) 101 | 102 | # Must dispatch new compute list with updated uniforms to take effect 103 | if dispatch: 104 | dispatch_compute_list() 105 | execute_compute_shader() 106 | 107 | 108 | ## Same as `set_uniform_data`, except it searches by the uniform's `alias` 109 | func set_uniform_data_by_alias(data: Variant, alias: String, set_id: int = 0, dispatch: bool = true) -> void: 110 | 111 | if !initialized: 112 | printerr("ComputeWorker must be initialized before accessing uniform data") 113 | return 114 | 115 | var uniform = get_uniform_by_alias(alias, set_id) 116 | 117 | uniform.set_uniform_data(rd, data) 118 | 119 | # Must dispatch new compute list with updated uniforms to take effect 120 | if dispatch: 121 | dispatch_compute_list() 122 | execute_compute_shader() 123 | 124 | 125 | ## Submit current compute list and wait for sync to update uniform values 126 | func execute_compute_shader() -> void: 127 | 128 | if use_global_device: return 129 | 130 | emit_signal("compute_begin") 131 | rd.submit() 132 | 133 | rd.sync() 134 | emit_signal("compute_end") 135 | 136 | 137 | ## Internal. Create the compute pipeline for the RenderingDevice, returns pipeline RID 138 | func _create_compute_pipeline(shader: RID) -> RID: 139 | 140 | var pipeline := rd.compute_pipeline_create(shader) 141 | return pipeline 142 | 143 | 144 | ## Binds and dispatches the compute list using the current uniform set and pipeline 145 | func dispatch_compute_list() -> void: 146 | 147 | var compute_list := rd.compute_list_begin() 148 | rd.compute_list_bind_compute_pipeline(compute_list, compute_pipeline) 149 | 150 | for u_set in uniform_sets: 151 | rd.compute_list_bind_uniform_set(compute_list, u_set.uniform_set_rid, u_set.set_id) 152 | 153 | rd.compute_list_dispatch(compute_list, work_group_size.x, work_group_size.y, work_group_size.z) 154 | rd.compute_list_end() 155 | 156 | 157 | ## Get a UniformSet resource by its set id 158 | func get_uniform_set_by_id(id: int) -> UniformSet: 159 | 160 | for u_set in uniform_sets: 161 | if u_set.set_id == id: 162 | return u_set 163 | return null 164 | 165 | 166 | ## Get GPU_* uniform object in `set` by binding id 167 | func get_uniform_by_binding(binding: int, set_id: int = 0) -> GPUUniform: 168 | 169 | for uniform in get_uniform_set_by_id(set_id).uniforms: 170 | if uniform.binding == binding: 171 | return uniform 172 | return null 173 | 174 | 175 | ## Get the GPUUniform object in `set` by its user-defined `alias` 176 | func get_uniform_by_alias(alias: String, set_id: int = 0) -> GPUUniform: 177 | 178 | for uniform in get_uniform_set_by_id(set_id).uniforms: 179 | if uniform.alias == alias: 180 | return uniform 181 | return null 182 | 183 | 184 | ## Get the binding id of the GPU_* uniform in `set` by user-defined `alias` 185 | func get_uniform_binding_by_alias(alias: String, set_id: int = 0) -> int: 186 | 187 | for uniform in get_uniform_set_by_id(set_id).uniforms: 188 | if uniform.alias == alias: 189 | return uniform.binding 190 | return -1 191 | 192 | 193 | ## Frees all RenderingDevice-created resources, then the RenderingDevice itself. 194 | ## Can be used to stop execution and change shaders, uniforms, etc. 195 | ## `initialize()` must be called again to resume operation. 196 | func destroy() -> void: 197 | 198 | if !rd: return 199 | 200 | for u_set in uniform_sets: 201 | u_set.destroy(rd) 202 | 203 | rd.free_rid(compute_pipeline) 204 | rd.free_rid(shader_rid) 205 | 206 | if !use_global_device: 207 | rd.free() 208 | 209 | rd = null 210 | initialized = false 211 | 212 | 213 | func _exit_tree(): 214 | destroy() 215 | --------------------------------------------------------------------------------