[GPU/Metal] Snapshot native MSL and iOS app work

This commit is contained in:
XeniOS
2026-06-09 15:17:46 +09:00
parent d96967471d
commit 728d3c2bfd
92 changed files with 2310 additions and 1009 deletions
+228
View File
@@ -0,0 +1,228 @@
# Codebase Discovery Report: Xenia (Xbox 360 Emulator) — iOS/Metal Port
> Generated by the `porting-discover` methodology (Game Porting Toolkit 4 skills).
> **Framing caveat:** This is **not a greenfield port**. Xenia already has a mature, largely
> complete Metal backend on Metal 3 (metal-cpp). This report is therefore a **Metal 4 / GPTK-4
> modernization readiness** assessment, not a from-scratch porting discovery. A completed discovery
> should have no unresolved [PENDING] entries.
## Summary
Xenia-edge-ios-msl is an Xbox 360 emulator with a substantial, working Metal backend (~41 files in
`src/xenia/gpu/metal/`) written in **metal-cpp** + Obj-C++ (`.mm`) glue, targeting **iOS 18.0** /
macOS 15.0. It already uses several Metal 4-era APIs (`MTLResidencySet`, `MTLSharedEvent`, bindless
argument buffers) on the Metal 3 command model, with a dual-path shader translator (Metal Shader
Converter DXBC→DXIL→metallib, plus a native MSL emitter).
Most of the immediately useful GPTK-4 surface is **version-agnostic** and ships on the current
iOS 18 / Metal 3 build with **no deployment-target change**: Metal validation, GPU capture/inspection,
the rendering-diagnosis playbook, Metal Shader Converter tuning, metal-cpp lifetime hygiene, and
un-gating the (already-wired) MetalFX **spatial** scaler on iOS. The **Metal 4 command-model**
adoption (flexible PSOs, explicit barriers, `MTL4ArgumentTable`) is a separate, medium-term track,
gated on iOS 26 and scoped as a **runtime-gated dual backend** (decided — path C, no device loss).
## Recommended Work Tracks
**Track 1 — Version-agnostic, ships at iOS 18 / Metal 3 (do first; highest ROI):**
1. Enable Metal validation (env-vars) — catches memory errors in generated shaders.
2. Capture a `.gputrace` (you have none) — rendering ground truth for correctness work.
3. Apply the `debugging-rendering-issues` symptom router to current visual bugs.
4. Metal Shader Converter tuning (minimum compatibility flags, min GPU/OS target, layout choice).
5. Un-gate the MetalFX spatial scaler on iOS (`metal_presenter.mm:42`).
6. metal-cpp lifetime audit at the `.mm`/metal-cpp boundary; frame-pacing review.
**Track 2 — Metal 4, runtime-gated iOS 26+ (dual backend, decided; medium-term):**
1. Finish the Metal 3 explicit hazard model + run under `_validate` on trace titles (prereq).
2. `MTL4Compiler` flexible PSOs + color-attachment mapping → collapse format/blend PSO permutations.
3. Promote the hazard model to Metal 4 queue/intra-pass barriers.
4. `MTL4ArgumentTable` + queue-level residency; replace Metal-4-removed APIs (`setVertexBytes`, per-encoder binds).
## Skills Loaded
- `porting-methodology` — milestone/goal framing for the recommendations below.
- `translating-to-metal4-api` — Metal 3 → Metal 4 mapping; TBDR considerations; removed APIs.
- `creating-metal4-shader-pipelines` — assessed pipeline cache against `MTL4Compiler`, flexible PSOs, `MTL4Archive`.
- `managing-metal4-synchronization` — assessed current fence/event/useResource model vs. Metal 4 explicit barriers.
- `using-metal-validation` — API/shader validation env-vars and per-pipeline scoping (version-agnostic).
- `debugging-rendering-issues` — symptom→cause router for visual bugs (largely version-agnostic).
- `using-gpucapture` / `using-gpudebug` — CLI `.gputrace` capture + inspection.
- `managing-metal-cpp-lifetimes``NS::TransferPtr`/`RetainPtr` ownership at the ARC boundary.
- `using-metalfx-temporal-upscaler` / `using-metalfx-frame-interpolation` — MetalFX availability + applicability.
- Metal Shader Converter `docs/metal-shader-converter/performance.md` — codegen tuning knobs.
- MetalFX + `MTL4CommandQueue` availability cross-checked against Apple reference (sosumi.ai).
## Game Porting Toolkit Evaluation Findings
Not directly applicable — this is an emulator, not a Windows game running under the GPTK evaluation
environment. The relevant "source" is the guest Xbox 360 GPU (Xenos) command stream, already handled
by Xenia's existing D3D12/Vulkan/Metal backends.
## Trace Analysis
Instruments traces are present in `scratch/` and are usable for performance planning. The MSC perf
guide recommends Metal System Trace to evaluate shader-execution overlap / TLAB serialization, so
these can be mined directly:
| Trace | Type | Use |
|---|---|---|
| `mirrors-edge-time-profiler.trace` | Time Profiler | CPU hotspots |
| `mw2-ios-msl.trace` | Metal System Trace (iOS, MSL path) | CPU/GPU timing on device |
| `halo3-odst.trace` | Metal System Trace | per-pass GPU timing |
| `ios-runs.trace` | Metal System Trace | device run timing |
| `xctrace_exports/` | xctrace CSV/exports | scripted analysis |
**Gap:** no `.gputrace` (GPU frame capture) found — that is the rendering ground truth for
correctness validation. Recommend capturing one via the `using-gpucapture` workflow (`gpucapture` CLI,
macOS 27) for any rendering-correctness milestone. This is a **Track 1** item.
## Reference Artifacts
| Artifact Type | Path | Notes |
|---|---|---|
| Metal System Trace (.trace) | `scratch/*.trace` | timing only, no frame capture |
| xctrace exports | `scratch/xctrace_exports/` | derived timing data |
| MSL AIR repro | `scratch/msl_air_repro/` | shader compile repro case |
| Hazard-model design doc | `scratch/metal_hazard_model_design.md` | in-progress explicit-sync design |
| GPU frame capture (.gputrace) | — | **not collected — recommend capturing** |
## Platform Readiness
| Area | Status | Notes |
|------|--------|-------|
| macOS build | Ready | macOS 15.0 target; Metal + MetalKit linked |
| iOS build | Ready | `build-ios-xcode/`, CMake presets; iOS 18.0 target |
| Platform layer (windowing) | Ready | `ui/ios/` (UIKit + CAMetalLayer), `ui/metal/metal_presenter.mm` |
| Content pipeline | Ready | emulator consumes guest assets at runtime; n/a |
| Required libraries | Ready | metal-cpp + metal-shader-converter vendored in `third_party/` |
| Deployment target | Keep 18.0 (dual backend) | Floor stays iOS 18.0; Metal 4 path (iOS 26+) added behind a runtime `supports…()`/OS gate — **path C chosen**, no device loss |
## Graphics Backend Analysis
> "Opportunity" column covers both version-agnostic (T1) and Metal-4 (T2) work.
| # | Category | Finding | Apple-platform opportunity |
|---|----------|---------|----------------------------|
| 1 | Existing backends | `d3d12`, `vulkan`, `metal`, `null` under `src/xenia/gpu/` | Metal is the iOS target; others unaffected |
| 2 | API abstraction | Strong: `CommandProcessor`/`GraphicsSystem` abstraction with per-backend impls | Any Metal 4 work is contained to the metal backend; a runtime gate fits the existing seams |
| 3 | Shader language | Dual: MSC (DXBC→DXIL→metallib) + native MSL emitter (`msl_shader_translator.cc`) | **T1:** MSC tuning + DXBC→DXIL intermediate-transform caveat argues for native MSL on hot shaders. **T2:** MSC path already Metal-4-ABI-compatible |
| 4 | Shader pipeline | `metal_pipeline_cache` (Metal 3 `MTL::RenderPipelineState`, async pool, `MTL::BinaryArchive`) + `metal_stage_compile_cache` (persistent MSC cache) | **T1:** async + caching already solved; tune MSC codegen. **T2:** flexible PSOs + color-attachment mapping collapse format/blend permutations |
| 5 | Existing Metal backend | Mature: command processor, RT cache, texture cache, shared-memory/EDRAM, geometry/tessellation emulation | Modernization + hardening, not bring-up |
| 6 | Binding model | Bindless argument buffers — MSC top-level argument buffer + native MSL texture/sampler heaps (65536/2048 slots) | **T1:** linear-layout vs root-signature tradeoff (occupancy). **T2:** maps to `MTL4ArgumentTable` |
| 7 | Render graph | None formal — imperative command processor translating guest draws | Explicit barriers (T2) must be inserted at the command-processor level |
| 8 | Synchronization | Metal 3: `MTL::Fence` (`shared_memory_fence_`), `MTL::SharedEvent`, `useResource`/`useResources`/`useHeap`; **experimental explicit hazard model** behind `metal_backend_hazard_model` (+ `_validate`) | **T1:** finish + validate the hazard model on Metal 3. **T2:** direct on-ramp to Metal 4 queue/intra-pass barriers |
| 9 | Threading | Async pipeline-compile thread pool (`creation_threads_`, priority queue); Xenia command-processor thread | `MTL4Compiler` is multithreaded by default; existing pool may be simplified (T2) |
| 10 | Memory management | `MTL::Heap` pools, `MTLResidencySet` (`AddResidencySetHeap`), shared-memory buffers for EDRAM | Already Metal-4-style residency; extend to queue-level residency sets (T2) |
| 11 | Language conventions | metal-cpp (manual ref-counting) + `.mm` ARC glue (`metal_presenter.mm`, `ir_runtime_impl.mm`) | **T1:** `managing-metal-cpp-lifetimes` audit at the bridge boundary |
| 12 | ObjC/ARC | Mixed ARC (`.mm`) and metal-cpp (`NS::`); CAMetalLayer/drawable handling in ObjC | **T1:** watch `NS::TransferPtr` vs `RetainPtr` ownership at boundaries |
## Platform Gap Analysis
- **Debugging / correctness tooling** → biggest under-used surface: Metal validation (`using-metal-validation`), GPU capture/inspect (`using-gpucapture` / `using-gpudebug`), rendering diagnosis (`debugging-rendering-issues`). All version-agnostic, all Track 1.
- **Windowing/presentation** → already on `CAMetalLayer` (iOS via `ui/ios/`). Frame pacing/vsync/EDR review available without Metal 4. Skill: `presenting-metal-drawables`.
- **Input** → `GameController` framework already linked (`ui/ios/CMakeLists.txt`); touch model present. Skill: `using-game-controller`.
- **Graphics (Metal 4 deltas)** → flexible PSOs, explicit barriers, `MTL4ArgumentTable` — Track 2 only. Skills: `translating-to-metal4-api`, `managing-metal4-synchronization`, `creating-metal4-shader-pipelines`, `managing-metal4-resources`.
- **Upscaling** → MetalFX **spatial** present but disabled on iOS (Track 1 un-gate); temporal/frame-gen need motion vectors the emulator doesn't produce. Skills: `using-metalfx-temporal-upscaler`.
- **Audio / file system / threading** → handled by Xenia's existing cross-platform base layers; no Apple-specific gap surfaced.
## Feature Coverage Matrix
> Function counts not enumerated; status reflects presence/maturity in the Metal backend.
| Feature Domain | Status | Essential | Notes |
|----------------|--------|-----------|-------|
| Device / Init | Present | Yes | `metal_provider`, `metal_command_processor` |
| Buffers | Present | Yes | shared-memory / upload pools |
| Textures | Present | Yes | texture cache w/ format conversion |
| Render Targets | Present | Yes | `metal_render_target_cache` (EDRAM emulation) |
| Samplers | Present | Yes | bindless sampler heap |
| Pipeline State | Present | Yes | Metal 3 PSOs; **flexible-PSO opportunity** |
| Descriptor Binding | Present | Yes | bindless argument buffers (MSC TLAB + native heaps) |
| Command Encoding (Draw) | Present | Yes | standard / geometry / tessellation / native-mesh paths |
| Command Encoding (Dispatch) | Present | Depends | compute used for emulation passes |
| Resource Copy (Blit) | Present | Yes | shared-memory upload, gamma compute |
| Synchronization | Present (transitional) | Yes | fences/events/useResource + experimental hazard model |
| Presentation / Swap Chain | Present | Yes | CAMetalLayer; SharedEvent-gated mailbox |
| Queries (Timestamp/Occlusion) | Partial | Optional | verify counter sampling coverage |
| Debug Markers / Labels | Present | Yes (early) | labels used for capture readability |
| Compute | Present | Depends | emulation + gamma/upscale |
| Raytracing | Absent | Optional | not used by Xenos emulation |
| Indirect Draw/Dispatch | Partial | Optional | confirm against guest indirect paths |
## Practical Porting Advice (tailored)
**Correctness tooling (Track 1):**
- **Metal validation** — enable `MTL_DEBUG_LAYER=1` broadly (cheap, CPU-side). Add `MTL_SHADER_VALIDATION=1` selectively for GPU-side memory errors in generated shaders — and **pair it with `MTL_SHADER_VALIDATION_REPORT_TO_STDERR=1`** or errors only hit the system log. For this pre-Metal-4 build, per-pipeline scoping is the env allow/deny list `MTL_SHADER_VALIDATION_ENABLE_PIPELINES` / `_DISABLE_PIPELINES` (the `MTL4PipelineOptions.shaderValidation` route is Metal-4-only).
- **Rendering diagnosis** — the `debugging-rendering-issues` symptom router maps onto classic Xenos→Metal traps: BGRA↔RGBA channel order + `MTLTextureSwizzleChannels`; sRGB/gamma double-encode (you have gamma-ramp compute); reversed-depth z-fighting (clear value + compare must change together); premultiplied alpha on the drawable; Y-flip/winding; `D24_UNORM_S8_UINT` not universal on Apple GPUs → prefer `Depth32Float_Stencil8`; `COLOR_WRITE_ENABLE``MTLColorWriteMask` bit-layout reversal.
**Metal Shader Converter tuning (Track 1, not Metal 4):** the perf guide maps onto knobs already in `MetalStageCompileKey` (`compatibility_flags`, `minimum_gpu_family`, `minimum_os`, `validation_flags`):
- Use the **minimum** compatibility flags (`IRCompilerSetCompatibilityFlags`) — each costs runtime perf.
- Set `IRCompilerSetMinimumGPUFamily` / `SetMinimumDeploymentTarget` — newer targets let MSC emit more optimal IR.
- Favor the **linear resource layout** over root-signature bindless for shaders that don't need bindless (single indirection, lower register pressure).
- The guide warns against **intermediate IR transforms** — your DXBC→DXIL(dxilconv)→MSC chain is exactly that, a concrete argument for maturing the **native-MSL path** on hot shaders.
**Pipeline / sync (Track 2):**
- PSO compile stutter is the canonical emulator problem; you've already attacked it (async pool + binary archive + persistent stage cache). The remaining lever is **reducing PSO count** via flexible PSOs / color-attachment mapping — your `MetalPipelineDescription` bakes `color_formats[4]`, `depth/stencil_format`, `sample_count`, `normalized_color_mask`, `blendcontrol[4]` into the key, exactly the axes flexible PSOs defer.
- The experimental `metal_backend_hazard_model` is effectively a Metal 4 barrier model in Metal 3 clothing; finish it now so the Metal 4 port is a primitive swap, not a redesign.
## Stub Candidates
Not applicable in the usual sense (mature port). Equivalent "feature flags already present": MetalFX
(`metal_presenter_use_metalfx`), hazard model (`metal_backend_hazard_model`), native-MSL vs MSC backend
selection (`MetalShader::Backend`). These gate experimental paths and are the natural milestone toggles.
## Quick Wins
Ordered by ROI; all of Track 1, none require a deployment-target change:
1. **Enable Metal validation** — env-vars only, no code. Catches memory errors in generated MSL/metallib (`MTL_DEBUG_LAYER`, `MTL_SHADER_VALIDATION` + `…_REPORT_TO_STDERR`).
2. **Capture a `.gputrace`** via `gpucapture` — you currently have none; this is rendering ground truth for any correctness work.
3. **Un-gate MetalFX spatial on iOS**`metal_presenter.mm:42` (`#if !XE_PLATFORM_IOS`) compiles it out, but `MTLFXSpatialScaler`/`MTLFXTemporalScaler` are iOS **16.0+** (verified). The spatial path is already wired; un-gating lights up internal-res→display upscaling. First checkpoint: it compiles clean on the iOS path (never built there before).
4. **MSC codegen tuning** — audit compatibility flags down to the minimum; tune min GPU family/OS.
5. **MSC programmable blending / framebuffer fetch in HLSL** for EDRAM on TBDR tile memory — reduces render-target round-trips. Skill: `compiling-with-metal-shaderconverter`.
6. **Refresh vendored metal-cpp** to the GPTK-4 (iOS 27) drop for Apple10 GPU family + Metal 4 surface.
## Parallel Work Opportunities
- Mine the existing `.trace` captures (MW2, Halo 3 ODST, Mirror's Edge) to rank the heaviest GPU passes and to evaluate MSC TLAB-induced shader serialization (per the MSC perf guide) before investing in flexible PSOs or upscaling.
- Run the hazard model under `_validate` on those titles to find missed hazards on Metal 3 — de-risks the eventual Metal 4 barrier swap independent of the deployment-target decision.
- Stand up the validation env-vars in the dev launch path so every run surfaces shader/API misuse.
## Risk Assessment
- **Correctness regressions are hard to see without ground truth:** no `.gputrace` collected. Mitigation: capture one (Track 1) and enable Metal validation before correctness-sensitive changes.
- **Explicit sync correctness (T2):** Metal 4 has no driver hazard tracking — under-barriering → GPU faults, over-barriering → perf loss. The skill calls this the longest phase of a port. Mitigation: finish + `_validate` the Metal 3 hazard model first (Track 1).
- **metal-cpp/ARC boundary:** mixed ownership models across `.mm`/metal-cpp risk use-after-free; audit with `managing-metal-cpp-lifetimes`. Mitigation: Metal validation + leak instruments (Track 1). See Known Blockers for the specific sites.
- **Deployment-target tension (T2):** Metal 4 APIs are iOS 26+ (`MTL4CommandQueue` verified). Resolved via the dual-backend gate (path C) — no device loss, at the cost of maintaining two paths.
- **Native MSL emitter maintenance:** owning an MSL emitter means Metal version/behavior changes land on you, not on MSC.
## Dependency Graph
- Track 1 items (validation, `.gputrace`, rendering diagnosis, MSC tuning, MetalFX un-gate, lifetime audit): **all independent**, ship at iOS 18.
- Hazard-model completion: **independent** (Metal 3), and a **prerequisite** for Metal 4 sync.
- Flexible PSOs / Metal 4 command model: **blocked on** the iOS 26 runtime gate (dual backend).
- Full Metal 4 command model: **depends on** explicit sync being complete (no implicit hazard tracking) and on replacing Metal-4-removed APIs (`setVertexBytes`, per-encoder binds).
## Key Files
- `src/xenia/gpu/metal/metal_command_processor.{h,cc}` — submission, sync, residency, encoders.
- `src/xenia/gpu/metal/metal_pipeline_cache.{h,cc}` — PSO creation/caching/async pool/binary archive.
- `src/xenia/gpu/metal/metal_stage_compile_cache.{h,cc}` — persistent MSC metallib cache.
- `src/xenia/gpu/msl_shader_translator.{h,cc}` — native MSL emitter.
- `src/xenia/ui/metal/metal_presenter.mm` — CAMetalLayer presentation + MetalFX (gated, line 42).
- `src/xenia/ui/metal/metal_immediate_drawer.mm` — UI drawing; `__bridge`/`CFRelease` buffer lifetime site.
- `scratch/metal_hazard_model_design.md` — explicit-sync design in progress.
## Scope Decisions (from user)
- **Language:** metal-cpp + `.mm` glue. Confirmed by ownership model in `src/xenia/ui/metal/` and `src/xenia/gpu/metal/`.
- **Off-limits:** None stated by the user yet. Suggested local policy for this milestone: treat `third_party/` and external SDK vendoring as out-of-scope unless the user explicitly asks for version/ABI updates.
- **Abstraction strategy:** Existing abstraction (multi-backend `CommandProcessor`). No new layer needed.
- **Metal 4 adoption path:** **C — runtime-gated dual backend** (decided). Metal 3 path serves iOS 1825; a Metal 4 path (flexible PSOs + explicit barriers + `MTL4ArgumentTable`) is added behind a runtime iOS 26+ / `supports…()` gate. No device loss.
- **Reference available:** Yes. Behavioral parity for graphics behavior is already encoded in the existing Xenia D3D12 path (`src/xenia/gpu/d3d12/`) and mirrored by this mature Metal path; also has platform trace references in `scratch/*.trace` and export logs.
## Known Blockers / Constraints
- **`metal-cpp` / ARC ownership mismatch risk:** runtime-safe but fragile boundaries exist where Objective-C ownership crosses into metal-cpp raw pointers. In `metal_presenter.mm`, the queue is intentionally non-owning (`__bridge` from provider) and never released there. In `metal_immediate_drawer.mm`, temporary `MTLBuffer` values are stored as `void*` via `__bridge` and released with `CFRelease` in `EndDrawBatch()`, which is correct only if retain counts are consistent and should be audited carefully in future Metal4 changes.
- **No `gputrace` capture yet:** only timing traces exist in `scratch/`; render-correctness and exact object-lifetime confirmation is incomplete until a `.gputrace` is collected.
- **API-migration blocker for full Metal 4 parity:** several renderer paths still use APIs removed in Metal 4 (for example `setVertexBytes` and per-encoder resource binding); converting these is a hard requirement for true MTL4 path parity.
- **Target-floor constraint:** `iOS 18.0` and legacy devices are only covered by Metal 3 path; Metal 4 features remain runtime-gated to `iOS 26+`.
@@ -1,176 +0,0 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x",
"filename" : "iphone-notification-20@2x.png"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x",
"filename" : "iphone-notification-20@3x.png"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x",
"filename" : "iphone-settings-29@2x.png"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x",
"filename" : "iphone-settings-29@3x.png"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x",
"filename" : "iphone-spotlight-40@2x.png"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x",
"filename" : "iphone-spotlight-40@3x.png"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x",
"filename" : "iphone-app-60@2x.png"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x",
"filename" : "iphone-app-60@3x.png"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x",
"filename" : "ipad-notification-20.png"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x",
"filename" : "ipad-notification-20@2x.png"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x",
"filename" : "ipad-settings-29.png"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x",
"filename" : "ipad-settings-29@2x.png"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x",
"filename" : "ipad-spotlight-40.png"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x",
"filename" : "ipad-spotlight-40@2x.png"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x",
"filename" : "ipad-app-76.png"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x",
"filename" : "ipad-app-76@2x.png"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x",
"filename" : "ipad-pro-app-83.5@2x.png"
},
{
"idiom" : "ios-marketing",
"size" : "1024x1024",
"scale" : "1x",
"filename" : "ios-marketing-1024.png"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x",
"filename" : "mac-16.png"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x",
"filename" : "mac-16@2x.png"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "1x",
"filename" : "mac-32.png"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x",
"filename" : "mac-32@2x.png"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "1x",
"filename" : "mac-128.png"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x",
"filename" : "mac-128@2x.png"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "1x",
"filename" : "mac-256.png"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "2x",
"filename" : "mac-256@2x.png"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "1x",
"filename" : "mac-512.png"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "2x",
"filename" : "mac-512@2x.png"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Some files were not shown because too many files have changed in this diff Show More