Commit 69eaaf30 authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: rung C2 - hoist pose prepare state to per-sequence/per-scene levels

Design 3-A4i rung C2 (native tile_processor_gpu HEAD):
- IntersceneLma: per-SEQUENCE cache (reference Camera + flattened centers,
  keyed on the reference ErsCorrection; the virtual center is static by
  construction - zero pose, zero rates) with an explicit
  resetPoseSequenceCache() re-armed at sequence start; per-SCENE cache
  (scene Camera in the per-scene instance: ERS rates never change across
  cycles - setupERS depends only on rates/line_time, verified, and the 3
  adjusted angles travel in pose_vectors). setupERS + Camera.capture now run
  once per level instead of 4x/scene; the provider gets null for resident
  groups. Provider/GpuQuad/GpuQuadJna signatures gain explicit numTiles.
- Dead work deleted: the threaded setEigenTransform build at the prepareLMA
  head runs only on the legacy/capture/MB fall-through (the GPU assemble
  builds the transform from resident peaks on the production path).
- CuasPoseRT: resetPoseSequenceCache() at testPoseSequence start.
Expected: prep setup 5.7 -> ~1.5 ms cycle-1 / ~0.3-0.7 cycles 2-4, prepare
~22.9 -> ~3-5 ms/scene; per-cycle PCIe ~120KB -> ~60B + result.
Gates: mvn package+test PASS; Stage0 36/36; full native suite PASS.
Co-Authored-By: 's avatarClaude Fable 5 <noreply@anthropic.com>
parent c5e83b04
...@@ -1087,11 +1087,12 @@ public class CuasPoseRT { ...@@ -1087,11 +1087,12 @@ public class CuasPoseRT {
// vector + centers + policy scalars; D2H = the 8-float compact result. The // vector + centers + policy scalars; D2H = the 8-float compact result. The
// packed-index slot/shift are CUAS host policy. By Claude on 07/17/2026. // packed-index slot/shift are CUAS host policy. By Claude on 07/17/2026.
intersceneLma.setPoseLmaPrepareProvider((refCam, sceneCam, refXyz, refAtr, intersceneLma.setPoseLmaPrepareProvider((refCam, sceneCam, refXyz, refAtr,
sceneXyz, sceneAtr, centers, useEigen, eigMinSqrt, eigMaxSqrt, sceneXyz, sceneAtr, centers, numTiles, useEigen, eigMinSqrt, eigMaxSqrt,
minConfidence, sameWeights, pullTargets, paramRegweights, capture) -> { minConfidence, sameWeights, pullTargets, paramRegweights, capture) -> {
final IntersceneLmaFloat.PrepareResidentResult result = final IntersceneLmaFloat.PrepareResidentResult result =
lmaGpu.execPoseLmaPrepareResident( lmaGpu.execPoseLmaPrepareResident(
refCam, sceneCam, refXyz, refAtr, sceneXyz, sceneAtr, centers, refCam, sceneCam, refXyz, refAtr, sceneXyz, sceneAtr, centers,
numTiles, // rung C2: null camera/centers = keep resident // By Claude on 07/17/2026
0xff, GPUTileProcessor.CORR_NTILE_SHIFT, 0xff, GPUTileProcessor.CORR_NTILE_SHIFT,
useEigen, eigMinSqrt, eigMaxSqrt, minConfidence, sameWeights, useEigen, eigMinSqrt, eigMaxSqrt, minConfidence, sameWeights,
pullTargets, paramRegweights, capture); pullTargets, paramRegweights, capture);
...@@ -1622,6 +1623,10 @@ public class CuasPoseRT { ...@@ -1622,6 +1623,10 @@ public class CuasPoseRT {
"NO LMA: measurement/render chain only"+ "NO LMA: measurement/render chain only"+
(clt_parameters.curt.pose_lean ? "" : " (only implemented for the LEAN engine - ignored)")); (clt_parameters.curt.pose_lean ? "" : " (only implemented for the LEAN engine - ignored)"));
} }
// Rung C2: the per-sequence pose "configuration registers" (reference camera
// block + tile centers) are keyed on the reference ErsCorrection and must be
// re-armed at every sequence start. By Claude on 07/17/2026.
IntersceneLma.resetPoseSequenceCache();
// DEBUG (pose_corr_save): render per-scene pixel-domain correlations vs the virtual // DEBUG (pose_corr_save): render per-scene pixel-domain correlations vs the virtual
// center (-POSE-RT-CORR2D, z=scenes, last LMA cycle, 16x16 cells per tile) - the same // center (-POSE-RT-CORR2D, z=scenes, last LMA cycle, 16x16 cells per tile) - the same
// visual debugging used on the oracle. Lean only: the oracle engine does not expose // visual debugging used on the oracle. Lean only: the oracle engine does not expose
......
...@@ -2962,13 +2962,14 @@ public class GpuQuad{ // quad camera description ...@@ -2962,13 +2962,14 @@ public class GpuQuad{ // quad camera description
* prepare remains the fallback. By Claude on 07/17/2026. * prepare remains the fallback. By Claude on 07/17/2026.
*/ */
public IntersceneLmaFloat.PrepareResidentResult execPoseLmaPrepareResident( public IntersceneLmaFloat.PrepareResidentResult execPoseLmaPrepareResident(
IntersceneLmaFloat.Camera reference, IntersceneLmaFloat.Camera reference, // null = keep resident (rung C2)
IntersceneLmaFloat.Camera scene, IntersceneLmaFloat.Camera scene, // null = keep resident (rung C2)
float [] reference_xyz, float [] reference_xyz,
float [] reference_atr, float [] reference_atr,
float [] scene_xyz, float [] scene_xyz,
float [] scene_atr, float [] scene_atr,
float [] centers, float [] centers, // null = keep resident (rung C2)
int num_tiles, // rung C2 // By Claude on 07/17/2026
int corr_slot, int corr_slot,
int ntile_shift, int ntile_shift,
boolean use_eigen, boolean use_eigen,
......
...@@ -558,13 +558,14 @@ public class GpuQuadJna extends GpuQuad { ...@@ -558,13 +558,14 @@ public class GpuQuadJna extends GpuQuad {
// ---- rung C1: resident prepareLMA (design 2026-07-16) ---- // By Claude on 07/17/2026 // ---- rung C1: resident prepareLMA (design 2026-07-16) ---- // By Claude on 07/17/2026
@Override public IntersceneLmaFloat.PrepareResidentResult execPoseLmaPrepareResident( @Override public IntersceneLmaFloat.PrepareResidentResult execPoseLmaPrepareResident(
final IntersceneLmaFloat.Camera reference, final IntersceneLmaFloat.Camera reference, // null = keep resident (rung C2)
final IntersceneLmaFloat.Camera scene, final IntersceneLmaFloat.Camera scene, // null = keep resident (rung C2)
final float[] reference_xyz, final float[] reference_xyz,
final float[] reference_atr, final float[] reference_atr,
final float[] scene_xyz, final float[] scene_xyz,
final float[] scene_atr, final float[] scene_atr,
final float[] centers, final float[] centers, // null = keep resident (rung C2)
final int numTiles,
final int corrSlot, final int corrSlot,
final int ntileShift, final int ntileShift,
final boolean useEigen, final boolean useEigen,
...@@ -575,13 +576,12 @@ public class GpuQuadJna extends GpuQuad { ...@@ -575,13 +576,12 @@ public class GpuQuadJna extends GpuQuad {
final float[] pullTargets, final float[] pullTargets,
final float[] paramRegweights, final float[] paramRegweights,
final boolean capture) { final boolean capture) {
if ((reference == null) || (scene == null) || (centers == null) || if ((numTiles <= 0) ||
((centers.length % 3) != 0) || ((centers != null) && (centers.length != 3 * numTiles)) ||
(pullTargets == null) || (pullTargets.length != IntersceneLmaFloat.NUM_PARAMS) || (pullTargets == null) || (pullTargets.length != IntersceneLmaFloat.NUM_PARAMS) ||
(paramRegweights == null) || (paramRegweights.length != IntersceneLmaFloat.NUM_PARAMS)) { (paramRegweights == null) || (paramRegweights.length != IntersceneLmaFloat.NUM_PARAMS)) {
throw new IllegalArgumentException("GpuQuadJna.execPoseLmaPrepareResident: inconsistent inputs"); throw new IllegalArgumentException("GpuQuadJna.execPoseLmaPrepareResident: inconsistent inputs");
} }
final int numTiles = centers.length / 3;
final int numValues = IntersceneLmaFloat.NUM_COMPONENTS * numTiles + final int numValues = IntersceneLmaFloat.NUM_COMPONENTS * numTiles +
IntersceneLmaFloat.NUM_PARAMS; IntersceneLmaFloat.NUM_PARAMS;
final float[] poseVectors = new float[12]; final float[] poseVectors = new float[12];
...@@ -595,10 +595,18 @@ public class GpuQuadJna extends GpuQuad { ...@@ -595,10 +595,18 @@ public class GpuQuadJna extends GpuQuad {
final float[] outEigen = capture ? new float[4 * numTiles] : null; final float[] outEigen = capture ? new float[4 * numTiles] : null;
final int rc = lib.tp_proc_exec_pose_lma_prepare_resident( final int rc = lib.tp_proc_exec_pose_lma_prepare_resident(
proc, proc,
poseCameraMeta(reference), reference.radial, (reference != null) ? poseCameraMeta(reference) : null,
reference.rByRDist, reference.rByRDist.length, reference.ers, reference.ers.length, (reference != null) ? reference.radial : null,
poseCameraMeta(scene), scene.radial, (reference != null) ? reference.rByRDist : null,
scene.rByRDist, scene.rByRDist.length, scene.ers, scene.ers.length, (reference != null) ? reference.rByRDist.length : 0,
(reference != null) ? reference.ers : null,
(reference != null) ? reference.ers.length : 0,
(scene != null) ? poseCameraMeta(scene) : null,
(scene != null) ? scene.radial : null,
(scene != null) ? scene.rByRDist : null,
(scene != null) ? scene.rByRDist.length : 0,
(scene != null) ? scene.ers : null,
(scene != null) ? scene.ers.length : 0,
poseVectors, centers, poseVectors, centers,
numTiles, IntersceneLmaFloat.NUM_COMPONENTS, numTiles, IntersceneLmaFloat.NUM_COMPONENTS,
corrSlot, ntileShift, corrSlot, ntileShift,
......
...@@ -431,11 +431,10 @@ public class IntersceneLma { ...@@ -431,11 +431,10 @@ public class IntersceneLma {
// the LMA-prepare budget. Null sink = zero overhead. By Claude on 07/17/2026. // the LMA-prepare budget. Null sink = zero overhead. By Claude on 07/17/2026.
final ProfileSink prof_sink = profileSink; final ProfileSink prof_sink = profileSink;
final long prof_t0 = (prof_sink != null) ? System.nanoTime() : 0L; final long prof_t0 = (prof_sink != null) ? System.nanoTime() : 0L;
// before getFxDerivs // Rung C2: the threaded setEigenTransform build is DEAD WORK on the resident
eig_trans = setEigenTransform( // path (the GPU assemble builds the transform from the resident peaks) - it
eig_max_sqrt, // final double eig_max_sqrt, // is deferred to the legacy/capture fall-through below. By Claude on 07/17/2026.
eig_min_sqrt, // final double eig_min_sqrt, eig_trans = null;
eigen); // final double [][] eigen); // [tilesX*tilesY]{lamb0_x,lamb0_y, lamb0, lamb1} eigenvector0[x,y],lam0,lam1
tilesX = reference_QuadClt.getTileProcessor().getTilesX(); // just for debug images tilesX = reference_QuadClt.getTileProcessor().getTilesX(); // just for debug images
scenesCLT = new QuadCLT [] {reference_QuadClt, scene_QuadClt}; scenesCLT = new QuadCLT [] {reference_QuadClt, scene_QuadClt};
resetPoseFxInputs(); resetPoseFxInputs();
...@@ -516,6 +515,12 @@ public class IntersceneLma { ...@@ -516,6 +515,12 @@ public class IntersceneLma {
} // invalid/unavailable -> loud legacy fallback below } // invalid/unavailable -> loud legacy fallback below
System.out.println("IntersceneLma: resident prepare unavailable - legacy Java prepare"); System.out.println("IntersceneLma: resident prepare unavailable - legacy Java prepare");
} }
// Legacy / capture / MB fall-through: build the eigen transforms here
// (deferred from the head - dead work on the resident path). By Claude on 07/17/2026.
eig_trans = setEigenTransform(
eig_max_sqrt, // final double eig_max_sqrt,
eig_min_sqrt, // final double eig_min_sqrt,
eigen); // final double [][] eigen); // [tilesX*tilesY]{lamb0_x,lamb0_y, lamb0, lamb1} eigenvector0[x,y],lam0,lam1
if (vector_XYSDS != null) { // skip when used for the motion blur vectors, not LMA if (vector_XYSDS != null) { // skip when used for the motion blur vectors, not LMA
setSamplesWeights(vector_XYSDS, // not regularized yet ! // 3d updated setSamplesWeights(vector_XYSDS, // not regularized yet ! // 3d updated
min_confidence, // final double min_confidence,// minimal tile confidence to use. Use 0 to disable min_confidence, // final double min_confidence,// minimal tile confidence to use. Use 0 to disable
...@@ -2026,7 +2031,8 @@ public class IntersceneLma { ...@@ -2026,7 +2031,8 @@ public class IntersceneLma {
IntersceneLmaFloat.Camera scene, IntersceneLmaFloat.Camera scene,
float [] referenceXyz, float [] referenceAtr, float [] referenceXyz, float [] referenceAtr,
float [] sceneXyz, float [] sceneAtr, float [] sceneXyz, float [] sceneAtr,
float [] centers, float [] centers, // null = keep resident (per-sequence)
int numTiles, // rung C2 // By Claude on 07/17/2026
boolean useEigen, float eigMinSqrt, float eigMaxSqrt, boolean useEigen, float eigMinSqrt, float eigMaxSqrt,
float minConfidence, boolean sameWeights, float minConfidence, boolean sameWeights,
float [] pullTargets, float [] paramRegweights, float [] pullTargets, float [] paramRegweights,
...@@ -2038,6 +2044,22 @@ public class IntersceneLma { ...@@ -2038,6 +2044,22 @@ public class IntersceneLma {
} }
private IntersceneLmaFloat.PrepareResidentResult poseResidentPrepare = null; private IntersceneLmaFloat.PrepareResidentResult poseResidentPrepare = null;
private static boolean poseLmaPrepareOracleReported = false; // static like the other one-shot flags: IntersceneLma is per-scene (was instance -> 497 capture cycles) // By Claude on 07/17/2026 private static boolean poseLmaPrepareOracleReported = false; // static like the other one-shot flags: IntersceneLma is per-scene (was instance -> 497 capture cycles) // By Claude on 07/17/2026
// Rung C2 "configuration registers" (design 2026-07-16): per-SEQUENCE state -
// the virtual-center reference camera is static by construction (zero pose,
// zero rates) and the tile-centers grid is fixed - keyed on the reference
// ErsCorrection identity and reset explicitly at sequence start. Per-SCENE
// state (scene camera: ERS rates change per scene, never across cycles - only
// the 3 angles do, and those travel in pose_vectors) lives in the per-scene
// instance. Single-threaded pose loop - no synchronization. By Claude on 07/17/2026.
private static Object poseSeqKey = null;
private static IntersceneLmaFloat.Camera poseSeqRefCamera = null;
private static float [] poseSeqCenters = null;
public static void resetPoseSequenceCache() {
poseSeqKey = null;
poseSeqRefCamera = null;
poseSeqCenters = null;
}
private IntersceneLmaFloat.Camera poseResidentSceneCamera = null; // per-scene; NOT cleared by resetPoseFxInputs
/** Run the resident GPU prepare at the current parameters_vector (mirrors the /** Run the resident GPU prepare at the current parameters_vector (mirrors the
* getFxDerivs head: ERS pokes + setupERS + camera/centers capture). On * getFxDerivs head: ERS pokes + setupERS + camera/centers capture). On
...@@ -2059,21 +2081,37 @@ public class IntersceneLma { ...@@ -2059,21 +2081,37 @@ public class IntersceneLma {
final double [] scene_atr = new double[3]; final double [] scene_atr = new double[3];
final double [] reference_xyz = new double[3]; final double [] reference_xyz = new double[3];
final double [] reference_atr = new double[3]; final double [] reference_atr = new double[3];
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) { // pose values for pose_vectors: every call (cheap)
ers_ref.ers_watr_center_dt[i] = full_vector[ErsCorrection.DP_DVAZ + i];
ers_ref.ers_wxyz_center_dt[i] = full_vector[ErsCorrection.DP_DVX + i];
ers_scene.ers_watr_center_dt[i] = full_vector[ErsCorrection.DP_DSVAZ + i];
ers_scene.ers_wxyz_center_dt[i] = full_vector[ErsCorrection.DP_DSVX + i];
reference_atr[i] = full_vector[ErsCorrection.DP_DAZ + i]; reference_atr[i] = full_vector[ErsCorrection.DP_DAZ + i];
reference_xyz[i] = full_vector[ErsCorrection.DP_DX + i]; reference_xyz[i] = full_vector[ErsCorrection.DP_DX + i];
scene_atr[i] = full_vector[ErsCorrection.DP_DSAZ + i]; scene_atr[i] = full_vector[ErsCorrection.DP_DSAZ + i];
scene_xyz[i] = full_vector[ErsCorrection.DP_DSX + i]; scene_xyz[i] = full_vector[ErsCorrection.DP_DSX + i];
} }
ers_scene.setupERS(); // Rung C2: reference camera + centers = per-SEQUENCE (virtual center is
ers_ref.setupERS(); // static); scene camera = per-SCENE (ERS rates constant across cycles;
if (poseFloatReference == null) poseFloatReference = IntersceneLmaFloat.Camera.capture(ers_ref); // only the 3 angles change and they travel in pose_vectors). setupERS +
if (poseFloatScene == null) poseFloatScene = IntersceneLmaFloat.Camera.capture(ers_scene); // Camera.capture run once per level, and the provider gets null for
if (poseFloatCenters == null) poseFloatCenters = IntersceneLmaFloat.flattenCenters(macrotile_centers); // groups already resident. By Claude on 07/17/2026.
final boolean newSequence = (poseSeqKey != ers_ref);
if (newSequence) {
for (int i = 0; i < 3; i++) {
ers_ref.ers_watr_center_dt[i] = full_vector[ErsCorrection.DP_DVAZ + i];
ers_ref.ers_wxyz_center_dt[i] = full_vector[ErsCorrection.DP_DVX + i];
}
ers_ref.setupERS();
poseSeqRefCamera = IntersceneLmaFloat.Camera.capture(ers_ref);
poseSeqCenters = IntersceneLmaFloat.flattenCenters(macrotile_centers);
poseSeqKey = ers_ref;
}
final boolean newScene = (poseResidentSceneCamera == null);
if (newScene) {
for (int i = 0; i < 3; i++) {
ers_scene.ers_watr_center_dt[i] = full_vector[ErsCorrection.DP_DSVAZ + i];
ers_scene.ers_wxyz_center_dt[i] = full_vector[ErsCorrection.DP_DSVX + i];
}
ers_scene.setupERS();
poseResidentSceneCamera = IntersceneLmaFloat.Camera.capture(ers_scene);
}
final float [] pull = new float [IntersceneLmaFloat.NUM_PARAMS]; final float [] pull = new float [IntersceneLmaFloat.NUM_PARAMS];
final float [] regw = new float [IntersceneLmaFloat.NUM_PARAMS]; final float [] regw = new float [IntersceneLmaFloat.NUM_PARAMS];
for (int par = 0; par < IntersceneLmaFloat.NUM_PARAMS; par++) { for (int par = 0; par < IntersceneLmaFloat.NUM_PARAMS; par++) {
...@@ -2082,10 +2120,12 @@ public class IntersceneLma { ...@@ -2082,10 +2120,12 @@ public class IntersceneLma {
regw[par] = (float) param_regweights[par_indices[par]]; regw[par] = (float) param_regweights[par_indices[par]];
} }
final IntersceneLmaFloat.PrepareResidentResult result = poseLmaPrepareProvider.calculate( final IntersceneLmaFloat.PrepareResidentResult result = poseLmaPrepareProvider.calculate(
poseFloatReference, poseFloatScene, newSequence ? poseSeqRefCamera : null,
newScene ? poseResidentSceneCamera : null,
IntersceneLmaFloat.toFloat3(reference_xyz), IntersceneLmaFloat.toFloat3(reference_atr), IntersceneLmaFloat.toFloat3(reference_xyz), IntersceneLmaFloat.toFloat3(reference_atr),
IntersceneLmaFloat.toFloat3(scene_xyz), IntersceneLmaFloat.toFloat3(scene_atr), IntersceneLmaFloat.toFloat3(scene_xyz), IntersceneLmaFloat.toFloat3(scene_atr),
poseFloatCenters, (eigen_src != null), newSequence ? poseSeqCenters : null,
macrotile_centers.length, (eigen_src != null),
(float) eig_min_sqrt, (float) eig_max_sqrt, (float) eig_min_sqrt, (float) eig_max_sqrt,
(float) min_confidence, same_weights, pull, regw, capture); (float) min_confidence, same_weights, pull, regw, capture);
if ((result == null) || !result.valid) return false; if ((result == null) || !result.valid) return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment