Repository navigation
Refuse consolidating a voxel or mesh layer as unsupported (#659) - #684
Merged
leonardoaraujosantos merged 3 commits intoOct 4, 2026
Merged
Conversation
clay_layer_consolidation_cost, clay_layer_consolidate(_cancellable) and clay_layer_consolidate_region checked only for a missing or protected layer, so a voxel or mesh layer fell through to the bake and answered CLAY_ERROR_INVALID_ARGUMENT "nothing to consolidate" -- the detail meant for an empty SDF layer. clay_layer_plan_region_merge planned an empty merge the commit would then refuse. find_consolidatable now resolves the layer for all five calls: NOT_FOUND, then CLAY_ERROR_UNSUPPORTED naming the representation, then (for the editing calls) the protection refusal, before any params are read or anything is sampled. An empty SDF layer still answers INVALID_ARGUMENT. clay_layer_consolidation_advice and _state keep answering a voxel or mesh layer, as advice has documented since 0.86.0. Folding the checks into one helper also brings clay_layer_consolidate_region from cognitive complexity 19 to 15. Documents the error contract in clay.h and docs/05, with an OpenSpec change modifying "Consolidation across the ABI". No ABI version change.
Every consolidating entry point on a voxel and a mesh layer must answer CLAY_ERROR_UNSUPPORTED, name the representation in clay_last_error and leave the undo depth unchanged; a locked grid is still unsupported, and the advice still answers "not advised". An empty SDF layer is the control and still answers INVALID_ARGUMENT "nothing to consolidate".
check_task_symbols failed: tasks.md still named require_sdf_layer, the helper's earlier name. It is find_consolidatable.
leonardoaraujosantos
deleted the
fix/659-consolidate-refuses-voxel-mesh
branch
October 4, 2026 07:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Consolidating a voxel or a mesh layer failed with
CLAY_ERROR_INVALID_ARGUMENTand the detail meant for an empty SDF layer:ClaySpaceDesktop showed that detail on
layer/optimizeover a grid layer, and artists read it as "already optimised". The real answer is "this only applies to SDF layers". A host could not tell "wrong kind of layer" from "nothing there yet" without first askingclay_document_layer_info.Root cause
clay_layer_consolidation_cost,clay_layer_consolidate_cancellable(andclay_layer_consolidatethrough it) andclay_layer_consolidate_regionchecked only for a missing or a protected layer, then went to the bake. The bake returns false for a layer with no SDF content (src/scene/consolidate.cpp), and that false maps to "nothing to consolidate" / "nothing to merge".clay_layer_plan_region_mergehad no check at all: it succeeded with a plan that absorbs nothing, for a merge the commit would then refuse.Fix
find_consolidatableinbindings/c/clay_c.cppnow resolves the layer for all five calls, in this order:CLAY_ERROR_NOT_FOUNDwhen the layer is missing.CLAY_ERROR_UNSUPPORTEDfor a voxel or a mesh layer.clay_last_errorreads "consolidation applies to SDF layers: layer N is a voxel layer" (or "a mesh layer"), the same wordingclay_document_instance_layeruses.CLAY_ERROR_INVALID_ARGUMENT.All of this runs before any params are read and before anything is sampled. Representation goes before protection on purpose: a locked grid would otherwise answer "locked" and send the artist to unlock a layer that can never be consolidated.
An empty SDF layer still answers
CLAY_ERROR_INVALID_ARGUMENT"nothing to consolidate", so the two cases stay distinct.clay_layer_plan_region_mergestill plans zero absorbed roots for an empty SDF layer.Deliberately not changed:
clay_layer_consolidation_adviceandclay_layer_consolidation_state.clay_layer_warp_cost_get's rule for a stack of mixed kinds, and an existing test asserts that.Folding the three checks into one helper (plus a small
read_optional_merge) also bringsclay_layer_consolidate_regionfrom cognitive complexity 19 to 15._cancellablegoes from 14 to 13. Measured with clang-tidyreadability-function-cognitive-complexity.Docs and spec
clay.hcomments on cost, consolidate,_cancellable,plan_region_mergeandconsolidate_regionlist the new error. The advice comment says why it is the exception.docs/05gets a paragraph in the consolidation-advice section.refuse-consolidating-a-voxel-or-mesh-layermodifies "Consolidation across the ABI". It repeats the two existing scenarios and adds "A voxel or mesh layer is refused as unsupported" and "An empty SDF layer still has nothing to consolidate".Regression test
In
tests/unit/test_c_consolidate.cpp:_cancellable(with a token),plan_region_mergeandconsolidate_region, and asserts:CLAY_ERROR_UNSUPPORTED;clay_last_error()names "voxel" or "mesh";UNSUPPORTED;_stateanswers 0.Proof it failed before: I ran the same test file against unfixed
origin/main(02d9672). The new case failed 24 assertions (12 per representation:1 == 7for cost, consolidate,_cancellableandconsolidate_region,0 == 7forplan_region_merge, and everylast_error_namescheck). The control and advice checks passed there, as intended. With the fix: 19/19 cases, 622/622 assertions.Verification
All on macOS,
cpu-onlypreset withCLAY_BUILD_TESTS=ON, exit codes checked directly:ctest: 10/10, including all four unit shards.check_c_abi.pyagainst the freshly builtlibclay_shared.dylib: OK.check_layering,check_kernel_dialect,check_licenses,check_doc_latencyandcheck_test_shards --binary: OK (3029 cases partitioned).openspec@1.12.0 validate --all --strict: 76/76.release_check.py --skip-slow: these rows PASS: version, configure, build, tests (11/11), parity, layering, dialect, licenses, task-symbols, bindings (pyclay imported), kernels, abi, openspec.deviceand fourhardware/*waivers. Those are release-time gates and are already stale onmain: the device gate last ran at 7f6cf38, and the hardware waivers trip oninclude/clay/eval/bake_volume.h, which this PR does not touch.-Werror(the manylinux job) cannot run on macOS. The added code is plainif/std::stringconcatenation with the assignment-in-condition parenthesised.ABI
No entry-point, struct, enumerator, format or version change. The ABI stays at 0.123.0. This is a behaviour change on an error path only:
CLAY_ERROR_UNSUPPORTEDwhere it used to getCLAY_ERROR_INVALID_ARGUMENT.clay_layer_plan_region_mergeon such a layer now fails instead of returning an empty plan.Closes #659