85 lines
3.3 KiB
GDScript
85 lines
3.3 KiB
GDScript
## Issues bounded, per-frame permits for renderer main-thread operation lanes.
|
|
##
|
|
## The scheduler owns counters only. Queue contents, operation ordering and the
|
|
## side effects performed after a permit remain owned by the caller. One instance
|
|
## belongs to one renderer lifecycle and must only be used on the main thread.
|
|
class_name RenderBudgetScheduler
|
|
extends RefCounted
|
|
|
|
const TILE_FINALIZE: StringName = &"tile_finalize"
|
|
const TERRAIN_UPGRADE_FINALIZE: StringName = &"terrain_upgrade_finalize"
|
|
const TERRAIN_CONTROL_SPLAT_FINALIZE: StringName = &"terrain_control_splat_finalize"
|
|
const TERRAIN_SPLAT_CACHE_FINALIZE: StringName = &"terrain_splat_cache_finalize"
|
|
const TERRAIN_SPLAT_BUILD: StringName = &"terrain_splat_build"
|
|
const WATER_FINALIZE: StringName = &"water_finalize"
|
|
const CHUNK_GEOMETRY: StringName = &"chunk_geometry"
|
|
const TILE_LOAD_START: StringName = &"tile_load_start"
|
|
const TILE_LOD_CREATE: StringName = &"tile_lod_create"
|
|
const TILE_LOD_REMOVE: StringName = &"tile_lod_remove"
|
|
const M2_ANIMATION_FINALIZE: StringName = &"m2_animation_finalize"
|
|
const M2_MESH_FINALIZE: StringName = &"m2_mesh_finalize"
|
|
const M2_BUILD: StringName = &"m2_build"
|
|
const WMO_BUILD: StringName = &"wmo_build"
|
|
const WMO_RENDER_GROUP_BUILD: StringName = &"wmo_render_group_build"
|
|
const DETAIL_ASSET_SYNC: StringName = &"detail_asset_sync"
|
|
|
|
var _remaining_permits_by_lane: Dictionary = {}
|
|
var _consumed_permits_by_lane: Dictionary = {}
|
|
var _is_cancelled := false
|
|
|
|
|
|
## Replaces all lane limits for a new frame. Negative limits are treated as zero.
|
|
## Calling this after [method cancel] leaves the scheduler cancelled.
|
|
func begin_frame(operation_limits_by_lane: Dictionary) -> void:
|
|
_remaining_permits_by_lane.clear()
|
|
_consumed_permits_by_lane.clear()
|
|
if _is_cancelled:
|
|
return
|
|
|
|
for lane_variant in operation_limits_by_lane:
|
|
var lane := StringName(lane_variant)
|
|
_remaining_permits_by_lane[lane] = maxi(0, int(operation_limits_by_lane[lane_variant]))
|
|
_consumed_permits_by_lane[lane] = 0
|
|
|
|
|
|
## Returns whether a lane can issue another permit without consuming it.
|
|
## Unknown lanes and cancelled schedulers return false.
|
|
func has_remaining_permit(lane: StringName) -> bool:
|
|
if _is_cancelled:
|
|
return false
|
|
return int(_remaining_permits_by_lane.get(lane, 0)) > 0
|
|
|
|
|
|
## Consumes one permit from [param lane] and returns true when it was granted.
|
|
## Unknown, exhausted or cancelled lanes return false without changing state.
|
|
func try_consume_permit(lane: StringName) -> bool:
|
|
if not has_remaining_permit(lane):
|
|
return false
|
|
_remaining_permits_by_lane[lane] = int(_remaining_permits_by_lane[lane]) - 1
|
|
_consumed_permits_by_lane[lane] = int(_consumed_permits_by_lane.get(lane, 0)) + 1
|
|
return true
|
|
|
|
|
|
## Returns the unconsumed permit count for one lane.
|
|
func remaining_permits(lane: StringName) -> int:
|
|
if _is_cancelled:
|
|
return 0
|
|
return int(_remaining_permits_by_lane.get(lane, 0))
|
|
|
|
|
|
## Returns a detached diagnostic snapshot of permits consumed in this frame.
|
|
func consumed_permits_snapshot() -> Dictionary:
|
|
return _consumed_permits_by_lane.duplicate()
|
|
|
|
|
|
## Permanently rejects new permits for this scheduler instance and clears limits.
|
|
## In-flight work remains the caller's responsibility and is not interrupted.
|
|
func cancel() -> void:
|
|
_is_cancelled = true
|
|
_remaining_permits_by_lane.clear()
|
|
|
|
|
|
## Returns whether [method cancel] ended this scheduler lifecycle.
|
|
func is_cancelled() -> bool:
|
|
return _is_cancelled
|