2024-12-27 21:00:07 +01:00

75 lines
2.5 KiB
GDScript

## Represents a Compute Shader as an Observable Sequence.
## [br][br]
## Please note: This is a [b]cold[/b] [Observable]. It transfers data to GPU
## on subscribe. Thus, each subscription causes one computational step.
## When the compute shader finishes, the [RenderingDevice] is emitted as item.
## Afterwards the stream completes.
## [br][br]
## [b]Args:[/b]
## [br]
## [code]shader_path[/code] the path to the GLSL file with the shader source
## [br]
## [code]rd[/code] The current instance of [RenderingDevice]
## [br]
## [code]work_groups[/code]: Set x, y and z dimensions of work groups.
## [br]
## [code]uniform_sets[/code]: A list containing lists of [RDUniform]
## representing n uniform sets starting with [code]set = 0[/code] going
## upwards.
## [br]
## [code]scheduler[/code]: Schedules the CPU side of the shader computation
## [br][br]
## [b]Return:[/b]
## An observable sequence which performs a new computation on the device,
## each time an [Observer] subscribes.
static func from_compute_shader_(
shader_path : String,
rd : RenderingDevice,
work_groups : Vector3i,
uniform_sets : Array = [],
scheduler : SchedulerBase = null
) -> Observable:
# Create shader and pipeline
var shader_file = load(shader_path)
var shader_spirv = shader_file.get_spirv()
var shader = rd.shader_create_from_spirv(shader_spirv)
var pipeline = rd.compute_pipeline_create(shader)
var uniform_sets_rids = []
for sid in range(uniform_sets.size()):
uniform_sets_rids.append(
rd.uniform_set_create(uniform_sets[sid], shader, sid)
)
var subscribe = func(
observer : ObserverBase,
scheduler_ : SchedulerBase = null
) -> DisposableBase:
var _scheduler
if scheduler != null: _scheduler = scheduler
elif scheduler_ != null: _scheduler = scheduler_
else: _scheduler = CurrentThreadScheduler.singleton()
var action = func(_scheduler = null, _state = null):
# Setup compute pipeline and uniforms
var compute_list = rd.compute_list_begin()
rd.compute_list_bind_compute_pipeline(compute_list, pipeline)
for sid in range(uniform_sets_rids.size()):
rd.compute_list_bind_uniform_set(compute_list, uniform_sets_rids[sid], sid)
rd.compute_list_dispatch(compute_list, work_groups.x, work_groups.y, work_groups.z)
rd.compute_list_end()
# Send to GPU
rd.submit()
# Sync with CPU
rd.sync()
observer.on_next(rd)
observer.on_completed()
return _scheduler.schedule(action)
return Observable.new(subscribe)