Commit Graph
76 Commits
Author SHA1 Message Date
西风逍遥游 5daf089955 feat(decal): P0 screen-space decal framework with albedo blending
Adds the box-projected decal layer between the G-buffer and forward passes: RenderControl decal feature (implies gbuffer); Vulkan DecalLayer resources + premultiplied-alpha pass + unit-box projection shader reading hwDepth/GBuffer normal; mesh3d bindings 8/9/10 with albedo over-blend before lighting (clustered + GPU-driven bound too); RenderSystem3D DecalExtraDrawer hook; new decal module (L4, script Decal) with DecalManager spawn/remove/quotas/lifetime fade; compile_decal_shaders.py; tests incl. GPU smoke (red decal on white plane).
2026-08-23 00:03:19 +08:00
西风逍遥游 1046c57887 ci: extend binding doc gate from new chapters to all modules
scripts/check_bindings.py now treats pre-existing doc gaps as registered
debt: scripts/check_bindings_gaps.txt (module:binding, regenerated via
--write-gaps, 857 entries) turns them into warnings, while any NEW bound
name missing from its doc chapter fails the check. make check/bindings and
the CI layering job now run the full --strict check instead of the ten
newly-authored chapters, so docs cannot silently drift from bindings
anywhere in the tree.
2026-08-22 11:55:35 +08:00
西风逍遥游 7def184397 merge: integrate origin/dev (webgpu-progress, quality-gates) into codex/0.2.0-prep
Resolved conflicts:
- test/*: keep the shared Fixtures.h migration (drop the per-file
  openGfxWindow copies that dev still had).
- vulkan/Graphics.cpp: keep dev's extName loop variable rename AND the
  headless set_headless() line.

Local win32-debug build + headless/sampler/mocks/binding tests pass after
forcing a rebuild of EVProcgen (stale object from the pre-merge tree caused
a duplicate PbrTextureSet::destroy symbol).
2026-08-22 09:37:37 +08:00
西风逍遥游 2788021701 Merge pull request #169 from EVEngine/codex/webgpu-progress
WebGPU: playground, SSAO, clustered lighting, voxel AO & custom shaders
2026-08-22 09:29:54 +08:00
西风逍遥游 e82887921a feat(quality): script-binding self-check (source vs docs) + runtime binding smoke
- scripts/check_bindings.py: scans every addFunc/addVar in src/modules and
  greps the matching docs/usr/modules chapter. Missing names are warnings by
  default (large pre-existing doc debt); --strict + --modules turn them into
  CI failures. Wired as make check/bindings and a step in the CI layering
  job for the ten newly-authored chapters (avatar, buildingfx, camera,
  database, dialogue, grid, housegen, sceneloader, stylize, virtualgeometry),
  so those chapters cannot silently drift from the bindings.
- test/binding_selfcheck.cpp: builds a script VM with every module exposed,
  constructs the light modules and asserts curated hot bindings exist
  (eve.reflect itself is covered by the existing ReflectScript test).
2026-08-22 08:35:24 +08:00
西风逍遥游 811eff1c3a ci(quality): warnings-as-errors gate, sanitizers, smoke, Python lint/tests
- EVENGINE_ENABLE_STRICT_WARNINGS option: MSVC /W4 /WX, GCC/Clang
  -Wall -Wextra -Werror, with documented noise suppressions and
  -isystem/-external:I for third-party headers; enabled on the
  Windows/Linux debug CI jobs.
- Fix warnings across engine, modules and tests exposed by the gate,
  including real bugs (incomplete-type deletes, Timespan microsecond
  overflow, overload hiding, enum switch gaps, dead code).
- Add Linux ASan+UBSan job, example smoke step, python-tools test
  job, ruff config (scripts+tools), weekly Linux coverage job and a
  CodeQL workflow.
2026-08-22 02:27:37 +08:00
西风逍遥游 87b2731fb6 Merge remote-tracking branch 'origin/dev' into codex/examples-devx-ai-native
# Conflicts:
#	Makefile
2026-08-22 00:50:23 +08:00
西风逍遥游 7228277392 fix(ci): make DevLab MCP test robust to slow runners
CI hit a python socket timeout connecting to the embedded MCP server,
likely because the sed-triggered hot reload delayed frame-loop MCP pumping
on a slower runner. Bump the socket timeout to 30s, retry eve_status, and
dump the eve log tail on failure so future CI failures carry the actual
engine output.
2026-08-22 00:46:45 +08:00
西风逍遥游 8af30cb1d3 docs: resolve merge with dev, keep gallery link in user guide 2026-08-21 22:50:38 +08:00
西风逍遥游 e3ad78d30c docs: add example render gallery with real engine captures
Render 14 examples with the prebuilt eve host and capture the actual
swapchain frame via gfx.saveFramePng (capture_root.nut wrapper), then
publish the PNGs under docs/images/examples with a gallery README and a
link from the user guide.

Adds scripts/capture_example.ps1 + scripts/capture_root.nut for
regenerating the captures on any example.
2026-08-21 22:48:40 +08:00
西风逍遥游 ef83a2eb89 Merge remote-tracking branch 'origin/dev' into codex/examples-devx-ai-native 2026-08-21 22:28:12 +08:00
西风逍遥游 b93247cf5f fix(ci): verify DevLab via MCP instead of grepping captured print
With --debug the engine routes Squirrel print() into the DevTools console,
so 'DevTools attached' never reaches stdout/stderr and the log-grep test
always timed out. The test now starts eve with --mcp-port, waits for the
stderr 'MCP listening' line, and verifies attachment + hot reload through
the embedded MCP server (eve_status attached + eve_eval lab.reloads).
2026-08-21 22:03:31 +08:00
西风逍遥游 27e08963e2 fix(filesystem): sq_file handle never stored _path/_data
sq_newslot(-3) expects a [table, key, value] three-level stack; the code
pushed only the value, so the slot write silently targeted the native
frame's mode argument (a string, not a table) and was skipped. Handles
therefore had methods but empty _path/_data, making read()/getSize()
throw 'file not readable' on every platform where the stack layout
did not accidentally alias the table.

Fix cardgame's ui.sameLine() calls to pass an id (the binding requires
one), and make the example smoke failure output print non-frame-error
lines so future CI failures carry the real root cause instead of being
buried under per-frame error spam.
2026-08-21 21:39:41 +08:00
西风逍遥游 453d33387f Merge remote-tracking branch 'origin/dev' into codex/gpu-driven-rendering
# Conflicts:
#	AGENTS.md
#	external/VKBuilder
#	src/modules/graphics/Graphics.h
#	src/modules/graphics/RenderControl.cpp
#	src/modules/graphics/RenderSystem3D.cpp
#	src/modules/graphics/vulkan/Graphics.cpp
#	src/modules/graphics/vulkan/Graphics.h
2026-08-21 20:45:42 +08:00
西风逍遥游 63445728e1 feat(webgpu): online playground with live script hot-reload
Adds a self-contained browser playground (editor + canvas + console + REPL)
around the Emscripten WebGPU build, plus the engine fixes required to render:
- JS<->Squirrel bridge (apply/eval/read/pause) and Emscripten 6 exports
- soft hot-reload via load.nut handle_change with __pg state preservation
- fix Uint16 index buffer byte sizes in SetIndexBuffer calls
- fix dangling GbufferSlot/SceneColorSlot gpuHandle pointers (std::move bug)
- fallback shadow depth texture when no shadow map is configured
- fix WGSL syntax (mod/ivec2) and default shadow sampler maxAnisotropy
- serve_webgpu.py COOP/COEP server and playground docs/demos/assets
2026-08-21 20:35:20 +08:00
西风逍遥游 96a96de58d fix(examples): scene-ecs addNode arity; smoke prints full failing log tail
scene.addNode(id, name) requires both params; the example passed one.
smoke_examples.sh now dumps the last 25 lines of a failing example's log
so CI failures carry the full error context.
2026-08-21 19:55:37 +08:00
西风逍遥游 f7962f43fe feat(examples): developer-experience and AI-native showcase examples
- devlab: flagship --debug example (console/snapshot/AI panel/pause/hot
  reload/error slice), make devlab target with RUN_ARGS support
- ai-game: agent-drivable live game + agent_demo.py (pause/read/mutate/
  verify/snapshot/restore/screenshot loop)
- ai-editor: headless eve mcp editor host demo (JSON View + ViewModel MVVM)
- examples: fill all missing READMEs + config.nut, add examples/ index
- load.nut: add key_just_pressed/clampf/persist helpers; dedupe 19 examples
- rpg/cardgame: move JSON definitions to data files
- fix eve mcp crash: ModuleManager::requireAll() instantiates modules in
  the headless host (IEditorHost etc. were null)
- graphics: actionable screenshot error when readback was just enabled
- CI: smoke all examples (devlab with --debug) + DevLab hot-reload test

Fixes surfaced by the new CI smoke (examples had never been smoke-tested):
- scene_director kit: camera slot doubled as function + instance and was
  nulled by reset(); move the live Camera3D into cameraObj
- readTextFile used non-existent readn()/len(); use file.read()
  (rpg/cardgame/hex-levels)
- daynight used non-existent keyboard.wasPressed() -> key_just_pressed
- outline passed ints to float-only drawSolidRect; linear-structures
  slider passed an int value
- scene-ecs beginNode() requires (id, name); ai-stage guarded compilestring
- smoke_examples.sh: timeout -k 3 so SIGTERM-ignoring hosts cannot hang CI
2026-08-21 19:18:52 +08:00
西风逍遥游 eae8cfbc38 feat(graphics): stage 3 - VirtualGeometry hardware-raster integration
Virtual-geometry assets now render through the main GPU-driven frame instead of
the standalone software-raster experiment:

- Shared VG scene in vulkan::Graphics: pooled positions/triangles/clusters +
  per-cluster asset ids + per-slot visible list / indirect commands / asset
  models + materials. Meshes attach an asset via gpuDrivenVgAttachToMesh;
  GpuMeshRecord.vgAssetId routes them out of the instance chain.
- vg_main_cull.comp runs in the main frame's compute section (frustum + HZB
  against the per-asset model) and emits per-cluster VkDrawIndirectCommand
  (vertexCount = triCount*3, firstInstance = cluster id).
- Hardware raster: mesh3d_gbuffer_vgvis draws clusters with NO vertex input -
  gl_InstanceIndex = cluster, gl_VertexIndex = triangle corner, positions from
  the cluster stream; face normals computed from world edges; writes the same
  visID/visBary attachments (bit31 marks VG clusters).
- resolve_vis.frag decodes VG clusters: asset -> material, interpolates from
  the cluster stream, flat-tint shading via the shared PBR core, writes
  gl_FragDepth so later transparent draws depth-test correctly.
- gpu_emit.comp additionally writes non-indexed VkDrawIndirectCommand per
  bucket (the 20-byte indexed layout's firstInstance sits at offset 16, which
  vkCmdDrawIndirect (16-byte commands) ignores - this was the vis pass showing
  only instance 0). The vis pass now draws from that command stream.
- All per-frame bindless updates (vis samplers 15/16, VG bindings 26-29) moved
  BEFORE the set is bound to the recording command buffer (no UPDATE_AFTER_BIND;
  updating a bound set invalidates the CB - caught by validation).
- drawIndirectCount Vulkan 1.2 feature enabled at device creation; the VG
  count buffer carries VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT.
- RenderControl gains the "visResolve" feature flag (the stage-3 resolve path
  was previously enabled via an unknown flag that setFeature silently dropped).

Verified: GpuDriven.visResolveParity now genuinely exercises the resolve path
(maxDelta = 0.0 vs forward); GpuDriven.vgVisResolve renders a sphere's clusters
through the main frame (9 visible after frustum+HZB, tint-correct center,
frustum-culled to 0 behind the camera); 19 render tests + 3x suite repeat pass;
validation shows no new VUIDs.
2026-08-21 19:04:13 +08:00
西风逍遥游 f7d526d528 feat(graphics): stage 3 - visibility buffer + fullscreen resolve + vertex pool
Opaque GPU-driven instances now render through a deferred-style path under the
new "visResolve" render-control flag (1x scene pass):

- GBuffer gains visID (R32G32UI: instance + pooled triangle base) and visBary
  (R16G16F) attachments plus a vis render-pass variant and pipeline.
- The vis pass draws the cull chain's indirect commands with NO vertex input:
  the vertex shader fetches position/normal/uv from new pooled buffers via
  gl_VertexIndex (non-indexed draw reuses the same indirect commands), which
  also makes the per-vertex barycentric constants exact (gl_VertexIndex % 3).
  Triangle ids are computed in the vertex stage and passed flat, avoiding
  gl_PrimitiveID in the fragment (which would require the SPIR-V Geometry
  capability / geometryShader feature).
- resolve_vis.frag runs as a fullscreen triangle inside the scene color pass:
  it reconstructs world pos / normal / uv from the pool using the barycentrics,
  shades with the shared PBR code and writes the opaque depth (gl_FragDepth),
  so later hair/transparent draws depth-test correctly.
- New vertex pool (positions/normals/uvs as vec4/vec4/vec2 SSBO arrays +
  u32 index pool, host-visible, grow-by-2x with waitIdle); meshes are pooled
  lazily at registerMeshRecord and GpuMeshRecord.vertexOffset/indexOffset now
  point into the pool. Bindless set1 gains bindings 15/16 (vis samplers) and
  18-21 (pool buffers), all rewritten per slot/frame following the safe-point
  rule from 8f156a6.
- pbr_shade.glsl extracts the GPU-driven PBR/CSM/cloud/env shading so the
  forward path and the resolve share one source of truth.

Verified: GpuDriven.visResolveParity passes with maxDelta=0.0 vs the forward
path (same cull, same pixels); full GpuDriven + RenderSystem3D/Shadow3D/
Lighting3D suites pass; validation shows no new VUIDs (the SPIR-V Geometry
capability error from gl_PrimitiveID was removed by the flat-triangle-base
change).
2026-08-21 17:22:40 +08:00
西风逍遥游 d82d246465 gpu-driven stage 2: GPU frustum/HZB cull + GPU-written indirect draws
Add the stage-2 compute chain to the main frame:
- ComputePass wrapper + compile script for compute SPIR-V (hzb_build /
  gpu_cull / gpu_emit); bindless set extended with cull UBO, visible flags,
  compacted instances, indirect commands, HZB buffer and GBuffer depth.
- HZB: R32F max-downsampled mip chain per frame slot built from the
  GBuffer depth after the GBuffer pass (buffer-based; offsets header at slot
  start). Same-frame self-occlusion handled by testing the bounding sphere's
  FRONT depth, and near-zero depth (uninitialized/corner garbage) never
  occludes.
- Cull: per-instance Gribb-Hartmann frustum test + HZB occlusion test, flags
  written per instance; emit compacts visible instances per CPU-provided
  bucket layout and fills per-bucket indirect commands with atomic counters.
- Frame wiring: begin3DFrame defers opening the scene color pass when the
  cull chain is live, so the compute section records before the opaque
  draws; RenderSystem3D uploads sorted instances, runs cull+emit, opens the
  pass and draws with GPU-written commands (per-bucket, empty buckets no-op).
  Fallback to stage 1 when compute caps are missing. gpuDriven now forces
  the GBuffer pass (HZB source).
- Known limitation: HZB is built from the same-frame GBuffer, so objects
  already in the GBuffer cannot be occlusion-culled until the GBuffer itself
  is culled (stage 3 vis buffer); the chain is verified with frustum culling
  (2 of 5 instances culled) and pixel parity.

Tests: GpuDriven.opaqueForwardCullParity (5 spheres, 2 outside frustum ->
3 visible / 3 non-empty buckets, pixel parity < 0.03); all 6 GpuDriven
tests pass (integrated GPU; the AMD driver intermittently crashes at
vkCreateImage during init - environmental).
2026-08-21 15:09:39 +08:00
西风逍遥游 95b1491e86 feat(graphics): GPU-driven phase 1 - CPU-built indirect draws for opaque forward
- Shared GPU-driven types (GpuDrivenTypes.h) in the backend-independent
  graphics namespace; IndirectBuilder (pure CPU) sorts instances by
  (pipeline, material, mesh) and merges buckets into GpuIndirectCommand.
- Base Graphics gains a capability-gated seam (supportsGpuDriven3D,
  gpuDrivenMeshRecord/MaterialRecord, gpuDrivenSubmitOpaque); WebGPU keeps
  the default false.
- Vulkan backend: mesh3d_gpudriven vert/frag (instance + bindless textures +
  material table, mirroring mesh3d PBR/CSM/IBL shading), a dedicated pipeline
  with a firstInstance push constant, per-frame arena upload of the sorted
  instance buffer + commands, and per-bucket vkCmdDrawIndexedIndirect.
- Bindless set1 uses fixed-size descriptor arrays + dynamic indexing instead
  of nonuniform() because this toolchain's glslc lacks
  GL_EXT_nonuniform_qualifier; indices are uniform per bucket (one material
  per indirect draw), which is spec-legal. Caps requirements updated to
  match (drops runtime descriptor arrays / non-uniform indexing).
- RenderControl feature 'gpuDriven' (default OFF; opt-in until runtime
  verified). RenderSystem3D collects opaque instances when enabled and
  eligible (default camera, Material-driven, no custom shader, no clustered);
  any ineligible item falls back to the legacy per-draw path.
- Tests: IndirectBuilder merging/stable-order/pipeline-separation (CPU).
  GPU-driven runtime tests (GpuDriven.*) remain pending driver recovery.

Rendering is unchanged by default (feature off).
2026-08-20 21:30:54 +08:00
西风逍遥游 34d1fdb63b refactor(modules): clear remaining back-edges and split the largest TUs (#127)
* chore(ci): add clang-format gate, CODEOWNERS and agent collaboration rules

* refactor(modules): clear remaining back-edges and split the largest TUs

Three known dependency back-edges are gone (module_depgraph.py KNOWN_BACK_EDGES
is now empty; --check passes with 0 violations, 0 cycles):

- window -> graphics: window queries the new IWindowSurfaceHost capability
  (common/WindowSurfaceHost.h) instead of holding a Graphics pointer;
  Window::setGraphics was removed and all call sites updated.
- window -> image: Window::setIcon was replaced by setIconRGBA(const uint8_t*,
  w, h); the window no longer decodes ImageData.
- scene -> graphics: pickScreenAt / collectFrustumIdsAt implementations moved
  to graphics/ScenePicking.cpp (graphics -> scene is a legal downward edge);
  scene now depends only on spatial.

TU splits (pure moves, verified identical method sets and brace balance):

- vulkan/Graphics.cpp (5118 lines) -> Graphics.cpp (lifecycle), GraphicsPipeline,
  Graphics2D, Graphics3D, GraphicsMesh + shared GraphicsInternal.h.
- scene/Scene.cpp -> Scene.cpp (script layer / host lifecycle / serialization)
  + SceneNodes.cpp + shared SceneInternal.h.

Verified with a real build (MSVC 19.51, prebuilt third-party): full build green;
window.* and Scene.* suites pass, including scene picking/culling and GPU cases.

* refactor(graphics): narrow Graphics interfaces and clear public-header leaks

Step 4 — interface segregation:
- New lean interfaces: IGraphics2D, IGraphics3D, IResourceFactory, IPostFX
  (pure virtuals, forward-declared types only; graphics/Color.h extracted from
  Canvas.h so modules that only need the color type stop pulling Canvas.h).
- Graphics now implements all four facets; consumers can depend on the narrow
  interface they use instead of the 129-method god class.
- Migrated voxel (VoxelWorld::drawVisible -> IGraphics3D*) and model3d
  (ModelRenderer::buildRenderable(s) -> IResourceFactory&).
- Graphics.h slims from 24 sub-header includes to a handful of small type
  headers + forward declarations; the destructor moved out-of-line so
  unique_ptr effect members are destroyed where types are complete.

Step 5 — header leaks (module_depgraph.py '*' marks: 14 -> 7):
- map/TileLayer.h, particles/ParticleEmitter.h, avatar/AvatarInstance.h,
  animation/SpineAnim.h, map/TileSystem.h, model3d/ModelData.h,
  model3d/ModelRenderer.h, audio/Audio.h + Source.h, image/ImageData.h +
  Image.h, dialogue/Dialogue.h, procgen Palette/OutputSpec/TextureRecipe/
  PbrMaterial -> forward declarations, includes moved to .cpp.
- voxel/VoxelWorld.h: terrain sampler Pimpl'd (unique_ptr + out-of-line
  destructor), removing the procgen header dependency.
- gpgpu/vulkan backend headers stop pulling graphics/vulkan/Graphics.h.
- Remaining '*' marks are deliberate: tiny POD/enum headers (GridConfig,
  MapObject, BlendMode, Color), an internal backend header
  (GraphicsInternal.h -> filesystem), and lean interface references.

Verified with a full clean build (MSVC) and tests: window/Scene/voxel/
RenderSystem/Quad/shader/TextureSampler/resourceLifetime pass; broad suite
only shows the pre-existing PHYSFS-init filesystem-environment failures.

* feat(resources): revive ResourceManager as unified IAssetReloader-backed cache

* fix(resources): leak ResourceManager singleton to avoid exit-time teardown crashes

Cached CPU resources may own third-party handles (FreeType faces, Assimp
scenes, image decode handlers) whose libraries are torn down at process
exit in an unspecified TU order; destroying cached entries from the
singleton destructor can segfault at exit (seen on CI Windows in
model3d.materialApi.objMtl). Keep the singleton alive until OS reclaim;
explicit unload()/clear() still release entries during the run.

* refactor(devtools): consume business modules through capability interfaces

DevTools / cmdline no longer include business-module headers, so trimming
scene / physics / procgen / particles / audio / ui / graphics no longer
requires disabling devtools, and devtools can be switched off with
-DEVENGINE_MODULE_DEVTOOLS=OFF.

New capability interfaces in common/:
- ISceneQuery (scene) - host/node inspection + mutation + transform sync
- IRenderCapture (graphics) - render status, PNG capture, camera control,
  visible-entity snapshot, entity-ID mask, G-buffer PNGs
- IPhysicsQuery (physics) - 2D world lifecycle + ray casts
- IProcgenQuery (procgen) - recipe listing, map/mesh generation
- IParticlesQuery (particles) - emitter status + one-shot emit
- IAudioQuery (audio) - volume / stop-all
- IEditorHost (ui) - declarative editor host (used by cmdline too)

Providers register in their module constructors. DevTools rewires McpServer
(render/scene/procgen/physics/particles/audio/host tools), SceneInspect
(now delegates to ISceneQuery + IRenderCapture) and RenderVision (uses
IRenderCapture::capturePngDataUrl); cmdline/Mcp.cpp uses IEditorHost.

manifest: devtools DEPS graphics scene physics procgen particles audio ui
image event filesystem -> event; cmdline DEPS filesystem ui -> filesystem.

Verified: full build green; devtools.mcp.* tests pass; broad suite shows
only the pre-existing PHYSFS-init filesystem-environment failures.

* style: apply clang-format to changed lines after dev merge

* fix(webgpu): include RenderControl/TextureSampler explicitly after Graphics.h slimming

* fix(webgpu): provide newFont/print stubs to satisfy IGraphics2D/IResourceFactory vtables

* fix(common): make ProcgenQuery.h self-sufficient (cstdint/utility for GCC)
2026-08-20 05:53:33 +08:00
西风逍遥游 a195d4781f Merge branch 'dev' into codex/release-flow-sdk 2026-08-19 23:40:12 +08:00
西风逍遥游 9c058b4ba8 Merge pull request #128 from EVEngine/codex/review-fixes-2026-08-19
refactor: code-review fixes — build wiring, graphics ownership, module lifecycle
2026-08-19 23:37:38 +08:00
西风逍遥游 adf32a4e78 test: re-enable hair/runtime suites, add resource-lifetime and tooling tests
Re-add test/hair.cpp and test/runtime.cpp (fixing the missing zeroerr include and enum comparisons), add graphics.resourceLifetime tests for the new release APIs, a test-source manifest check, module declared-layer check with unit tests, and a raw-string-literal regression test.
2026-08-19 22:44:53 +08:00
西风逍遥游 ee956e356d build: dedupe third-party/system wiring, support all build types, pin deps
Centralize the engine include/link usage in an eve_engine_includes INTERFACE target and the per-platform system library list in cmake/system_libraries.cmake (no more duplicated lists or global include/link dirs). Accept RelWithDebInfo/MinSizeRel, apply the medialoader patch via ExternalProject PATCH_COMMAND instead of mutating the checkout at configure time, pin the third-party aggregate and Dawn to fixed commits, derive the SDK header list from the module manifest, and add deprecation notices for the third-party directory aliases. Also fix message typos and sync test-count docs.
2026-08-19 22:44:51 +08:00
西风逍遥游 38b70171fb fix(release): make sync-docs PR-based and release-aware
- compute main's changes since the merge-base with dev instead of per-commit
  cherry-picks, so merge/squash/rebase doc merges all work and dev-only work
  is never touched;
- allow release version touchpoints (RELEASE_PATHS) in the non-doc gate, fixing
  the spurious failure every sync-docs run after a non-ff release merge;
- sync by copying doc paths from main onto sync-docs/from-main and opening a
  PR to dev (no direct push), matching the PR-only branch model;
- docs updated in 发布流程.md and the release-branch-model spec.
2026-08-19 22:07:42 +08:00
西风逍遥游 b08657ab67 feat(sdk): package licenses, auto-export module headers, add plugin/APK smoke tests, checksums and branch cleanup
- install_sdk.cmake: export headers for exactly the modules the build enabled
  (EVE_ENABLED_MODULES from cmake/module_manifest.cmake) instead of a stale
  whitelist; package engine + vendored third-party licenses under
  share/eve/licenses/.
- test-sdk.sh: hard-gate native C++ plugin compile (find_package(EVEngine) +
  add_eve_plugin) on win32/linux/macosx; android now assembles an APK from the
  SDK template (gradlew assembleDebug) instead of skipping.
- sdk-release.yml: run the android APK smoke; publish generates SHA256SUMS,
  verifies every zip's share/eve/VERSION against the tag, uploads SHA256SUMS
  with the SDKs, and (best-effort) attests build provenance.
- release.py: new cleanup-branches subcommand deletes merged vX.Y.Z /
  promote/* / rebase/* branches (tags and main/dev are never touched);
  new cleanup-branches.yml runs it weekly + on demand.
- docs: SDK packaging and branch cleanup sections in 发布流程.md and the
  release-branch-model spec.
2026-08-19 21:57:52 +08:00
西风逍遥游 703f1fb7a5 ci(release): fix ambiguous refspecs, add version consistency and SDK hardening
- release.py: use explicit refs/heads + refs/tags refspecs everywhere (short
  refspecs are ambiguous when the release branch and tag share a name, and git
  refuses to push them); rebase dev onto the branch's -dev write-back instead
  of the official tag; add a real-git integration test suite.
- version single-sourcing: fix config.h.in PATCH macro bug and include -dev;
  derive Android versionCode; sync required version touchpoints in start and
  enforce them via check-versions in CI.
- SDK: exact version assertions in test-sdk.sh, publish-time VERSION cross-check.
- workflows: converge toolchain versions to repo vars, SHA-pin actions, add
  Dependabot config.
2026-08-19 21:50:02 +08:00
西风逍遥游 138072f513 feat(release): open PRs instead of pushing main and dest
finish no longer updates main or force-pushes dest. It opens promote/vX.X.X to main and rebase/vX.X.X to dest for a human merge, and posts the main-gate check so GITHUB_TOKEN PRs stay mergeable.
2026-08-19 20:53:05 +08:00
西风逍遥游 ede37ca479 refactor: update documentation generation process and remove obsolete files
- Updated `.gitignore` to reflect changes in documentation generation commands.
- Modified `CMakeLists.txt` to set a new version format and streamline documentation handling by adding a subdirectory for docs.
- Removed the outdated `Doxyfile` and replaced it with a new configuration in `docs/Doxyfile.in`.
- Updated README files to reference the new documentation structure and generation process.
- Deleted unused `imgui.ini` and API conventions documentation file to clean up the repository.
2026-08-19 18:00:07 +08:00
西风逍遥游 6f3552a7c2 Merge pull request #116 from EVEngine/codex/voxel-engine-gap-improvements
feat(voxel): close feature/perf gap vs mainstream voxel engines
2026-08-19 07:43:01 +08:00
西风逍遥游 e98f125f21 feat(voxel): close feature/perf gap vs mainstream voxel engines
- Cross-chunk seam culling via GreedyMesher::ChunkSampler; border edits now
  invalidate the adjacent chunk; air writes no longer allocate chunks
- selectVisible meshes only after range/frustum culling
- DDA voxel raycast (CPU + script getters)
- Parallel remeshDirty(maxThreads) with serial fallback; output equals serial
- Vertex AO: Minecraft-style 4-corner AO packed 2bit x 4, Vulkan instancing +
  voxel_rect shaders (SPIR-V .inc regenerated); WebGPU accepts params (TODO)
- Persistence: serializeWorld/deserializeWorld (EVVX LE) + saveWorld/loadWorld;
  unloadChunksOutside + streamAround for player-centered streaming
- Terrain: reuse procgen::TerrainSampler (no new module), setTerrainParams +
  terrainHeightAt; script setTerrain/streamAround
- CPU tests + gap-analysis/module/user docs; local MSVC harness 1741 checks pass
2026-08-19 04:13:21 +08:00
Cursor Agentand西风逍遥游 d80df444aa refactor(scene): register link kinds instead of hard-coding them
A scene link keeps an external object in step with the node it hangs off. The
kinds were a closed enum with a switch in TransformSystem, so scene had to
include graphics, physics and audio to do the casts, and no other module could
ever attach to the tree without editing SceneHost.h -- particles, voxel,
spritestack, avatar and weather all had to stay outside it.

Kinds are registered now (scene/SceneLink.h). The module owning the target type
supplies pushWorld / pullWorld / alive, keeps the casts on its own side where
the type is complete, and scene never learns what a Renderable3D is. Dispatch is
a function-pointer table rather than virtual calls, since link sync runs for
every dirty node every frame.

The six typed helpers (linkRenderable2D and friends) stay as conveniences and
now resolve their kind by name, so they return false rather than crash when the
module that registers it was trimmed out. The script API already named kinds
with strings, which is exactly the registry key, so it is unchanged.

Direction is now the right way round: graphics, physics and audio depend on
scene rather than scene on them, and scene drops from L5 to L1. What remains is
scene -> graphics from pickScreenAt / collectFrustumIdsAt, which take a Camera3D
and read its projection; that is recorded in the back-edge whitelist as the next
thing to move.

Each provider lives in a SceneLinks.cpp, sharing the basename so the three come
out of the build together when scene is disabled.

Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
2026-08-18 13:46:25 +00:00
Cursor Agentand西风逍遥游 f7aacbc4a9 refactor(event): let modules translate their own platform events
The SDL pump did the translation itself, so it had to know about keyboard,
joystick, touch, window, graphics, audio and ui: eight upward dependencies from
one of the engine's lowest modules, and the source of every remaining
dependency cycle.

Each module now registers an IPlatformEventSink for the events it owns and the
pump only dispatches. Key and text events move to keyboard/sdl, joystick and
game-controller events (including the hotplug device table) to joystick/sdl,
finger events to touch/sdl, resize and the mobile background/foreground surface
watch to window/sdl, the ImGui observer to ui, and Audio::pump to an
end-of-pump hook in audio. The pump keeps only quit and window-close, which are
about the event loop rather than any one module.

Sinks run in priority order -- observer, then surface, then input -- so ImGui
still sees events first and the window is resized before anything reads its
size. The mobile surface teardown keeps using SDL_AddEventWatch rather than the
poll path, since by the time SDL_PollEvent returns the native surface is gone;
the watch is now installed by the window module on its first pump.

Also removes exceptionIfInRenderPass, whose body has been commented out since
it was written and whose only remaining effect was a graphics include.

The engine dependency graph now has zero cycles, down from 26, and the back-edge
whitelist is down to 2 (window -> graphics, window -> image). Layering is also
right way up: event sits at L0 with the input modules above it at L1/L2.

Verified: unit tests for event/input/ui/audio/thread pass, and the example
smoke suite gives the same 19 pass / 9 fail as the pre-change baseline (those 9
fail on main too, from script API drift in the examples themselves).

Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
2026-08-18 13:46:04 +00:00
Cursor Agentand西风逍遥游 164e8c1b4c refactor(filesystem): dispatch hot reload instead of hard-coding asset kinds
HotReload knew what lived at every watched path: it included graphics to
refresh textures, particles to reload emitter configs and map to reload tile
layers. That made the engine's lowest-level module depend on three of its
highest, and it was the only reason filesystem sat in a dependency cycle.

Each module now registers an eve::caps::IAssetReloader for the assets it owns
and HotReload only routes paths. Behaviour is unchanged: automatic dispatch
still matches by extension, an explicit bind() still targets one kind and
ignores the extension, and the texture reloader runs at kTexture priority so
the GPU upload happens before emitters and tile layers re-bind to it.

The reloadable set now follows the linked module set, so a build without
particles simply has no particle reloader rather than a dangling reference.
Reload kinds also become extensible: a module or plugin can add one without
touching filesystem.

Back-edge whitelist 14 -> 11; the dependency graph is now acyclic apart from
the event pump.

(map.render.tilesContributeDepthY fails when run after the hotreload cases both
before and after this change -- pre-existing test-order state, not from here.)

Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
2026-08-18 13:46:04 +00:00
Cursor Agentand西风逍遥游 08679654e0 feat(common): add the capability registry, use it for GPU info and main-thread posts
Introduces eve::cap in common/Capability.h: a name-keyed registry where the
consumer owns the interface, the provider registers an implementation, and
neither includes the other. It generalises what common/RenderTrace.h already
does for the render tracer, and supports both a single provider (provide/query)
and many ordered ones (addListener/forEach), keyed by string so a provider
compiled into a plugin lands in the same slot as the host.

Two upward dependencies go away:

  system -> graphics   IGpuInfo. The Vulkan physical-device fields move into
                       graphics/vulkan/GpuInfoProvider.cpp, with a WebGPU
                       counterpart, so System.cpp loses both the graphics
                       include and its EVENGINE_WEBGPU branches.

  thread -> event      IMainThreadPost. postMain and submitPost now enqueue
                       through the capability. The interface makes explicit
                       what was previously only a comment in submitPost: the
                       submitting thread calls prepare() so the worker never
                       reaches the module registry.

Both now report an error when no provider is linked, rather than lazily
creating a module the build may not contain.

Step S3 of docs/dev/模块编排与裁剪架构.md; back-edge whitelist 16 -> 14.

Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
2026-08-18 13:46:04 +00:00
Cursor Agentand西风逍遥游 c4fd641115 docs: add module orchestration and trimming architecture analysis
Analyse how the 53 modules currently collaborate and why none of them can be
trimmed outside the hardcoded WASM axis, then lay out a target architecture and
a six-step route to per-module build options.

Adds scripts/module_depgraph.py, which produces the dependency graph, the
7-layer topological ordering and the cycle list the document cites. Its --check
mode fails on any back-edge outside the 16 known ones, so it doubles as the CI
guardrail for step S1.

Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
2026-08-18 13:46:04 +00:00
西风逍遥游 cff9bb4d0c tensor: AITemplate-style compile pipeline, gpgpu Sequence, mini-LLM demo and weight-only quantization
Refactor the tensor module around AITemplate-style static compilation:

- Optimizer: DCE, constant folding, elementwise chain fusion, matmul/conv
  bias+activation epilogue fusion, liveness-based static memory planning,
  topological group execution order.
- KernelGen: shape-baked GLSL per fused group; two-pass softmax/layernorm;
  shared-memory SDPA; naive + 16x16 tiled matmul templates.
- GpuBackend: arena buffer allocation per memory plan, matmul autotuning,
  single command-buffer submission via the new gpgpu::Sequence (uploads,
  dispatches and downloads recorded once per run, Kompute-style).
- shaderc in-process GLSL->SPIR-V on Windows (no glslc.exe dependency),
  with glslc spawn fallback.
- CPU reference kernels shared by eager and the compiled interpreter;
  no-Vulkan fallback keeps compiled graphs runnable headless.

Neural-network coverage: softmax/logsoftmax, layernorm/rmsnorm (with
weight/bias), gelu/silu, conv1d/conv2d, pool, embedding, concat/slice,
axis reduces, argmax, cast, fused SDPA (+masked), resize2d, batched
matmul, seeded random.

Weight-only quantization (activations stay fp32):
- fp16 (IEEE half), fp8 (e4m3), fp4 (e2m1), int8, int4 with per-group
  block scales (MXFP-style: scale = maxAbs / format max magnitude).
- Quantized weights capture into graph Const nodes; CPU interpreter
  dequantizes at materialization; GPU matmul/embedding kernels dequantize
  inline from packed uint buffers (naive matmul variant).
- TF::quantizeWeight API + script binding.

Mini-LLM validation (TinyStories-gpt2-3M, 8 layers d=64):
- test/tensor_llm.cpp builds the full GPT-2 graph from engine ops and
  matches numpy reference: probs within 3e-7, greedy generation 24/24
  identical (~100 ms/token CPU), compiled path exact.
- tensor.llm.quantizedDtypes: fp16/int8/fp8/int4 all keep 16/16 greedy
  top-1 (fp4 16/16 with proper block scaling), weights 27.6 MB -> 3.3-13 MB.
- scripts/export_tiny_gpt2.py converts a PyTorch .bin checkpoint (no torch
  dependency) plus GPT-2 tokenizer into engine assets + numpy reference.

Tests: gpgpu 8/8, tensor 31/31 (original suite) + tensor.llm.* + tensor.quant.*
Assets in test/assets/mini_llm are gitignored (regenerate via the script).
2026-08-18 17:42:38 +08:00
sunxfancy 788adcbb53 Merge remote-tracking branch 'origin/main' into feature/virtual-geometry-nanite
# Conflicts:
#	CMakeLists.txt
#	src/engine/CMakeLists.txt
#	src/modules/graphics/Graphics.cpp
#	src/modules/graphics/Graphics.h
2026-08-17 17:14:42 +08:00
西风逍遥游 fe7b68deb4 feat(spritestack): sprite-stacking pseudo-3D rendering 2026-08-17 13:58:03 +08:00
sunxfancy fed7c3ff11 Merge remote-tracking branch 'origin/main' into feature/virtual-geometry-nanite 2026-08-16 21:49:45 +08:00
sunxfancy 2f13169b68 feat(virtualgeometry): add Nanite-style virtualized geometry rendering
Add a virtualgeometry module implementing a Nanite-inspired virtualized
geometry pipeline on the Vulkan backend:

- Cluster DAG preprocess (CPU): greedy meshletization + QEM edge-collapse
  hierarchical LOD, with per-cluster bounding spheres and geometric error.
- GPU-driven culling (compute): frustum + screen-space-error LOD selection
  that emits exactly one cluster per DAG branch (no gaps/overlaps).
- Software cluster rasterizer (compute): fills a visibility buffer
  (packed depth<<16 | clusterId) via atomicMin.
- Visibility-buffer resolve (CPU readback + resolve shader reference).
- Module facade (VirtualGeometry / VirtualGeometryRenderer) reusing the
  gpgpu compute backend; LodSelection CPU reference for tests.
- 14 unit tests (CPU preprocess + LOD-transition sweep + GPU end-to-end),
  shader compile script, example, and design doc.
2026-08-16 21:49:40 +08:00
西风逍遥游 095556319e Merge branch 'main' into feature/waterfall-shader 2026-08-16 21:29:04 +08:00
sunxfancy 28458bd104 fix(graphics): precompile water shader to SPIR-V for cross-platform support
Water used newMeshShader (runtime glslc compile), which is unsupported on
Windows (compileGlslWithGlslc throws there), failing graphics.water.* tests in
the Windows CI job. Extract the water fragment to shaders/water.frag, compile
it to water_frag_spv.inc, and create the shader via newMeshShaderFromSpv so it
works on every platform. Add compile_graphics_water_shaders.py.
2026-08-16 20:20:48 +08:00
sunxfancy 9d860e2d66 Merge remote-tracking branch 'origin/main' into feature/water-shader
# Conflicts:
#	src/modules/graphics/Graphics.cpp
2026-08-16 19:47:03 +08:00
sunxfancy 23ce82dba4 Merge remote-tracking branch 'origin/main' into feature/waterfall-shader 2026-08-16 16:24:52 +08:00
sunxfancy d8bf6820b6 Merge remote-tracking branch 'origin/main' into feature/waterfall-shader 2026-08-16 15:57:31 +08:00
西风逍遥游 0dfc18c08f deps: own libraries in external/, third-party deps in third-party/
Move the user-maintained VKBuilder from the third-party aggregate into external/ (git submodule), and relocate the third-party DungeonTemplateLibrary and Box3D from external/ into the third-party aggregate (previously pushed to EVEngine/third-party). Update .gitmodules, include paths, DTL/box3d build wiring, and docs.
2026-08-16 13:34:12 +08:00
西风逍遥游 7e3b73db83 Merge branch 'main' of https://github.com/EVEngine/EVEngine 2026-08-16 13:06:34 +08:00