Skip to content

Honor instance counts without per-instance vertex attributes - #1888

Open
bkaradzic-microsoft wants to merge 5 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:pr/native-attribute-less-instancing
Open

bkaradzic-microsoft wants to merge 5 commits into
BabylonJS:masterfrom
bkaradzic-microsoft:pr/native-attribute-less-instancing

Conversation

@bkaradzic-microsoft

@bkaradzic-microsoft bkaradzic-microsoft commented Sep 17, 2026

Copy link
Copy Markdown
Member

Summary

  • Call setInstanceCount when a draw requests instances but provides no per-instance vertex buffer, on backends supporting BGFX_CAPS_VERTEX_ID.
  • Preserve buffered instancing and ordinary draw behavior. Without the explicit count, bgfx draws only one instance even when the shader uses gl_InstanceID.
  • Add a GPU regression using the existing Mesh.forcedInstanceCount API: indexed and non-indexed geometry, ordinary draws, one instance, and three independently colored instances.
  • Require runtime BGFX_CAPS_VERTEX_ID, respect no-op Metal / disabled-render-test configurations, and wait for RTT-pass readiness without warmup renders. Vulkan remains enabled.
  • Correct Vulkan SPIR-V interface locations and vertex/instance built-ins exposed by the Linux regression.
  • Keep private bgfx capability probing out of the installed-SDK compile fixture; internal UnitTests retain the GPU coverage.

Independence

Based on master at bb01e283, with published Babylon.js 9.21.2 and stock bgfx. No protocol, dependency-pin, fixture, tolerance, compute, or storage-buffer changes.

This fixes the underlying draw behavior; it does not import or claim the separate JavaScript shader changes needed by some clustered-lighting scenes.

CI follow-up

d32b2f0e fixes the installation failures: shared JavaScript test code must also compile against the public SDK, which intentionally does not export private bgfx headers. Only the installed-consumer fixture omits the private capability probe. Actual Windows/D3D11 and Linux/OpenGL installed-SDK consumers both build without source-tree include paths or installed bgfx headers.

7f7b0083 fixes the reproduced Linux Vulkan failure. RTT readiness alone did not fix the count-zero control: the emitted SPIR-V lacked inter-stage Location decorations and used OpenGL-only VertexId/InstanceId built-ins. Preserve ordinary GLSL parsing, assign matching varying locations by name, reserve explicit locations and complete matrix/array ranges, assign fragment output locations, and emit Vulkan VertexIndex/InstanceIndex. The pinned GLSLANG_WEB build omits glslang's IO mapper, so this uses a Vulkan-local AST pass without changing dependencies or other backends.

Validation

  • The two initial direct compiler regressions fail before the compiler fix. Three final regressions cover reversed declaration order, explicit locations on either/both stages, matrix arrays, vertex-only outputs, fragment outputs, and both index built-ins.
  • Both emitted diagnostic shader modules pass spirv-val --target-env vulkan1.0.
  • Linux/JavaScriptCore/Vulkan/lavapipe: CI-equivalent native suite has 23 passes and 19 existing skips; JavaScript suite has 66 passes and 27 optional codec cases pending (plugins disabled).
  • Indexed/non-indexed 0/1/3-count GPU controls pass. Removing only setInstanceCount with the repaired compiler still fails count 3; restoring it passes.
  • Unchanged Vulkan CI visual controls pass: Capsule and Multi camera rendering.
  • Windows/D3D11/Chakra: all 10 selected JavaScript and shader-compilation cases pass. The GPU regression also previously passed Windows Vulkan.
  • No renderer exclusion, reference change, pixel-tolerance relaxation, or warmup render was added. The existing Vulkan CI exclusion for CompileComprehensiveGLSL remains unchanged (upstream Make CompileComprehensiveGLSL complete on Linux Vulkan #1877).

Interface-block review follow-up

9c024dfe keys linked interface blocks by block type rather than stage-local instance name. A regression with different instance names, a matrix member, and implicit / one-sided explicit block locations fails before and passes after in the existing BABYLON_NATIVE_DISABLE_WEBMIN=ON configuration. The default parser rejects shader IO blocks, so this new syntax-specific case explicitly skips there; all existing Vulkan shader and GPU controls remain enabled and pass in both configurations.

Copilot AI lite review requested due to automatic review settings September 17, 2026 20:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Pull request overview

This PR fixes attribute-less instancing by explicitly passing the requested instance count to bgfx when no per-instance vertex buffer is present, and adds a native GPU regression test.

Changes:

  • Calls setInstanceCount for supported backends using BGFX_CAPS_VERTEX_ID.
  • Adds a JavaScript test covering indexed and non-indexed meshes with 0, 1, and 3 instances.
  • Adds a native-rendering availability flag and includes the new test in the JavaScript suite.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
Plugins/NativeEngine/Source/VertexArray.cpp Supplies explicit instance counts for attribute-less draws.
Apps/UnitTests/Source/Tests.JavaScript.cpp Exposes whether native rendering tests should run.
Apps/UnitTests/JavaScript/src/tests.nativeEngine.attributeLessInstancing.ts Adds the GPU regression coverage.
Apps/UnitTests/JavaScript/src/tests.javaScript.all.ts Registers the new test suite.
Apps/UnitTests/JavaScript/dist/tests.javaScript.all.js Includes the compiled test bundle changes.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Apps/UnitTests/JavaScript/src/tests.javaScript.all.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.

Comment thread Apps/UnitTests/Source/Tests.JavaScript.cpp Outdated
Comment thread Plugins/NativeEngine/Source/VertexArray.cpp

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Vulkan location assignment incorrectly matches interface blocks by instance name, potentially breaking valid cross-stage linkage.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 8/9 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread Plugins/ShaderCompiler/Source/ShaderCompilerVulkan.cpp Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Low-level Vulkan shader-interface rewriting and backend-specific rendering behavior warrant final human review.

Review details
  • Files reviewed: 8/9 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

bkaradzic-microsoft and others added 5 commits September 18, 2026 07:27
Tell bgfx the explicit count when a draw derives its instance data from
gl_InstanceID instead of an instance buffer. Preserve the existing
buffered-instance path and gate the call on BGFX_CAPS_VERTEX_ID.

Add indexed/non-indexed GPU controls for ordinary draws and forced counts
of one and three, using distinct colors for all three instances.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
Require BGFX_CAPS_VERTEX_ID at runtime in addition to the existing
no-op Metal and disabled-render-test configuration guards.

Wait for the render target's own pass readiness before its single draw,
with an explicit timeout and no warmup renders. Report all three pixel
centers together when a draw fails.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
Mark the installation compile fixture explicitly so its shared JavaScript
test source does not include private bgfx headers. Internal UnitTests keep
the runtime capability check and GPU regression coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
Assign linked varying locations by name while preserving explicit locations
and reserving complete array/matrix ranges. Assign fragment output locations
and translate GLSL vertex/instance IDs to Vulkan index built-ins.

The Linux lavapipe regression failed even for an ordinary count-zero draw
because the previous SPIR-V lacked varying locations and used OpenGL-only
ID decorations. Keep ordinary GLSL parsing and stock dependency pins.

Add direct emitted-SPIR-V regressions for reversed declaration order,
one-sided explicit locations, matrix arrays, vertex-only outputs, fragment
outputs, and vertex/instance index built-ins.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
Use the linked block type name as the location key, matching glslang's
getAccessName semantics while retaining ordinary varying names.
Vertex and fragment stages can use different block instance names.

Add a regression with different instance names, a matrix member, an
ordinary varying, and an explicit location on only the fragment block.
Exercise it with the existing BABYLON_NATIVE_DISABLE_WEBMIN option;
the default minified parser does not support shader IO blocks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
@bkaradzic-microsoft
bkaradzic-microsoft force-pushed the pr/native-attribute-less-instancing branch from 9c024df to d469df6 Compare September 18, 2026 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants