Skip to content

Enable Unit Tests on Win32 D3D12 CI#1671

Draft
bghgary wants to merge 31 commits intoBabylonJS:masterfrom
bghgary:enable-d3d12-unit-tests
Draft

Enable Unit Tests on Win32 D3D12 CI#1671
bghgary wants to merge 31 commits intoBabylonJS:masterfrom
bghgary:enable-d3d12-unit-tests

Conversation

@bghgary
Copy link
Copy Markdown
Contributor

@bghgary bghgary commented Apr 22, 2026

Enables the Win32 D3D12 UnitTests in CI. Follow-up to #1646.

Changes

  • .github/workflows/build-win32.yml — remove the if: graphics-api != 'D3D12' gate on the Unit Tests step. (The Validation Tests step is left gated — separate concern.)
  • Apps/UnitTests/CMakeLists.txt
    • Auto-set SKIP_RENDER_TESTS when GRAPHICS_API=D3D12. The render-test helpers in Utils.D3D12.cpp (introduced alongside Add synchronous ExternalTexture.CreateForJavaScript and deprecate AddToContextAsync #1646) are stubs that throw; implementing real D3D12 upload/RT/readback paths is a follow-up beyond this PR's scope.
    • Deploy dxcompiler.dll + dxil.dll from the bgfx bundle next to UnitTests.exe on D3D12 builds. bgfx's D3D12 renderer uses DXC at runtime for shader compilation; those DLLs aren't part of Windows. Without this, every test that compiles a shader fails with Failed to load dxcompiler.dll.

Local verification (Win32 D3D12, RelWithDebInfo)

[==========] 6 tests from 4 test suites ran.
[  PASSED  ] 5 tests.
[  SKIPPED ] 1 test:
[  SKIPPED ] ExternalTexture.RenderTextureArray

Passing: ExternalTexture.Construction, ExternalTexture.CreateForJavaScript, JavaScript.All, ShaderCache.SaveAndLoad, UniformPadding.SubVec4UniformsDoNotOverflow.

Merge order

This PR depends on #1646 (which introduces Tests.ExternalTexture.Render.cpp / Utils.D3D12.cpp / SKIP_RENDER_TESTS). Do not merge until #1646 is in. Kept as draft until then.

Follow-ups (not blocking this PR)

  • Implement real D3D12 render helpers (committed resource + upload heap copy, RT + readback via CopyTextureRegion with 256-byte row alignment) and drop the D3D12 branch of the SKIP_RENDER_TESTS condition.
  • Consider enabling the Validation Tests step on D3D12 — separate investigation (same DXC runtime requirement may apply to Playground).
mergeable DO-NOT-MERGE (until #1646 merges)

[Created by Copilot on behalf of @bghgary]

bghgary and others added 30 commits March 24, 2026 22:05
- Add Tests.ExternalTexture.Render.cpp: end-to-end test that renders a
  texture array through a ShaderMaterial to an external render target,
  verifying each slice (red, green, blue) via pixel readback.
- Add tests.externalTexture.render.ts: JS test with sampler2DArray shader.
- Add RenderDoc.h/cpp to UnitTests for optional GPU capture support.
- Add Utils helpers: CreateTestTextureArrayWithData, CreateRenderTargetTexture,
  ReadBackRenderTarget, DestroyRenderTargetTexture (D3D11, Metal, stubs for
  D3D12/OpenGL).
- Fix ExternalTexture_Shared.h: pass m_impl->NumLayers() instead of
  hardcoded 1 in Attach(), preserving texture array metadata.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove layerIndex parameter from Impl::Update declaration to match
the updated signature in ExternalTexture_Shared.h.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Migrate HeadlessScreenshotApp, StyleTransferApp, and PrecompiledShaderTest
from AddToContextAsync (promise-based) to CreateForJavaScript (synchronous).
This removes the extra frame pump and promise callbacks that were previously
required.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…llers

- Move RenderDoc.h/cpp to D3D11-only CMake block with HAS_RENDERDOC define
- Guard RenderDoc calls with HAS_RENDERDOC instead of WIN32
- Update StyleTransferApp and PrecompiledShaderTest to use CreateForJavaScript

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
On OpenGL, TextureT is unsigned int (not a pointer), so reinterpret_cast
fails. Add NativeHandleToUintPtr helper using if constexpr to handle both
pointer types (D3D11/Metal/D3D12) and integer types (OpenGL).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- RenderDoc.h/cpp now accept void* device instead of ID3D11Device*
- Move RenderDoc to WIN32 block (not D3D11-only) since it works with any API
- Fix OpenGL build: use NativeHandleToUintPtr helper for TextureT cast
- Add Linux support (dlopen librenderdoc.so)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move DestroyTestTexture after FinishRenderingCurrentFrame so bgfx::frame()
processes the texture creation command before the native resource is released.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ensure the JS startup dispatch completes before calling
deviceUpdate.Finish() and FinishRenderingCurrentFrame(). This
guarantees that bgfx::frame() processes the CreateForJavaScript
texture creation command, making the texture available for subsequent
render frames. The old async API had an implicit sync point
(addToContext.wait) that the new sync API lost.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…eation

- Rename CreateForJavaScriptWithTextureArray to CreateForJavaScript and
  use arraySize=1 since texture array rendering is covered by
  RenderTextureArray. The old test crashed on CI (STATUS_BREAKPOINT in
  bgfx when creating texture arrays via encoder on WARP).
- Revert two-step create+override approach back to single createTexture2D
  call with _external parameter (overrideInternal from JS thread doesn't
  work since the D3D11 resource isn't created until bgfx::frame).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CreateForJavaScript already exists in Tests.ExternalTexture.cpp,
causing a linker duplicate symbol error.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… test)

The D3D11-specific CreateForJavaScript test crashed on CI due to
bgfx assertions when calling createTexture2D with _external on
the encoder thread. The cross-platform CreateForJavaScript test
in Tests.ExternalTexture.cpp already covers this functionality.
The texture array rendering is covered by RenderTextureArray.

Also revert app startup ordering to Finish->Wait (matching the
pattern used by HeadlessScreenshotApp on master).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The bgfx callback's fatal() handler was silently calling debugBreak()
on DebugCheck assertions with no output, making CI crashes impossible
to diagnose. Now logs the file, line, error code and message to stderr
before breaking, so the assertion details appear in CI logs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add DISM/d3dconfig step to CI to enable D3D debug layer, which will
provide detailed D3D11 validation messages for the CreateShaderResourceView
E_INVALIDARG failure. Kept the _external createTexture2D path (reverted
the AfterRenderScheduler approach) so we can see the actual D3D debug
output that explains the SRV mismatch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The bgfx _external texture path triggers E_INVALIDARG in
CreateShaderResourceView on CI's WARP D3D11 driver. The overrideInternal
alternative doesn't support full array textures (hardcodes ArraySize=1).
Since the _external path works on real GPUs, skip the render test on CI
via BABYLON_NATIVE_SKIP_RENDER_TESTS and keep the direct _external path.

Also adds D3D debug layer enablement to CI for future diagnostics, and
logs bgfx fatal errors to stderr before crashing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Switch from _external parameter (crashes on WARP) to create+overrideInternal
two-step approach. The overrideInternal path is compatible with WARP but
sets ArraySize=1 in the SRV, so the RenderTextureArray test (which needs
full array access) is skipped on CI. The render test works on real GPUs
where the _external path succeeds.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The overrideInternal call fires on AfterRenderScheduler after the first
bgfx::frame(). An additional frame pump ensures the native texture
backing is applied before the scene render.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove deleted Tests.ExternalTexture.D3D11.cpp from Install/Test/CMakeLists.txt
- Add extra frame pump after CreateForJavaScript in HeadlessScreenshotApp
  and StyleTransferApp so overrideInternal has time to apply the native
  texture backing before the first render.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nder-test

# Conflicts:
#	.github/jobs/win32.yml
…erResourceView

The createTexture2D _external path now works on WARP after the bgfx update
in master. Drop the placeholder + AfterRenderScheduler + overrideInternal
two-step dance and the extra frame pump that existed to apply it. This also
restores full array-slice SRV so RenderTextureArray no longer needs a
sanitizer-only skip.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove 'pump an extra frame' block from StyleTransferApp and
  HeadlessScreenshotApp (no longer needed after the _external revert).
- Update ExternalTexture Readme to match the one-call createTexture2D
  path and direct-construction consumer pattern.
- Drop unused DispatchSync declaration from UnitTests/Utils.h.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The SKIP_RENDER_TESTS flag was originally added because WARP could not handle the _external path in bgfx. bgfx PR BabylonJS#1669 fixed CreateShaderResourceView for the _external parameter, so the render test should pass on WARP now. Let CI verify.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Reword BABYLON_NATIVE_SKIP_RENDER_TESTS option description. WARP is available on Win32, so 'no real GPU' is inaccurate; the real reason to skip is a missing per-backend test harness.
- Add braces around if constexpr / else branches in NativeHandleToUintPtr per coding style.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Flip the graphics-api != 'D3D12' gate on the Unit Tests step in build-win32.yml so D3D12 runs the unit test suite. The render test is skipped on D3D12 via SKIP_RENDER_TESTS (the Utils.D3D12.cpp helpers for the render test are stubs that throw). Implementing real D3D12 render helpers is a TODO for a follow-up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- RenderDoc.cpp: drop absolute Windows path; use plain #include "renderdoc_app.h"
- Tests.ExternalTexture.Render.cpp: handle renderSlice rejection and add wait timeout to prevent test hangs
- Tests.ExternalTexture.cpp: add ExternalTexture.Update test (Update() path was dropped in the refactor)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Restore AddToContextAsync as a deprecated shim around CreateForJavaScript for source compat with existing consumers
- Tighten render test: color tolerance 25 -> 2; require exact 100%% match (was 90%%)
- Drop BABYLON_NATIVE_SKIP_RENDER_TESTS option; gate SKIP_RENDER_TESTS directly on GRAPHICS_API STREQUAL "D3D12"

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

1 participant