merge(M03): integrate ground query cold-start fix

This commit is contained in:
2026-07-16 00:52:08 +04:00
6 changed files with 61 additions and 7 deletions
+2
View File
@@ -937,6 +937,8 @@ $exe = Join-Path $env:TEMP 'godot-4.6.1-openwc\Godot_v4.6.1-stable_win64.exe'
- `WorldRenderFacade.sample_ground_height()` accepts `GodotWorldPosition` and - `WorldRenderFacade.sample_ground_height()` accepts `GodotWorldPosition` and
returns renderer-owned immutable `RenderedGroundSample` from already loaded returns renderer-owned immutable `RenderedGroundSample` from already loaded
quality/tile-LOD render meshes, avoiding a render-to-gameplay dependency. quality/tile-LOD render meshes, avoiding a render-to-gameplay dependency.
- Its factories load the predeclared Script path instead of relying on a warm
global-class cache; a dedicated cold-start verifier covers this bootstrap path.
- `renderer_ground_query_snapshot()` preserves the terrain probe's tile readiness, - `renderer_ground_query_snapshot()` preserves the terrain probe's tile readiness,
queue position, mesh bounds and nearby seam-fallback diagnostics as a detached queue position, mesh bounds and nearby seam-fallback diagnostics as a detached
Dictionary; callers receive no queue, tile-state, Mesh or Node reference. Dictionary; callers receive no queue, tile-state, Mesh or Node reference.
@@ -78,19 +78,20 @@ terrain-height probe away from direct streamer state/queue access.
- State: ready-for-review - State: ready-for-review
- Done: added renderer-owned typed sample, facade query/snapshot, migrated terrain - Done: added renderer-owned typed sample, facade query/snapshot, migrated terrain
probe, expanded internal-access/coordinate gates and updated module docs probe, expanded internal-access/coordinate gates and updated module docs
- Next: M03 integrator reviews and merges `b697a89` - Next: M03 integrator reviews and merges `b697a89` plus cold-start fix `9408d88`
- Blocked by: - Blocked by:
<!-- OPENWC_HANDOFF:READY:M03-RND-FACADE-GROUND-QUERY-001:b697a89 --> <!-- OPENWC_HANDOFF:READY:M03-RND-FACADE-GROUND-QUERY-001:9408d88 -->
## Handoff ## Handoff
- Commit: `b697a89` - Commits: implementation `b697a89`; cold-start fix `9408d88`
- Results: `WorldRenderFacade` delegates loaded-mesh ground sampling and returns - Results: `WorldRenderFacade` delegates loaded-mesh ground sampling and returns
renderer-owned `RenderedGroundSample`; detached diagnostic snapshots preserve renderer-owned `RenderedGroundSample`; detached diagnostic snapshots preserve
the probe report while hiding queue/tile/Mesh/Node references. Gameplay remains the probe report while hiding queue/tile/Mesh/Node references. Gameplay remains
on the independent M02 `TerrainQuery` composition. on the independent M02 `TerrainQuery` composition.
- Verification: facade `delegation=5 ground_contract=2 runtime_scenes=2 tools=3`; - Verification: facade `delegation=5 ground_contract=2 runtime_scenes=2 tools=3`;
cold rendered-ground value `contract=3` from an empty Godot class cache;
internal access `private_symbols=43 gameplay=7 editor_sources=9 renderer_tools=1`; internal access `private_symbols=43 gameplay=7 editor_sources=9 renderer_tools=1`;
terrain query contracts passed; coordinate boundary `files=113 consumers=5`; terrain query contracts passed; coordinate boundary `files=113 consumers=5`;
renderer manifest `7/7`; shutdown ownership, scheduler/planner, coordination, renderer manifest `7/7`; shutdown ownership, scheduler/planner, coordination,
+3
View File
@@ -293,6 +293,8 @@ Exact exported settings and cache versions remain documented in [`../../RENDER.m
gameplay or EditorPlugin package code. gameplay or EditorPlugin package code.
- Ground-query facade contract: available/unavailable typed result delegation, - Ground-query facade contract: available/unavailable typed result delegation,
detached nested diagnostics and terrain-probe source migration without private access. detached nested diagnostics and terrain-probe source migration without private access.
- Rendered-ground value contract: available/non-finite/unavailable invariants pass
from a cold Godot class cache before editor import.
- Integration/E2E: Eastern Kingdoms/Kalimdor streaming scenes, seven M00 - Integration/E2E: Eastern Kingdoms/Kalimdor streaming scenes, seven M00
cold/warm checkpoints and one dedicated mapped server-spawn checkpoint. cold/warm checkpoints and one dedicated mapped server-spawn checkpoint.
- Fidelity evidence: семь локальных build 12340 reference JPG покрывают terrain/ADT/M2/WMO/liquid/sky и реальный `GryphonRoost01`; automated cold/warm metrics имеют `compared=14`, `missing=0`. Sky использует приблизительно paired camera, а animated-M2 остаётся asset-paired/placement-unpaired из-за synthetic probe. - Fidelity evidence: семь локальных build 12340 reference JPG покрывают terrain/ADT/M2/WMO/liquid/sky и реальный `GryphonRoost01`; automated cold/warm metrics имеют `compared=14`, `missing=0`. Sky использует приблизительно paired camera, а animated-M2 остаётся asset-paired/placement-unpaired из-за synthetic probe.
@@ -361,6 +363,7 @@ Exact exported settings and cache versions remain documented in [`../../RENDER.m
| `src/domain/streaming/streaming_focus.gd` | Immutable camera-independent streaming position contract | | `src/domain/streaming/streaming_focus.gd` | Immutable camera-independent streaming position contract |
| `src/tools/verify_streaming_focus.gd` | Headless contract, dependency and runtime/tool wiring regression | | `src/tools/verify_streaming_focus.gd` | Headless contract, dependency and runtime/tool wiring regression |
| `src/tools/verify_world_render_facade.gd` | Focus/metrics/ground delegation, snapshot isolation and consumer wiring regression | | `src/tools/verify_world_render_facade.gd` | Focus/metrics/ground delegation, snapshot isolation and consumer wiring regression |
| `src/tools/verify_rendered_ground_sample.gd` | Cold-start renderer ground result invariant regression |
| `src/tools/verify_streaming_target_planner.gd` | Planner behavior, dependency and bounded timing regression | | `src/tools/verify_streaming_target_planner.gd` | Planner behavior, dependency and bounded timing regression |
| `src/tools/verify_render_budget_scheduler.gd` | Scheduler bounds, shared-lane priority, cancellation and timing regression | | `src/tools/verify_render_budget_scheduler.gd` | Scheduler bounds, shared-lane priority, cancellation and timing regression |
| `src/tools/verify_renderer_internal_access.gd` | Gameplay/EditorPlugin/registered renderer-tool boundary gate derived from private streamer fields | | `src/tools/verify_renderer_internal_access.gd` | Gameplay/EditorPlugin/registered renderer-tool boundary gate derived from private streamer fields |
+6 -4
View File
@@ -20,15 +20,17 @@ var _is_available: bool
var _height_units: float var _height_units: float
var _failure_code: StringName var _failure_code: StringName
const SCRIPT_PATH := "res://src/render/terrain/rendered_ground_sample.gd"
## Creates an available finite rendered-ground sample in Godot world units. ## Creates an available finite rendered-ground sample in Godot world units.
static func available(height_units_value: float) -> RenderedGroundSample: static func available(height_units_value: float) -> RefCounted:
return RenderedGroundSample.new(true, height_units_value, &"") return load(SCRIPT_PATH).new(true, height_units_value, &"")
## Creates an unavailable rendered-ground sample with a stable failure code. ## Creates an unavailable rendered-ground sample with a stable failure code.
static func unavailable(failure_code_value: StringName) -> RenderedGroundSample: static func unavailable(failure_code_value: StringName) -> RefCounted:
return RenderedGroundSample.new(false, 0.0, failure_code_value) return load(SCRIPT_PATH).new(false, 0.0, failure_code_value)
func _init( func _init(
@@ -0,0 +1,45 @@
extends SceneTree
## Cold-start contract for the renderer-owned ground query result value.
const SAMPLE_SCRIPT := preload("res://src/render/terrain/rendered_ground_sample.gd")
func _initialize() -> void:
var failures: Array[String] = []
var available_sample: RefCounted = SAMPLE_SCRIPT.available(42.25)
_expect_true(bool(available_sample.get("is_available")), "available sample", failures)
_expect_near(float(available_sample.get("height_units")), 42.25, "available height", failures)
var non_finite_sample: RefCounted = SAMPLE_SCRIPT.available(INF)
_expect_true(not bool(non_finite_sample.get("is_available")), "non-finite unavailable", failures)
_expect_true(
StringName(non_finite_sample.get("failure_code")) == &"render_terrain_height_not_finite",
"non-finite failure code",
failures
)
var unavailable_sample: RefCounted = SAMPLE_SCRIPT.unavailable(&"")
_expect_true(
StringName(unavailable_sample.get("failure_code")) == &"render_terrain_unavailable",
"empty failure code normalization",
failures
)
if not failures.is_empty():
for failure in failures:
push_error("RENDERED_GROUND_SAMPLE: %s" % failure)
quit(1)
return
print("RENDERED_GROUND_SAMPLE PASS contract=3")
quit(0)
func _expect_near(actual_value: float, expected_value: float, label: String, failures: Array[String]) -> void:
if not is_equal_approx(actual_value, expected_value):
failures.append("%s expected %.3f, got %.3f" % [label, expected_value, actual_value])
func _expect_true(actual_value: bool, label: String, failures: Array[String]) -> void:
if not actual_value:
failures.append("%s expected true" % label)
@@ -0,0 +1 @@
uid://b8juyikyvx1xw