Skip to content

Enable SAGAMetal by default and validate Studio Web export - #214

Merged
SpectralDragon merged 9 commits into
mainfrom
codex/sagametal-web-default
Nov 13, 2026
Merged

SpectralDragon merged 9 commits into
mainfrom
codex/sagametal-web-default

Conversation

@SpectralDragon

Copy link
Copy Markdown
Contributor

Enable SAGAMetal on macOS, iOS and tvOS and pin SAGA for Metal and Web. Keep the legacy Metal flag for comparison and keep the native Vulkan paths opt-in.

Local validation covered macOS Studio and native export, the iPad Studio simulator, tvOS device and simulator builds, and Chromium WebGPU for Debug and Release Studio exports. Apple CI includes the packaged Studio Web export.

@SpectralDragon
SpectralDragon marked this pull request as ready for review November 13, 2026 06:25
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-13T06:29:30.170455Z 889d96c Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@SpectralDragon
SpectralDragon merged commit e42994f into main Nov 13, 2026
15 of 18 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 889d96ce1b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +85 to +87
public func getImage(from _: Texture) -> Image? {
// Readback is asynchronous; use `readImage(from:)`.
nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Migrate synchronous image consumers before defaulting to SAGA

With SAGA now the default Apple renderer, returning nil here breaks existing consumers of Image(texture:). In particular, EditorProjectPreviewCapture.capture in EditorProjectPreviewStore.swift still uses synchronous readback for both saved project thumbnails and requested frames, so thumbnails stop updating and frame requests never receive pixels. EditorTextureAtlasAssetEditor.reloadPreview likewise receives an empty image. Migrate these consumers to the asynchronous readback path, or preserve synchronous readback support, before switching the default backend.

Useful? React with 👍 / 👎.

Comment on lines +120 to +125
let image = resource.image
let bytesPerRow = pixelFormat.bytesPerComponent * image.width
let data = unsafe image.data.withUnsafeBytes { unsafe [UInt8]($0) }
write(
data,
bytesPerRow: bytesPerRow,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Expand RGB images before uploading them as RGBA textures

For Texture2D(image:) constructed from an .rgb8 image, Image.Format.toPixelFormat selects .rgba8, but this code uploads the original three-byte-per-pixel data with a four-byte-per-pixel row stride. The upload therefore has insufficient data and cannot reproduce the image correctly. This regresses the default Apple path: MetalGPUTexture explicitly expands RGB8 data to RGBA8 before uploading. Apply the same conversion here, including subresource uploads.

Useful? React with 👍 / 👎.

Comment on lines +71 to +72
return try await withCheckedThrowingContinuation { continuation in
context.queue.enqueue { device in

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Resume readback continuations when device creation fails

If the asynchronous SAGA device initializer throws, OrderedGPUWorkQueue skips device jobs and invokes only their optional onUnavailable handlers. This enqueue supplies no such handler, leaving the checked continuation unresolved, so readData() hangs instead of throwing. SAGAGPUTexture.readImage() has the same failure path. Supply unavailable-device cleanup that resumes each readback continuation with an error, as command-buffer completion already does.

Useful? React with 👍 / 👎.

Comment on lines +7 to +8
@MainActor
struct WESLUIPipelineTests {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Nest the new GPU tests under the serialized rendering suite

When ADAENGINE_VALIDATE_WGSL=1 enables these tests in a parallel test run, this standalone suite can call setupRenderEngine() while a Render3DGPUTests test is suspended awaiting GPU work, replacing the process-wide renderer underneath that test. WESLGradientPipelineTests has the same issue. Nest both suites under Render3DGPUTests so they participate in its serialization; @MainActor alone does not prevent interleaving across suspension points. This also violates the explicit GPU-suite placement requirement in AGENTS.md.

AGENTS.md reference: AGENTS.md:L201-L202

Useful? React with 👍 / 👎.

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