Token导航 LogoToken导航TokenDH.com
前端设计需要联网github未标认证来源可访问clear审计通过

axiom-metal-migration公理金属迁移

Agent Skill

axiom-metal-migration 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

3,998

周安装

170

GitHub Stars

873

下载量

1,401
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:axiom-metal-migration(公理金属迁移)
来源仓库:https://github.com/charleswiltgen/axiom
仓库路径:skills/axiom-metal-migration
安装命令:
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-metal-migration
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-metal-migration

简介

用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息。

  • 适合在 Codex、Claude、Cursor、Gemini CLI 中围绕仓库状态、代码变更或协作事项进行整理。
  • 可结合来源仓库、安装命令和原始 README 继续核验具体用法。
  • 安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。
  • axiom-metal-migration 属于前端设计类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Metal Migration

Porting OpenGL/OpenGL ES or DirectX code to Metal on Apple platforms.

When to Use This Skill

Use this skill when:

  • Porting an OpenGL/OpenGL ES codebase to iOS/macOS
  • Porting a DirectX codebase to Apple platforms
  • Deciding between translation layer (MetalANGLE) vs native rewrite
  • Planning a phased migration strategy
  • Evaluating effort vs performance tradeoffs

Red Flags

❌ "Just use MetalANGLE and ship" — Translation layers add 10-30% overhead; fine for demos, not production

❌ "Convert shaders one-by-one without planning" — State management differs fundamentally; you'll rewrite twice

❌ "Keep the GL state machine mental model" — Metal is explicit; thinking GL causes subtle bugs

❌ "Port everything at once" — Phased migration catches issues early; big-bang migrations hide compounding bugs

❌ "Skip validation layer during development" — Metal validation catches 80% of porting bugs with clear messages

❌ "Worry about coordinate systems later" — Y-flip and NDC differences cause the most debugging time

❌ "Performance will be the same or better automatically" — Metal requires explicit optimization; naive ports can be slower

Migration Strategy Decision Tree

Starting a port to Metal?
│
├─ Need working demo in <1 week?
│   ├─ OpenGL ES source? → MetalANGLE (translation layer)
│   │   └─ Caveats: 10-30% overhead, ES 2/3 only, no compute
│   │
│   └─ Vulkan available? → MoltenVK
│       └─ Caveats: Vulkan complexity, indirect translation
│
├─ Production app with performance requirements?
│   └─ Native Metal rewrite (recommended)
│       ├─ Phased: Keep GL for reference, port module-by-module
│       └─ Full: Clean rewrite using Metal idioms from start
│
├─ DirectX/HLSL source?
│   └─ Metal Shader Converter (Apple tool)
│       └─ Converts DXIL bytecode → Metal library
│       └─ See metal-migration-ref for usage
│
└─ Hybrid approach?
    └─ MetalANGLE for demo → Native Metal incrementally
        └─ Best of both: fast validation, optimal end state

Pattern 1: Translation Layer (Quick Demo Path)

When to use: Validate feasibility, get stakeholder buy-in, prototype

MetalANGLE Setup (OpenGL ES → Metal)

// 1. Add MetalANGLE via SPM or CocoaPods
// GitHub: nicklockwood/MetalANGLE

// 2. Replace EAGLContext with MGLContext
import MetalANGLE

let context = MGLContext(api: kMGLRenderingAPIOpenGLES3)
MGLContext.setCurrent(context)

// 3. Replace GLKView with MGLKView
let glView = MGLKView(frame: bounds, context: context)
glView.delegate = self
glView.drawableDepthFormat = .format24

// 4. Existing GL code works unchanged
glClearColor(0, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT)
// ... your existing GL rendering code

Tradeoffs Table

AspectMetalANGLENative Metal
Time to demoHoursDays-weeks
Runtime overhead10-30%Baseline
Shader changesNoneFull rewrite
Compute shadersNot supportedFull support
Future-proofTranslation debtApple-recommended
DebuggingGL tools onlyGPU Frame Capture
Thermal/batteryHigherOptimizable

When MetalANGLE Fails

MetalANGLE will NOT work if your code:

  • Uses OpenGL ES extensions not in core ES 2/3
  • Relies on compute shaders (GL_COMPUTE_SHADER)
  • Requires precise GL state machine semantics
  • Needs performance within 10% of native
  • Targets visionOS (no translation layer support)

Pattern 2: Native Metal Rewrite (Production Path)

When to use: Production apps, performance-critical rendering, long-term maintenance

Phased Migration Strategy

Phase 1: Abstraction Layer (1-2 weeks)
├─ Create renderer interface hiding GL/Metal specifics
├─ Keep GL implementation as reference
├─ Define clear boundaries: setup, resources, draw, present
└─ Validate abstraction with existing tests

Phase 2: Metal Backend (2-4 weeks)
├─ Implement Metal renderer behind same interface
├─ Convert shaders GLSL → MSL (use metal-migration-ref)
├─ Run GL and Metal side-by-side for visual diff
├─ GPU Frame Capture for debugging
└─ Milestone: Feature parity, visual match

Phase 3: Optimization (1-2 weeks)
├─ Remove abstraction overhead where it hurts
├─ Use Metal-specific features (argument buffers, indirect)
├─ Profile with Metal System Trace
├─ Tune for thermal envelope and battery
└─ Remove GL backend entirely

GLSL to Metal Shading Language (MSL) Conversion

GLSLMSLNotes
attribute / varying[[stage_in]] structVertex attributes via struct
uniform[[buffer(N)]] parameterExplicit binding index
gl_PositionReturn float4 from vertexVertex function return value
gl_FragColorReturn float4 from fragmentFragment function return value
texture2D(tex, uv)tex.sample(sampler, uv)Separate sampler object
vec2/3/4float2/3/4Type names differ
mat4float4x4Matrix types differ
mix()mix()Same name
precision mediump float(not needed)Metal infers precision
#version 300 es#include <metal_stdlib>Different preamble

Example conversion:

// GLSL vertex shader
#version 300 es
uniform mat4 u_mvp;
in vec3 a_position;
in vec2 a_texCoord;
out vec2 v_texCoord;

void main() {
    v_texCoord = a_texCoord;
    gl_Position = u_mvp * vec4(a_position, 1.0);
}
// Equivalent MSL vertex shader
#include <metal_stdlib>
using namespace metal;

struct VertexIn {
    float3 position [[attribute(0)]];
    float2 texCoord [[attribute(1)]];
};

struct VertexOut {
    float4 position [[position]];
    float2 texCoord;
};

struct Uniforms {
    float4x4 mvp;
};

vertex VertexOut vertexShader(VertexIn in [[stage_in]],
                              constant Uniforms &uniforms [[buffer(1)]]) {
    VertexOut out;
    out.texCoord = in.texCoord;
    out.position = uniforms.mvp * float4(in.position, 1.0);
    return out;
}

Key differences to watch:

  • GLSL globals → MSL function parameters with [[attribute]] qualifiers
  • Implicit uniform binding → explicit [[buffer(N)]] indices
  • sampler2D combines texture+sampler → Metal separates texture2d and sampler
  • GLSL preprocessor → Metal uses C++ #include and using namespace metal

Core Architecture Differences

ConceptOpenGLMetal
State modelImplicit, mutableExplicit, immutable PSO
ValidationAt draw timeAt PSO creation
Shader compilationRuntime (JIT)Build time (AOT)
Command submissionImplicitExplicit command buffers
Resource bindingGlobal statePer-encoder binding
SynchronizationDriver-managedApp-managed

MTKView Setup (Native Metal)

import MetalKit

class MetalRenderer: NSObject, MTKViewDelegate {
    let device: MTLDevice
    let commandQueue: MTLCommandQueue
    var pipelineState: MTLRenderPipelineState!

    init?(metalView: MTKView) {
        guard let device = MTLCreateSystemDefaultDevice(),
              let queue = device.makeCommandQueue() else {
            return nil
        }
        self.device = device
        self.commandQueue = queue

        metalView.device = device
        metalView.clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 1)
        metalView.depthStencilPixelFormat = .depth32Float

        super.init()
        metalView.delegate = self

        buildPipeline(metalView: metalView)
    }

    private func buildPipeline(metalView: MTKView) {
        let library = device.makeDefaultLibrary()!
        let vertexFunction = library.makeFunction(name: "vertexShader")
        let fragmentFunction = library.makeFunction(name: "fragmentShader")

        let descriptor = MTLRenderPipelineDescriptor()
        descriptor.vertexFunction = vertexFunction
        descriptor.fragmentFunction = fragmentFunction
        descriptor.colorAttachments[0].pixelFormat = metalView.colorPixelFormat
        descriptor.depthAttachmentPixelFormat = metalView.depthStencilPixelFormat

        // Pre-validated at creation, not at draw time
        pipelineState = try! device.makeRenderPipelineState(descriptor: descriptor)
    }

    func draw(in view: MTKView) {
        guard let drawable = view.currentDrawable,
              let descriptor = view.currentRenderPassDescriptor,
              let commandBuffer = commandQueue.makeCommandBuffer(),
              let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else {
            return
        }

        encoder.setRenderPipelineState(pipelineState)
        // Bind resources explicitly - nothing persists between draws
        encoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
        encoder.setFragmentTexture(texture, index: 0)
        encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: vertexCount)
        encoder.endEncoding()

        commandBuffer.present(drawable)
        commandBuffer.commit()
    }
}

Common Migration Anti-Patterns

Anti-Pattern 1: Keeping GL State Machine Mentality

BAD — Thinking in GL's implicit state:

// GL mental model: "set state, then draw"
glBindTexture(GL_TEXTURE_2D, texture)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glUseProgram(program)
glDrawArrays(GL_TRIANGLES, 0, vertexCount)
// State persists until changed — can draw again without rebinding

GOOD — Metal's explicit model:

// Metal: encode everything explicitly per draw
let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: rpd)!
encoder.setRenderPipelineState(pipelineState)    // Always set
encoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)  // Always bind
encoder.setFragmentTexture(texture, index: 0)    // Always bind
encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: count)
encoder.endEncoding()
// Nothing persists — next encoder starts fresh

Time cost: 30-60 min debugging "why did my texture disappear" vs 2 min understanding the model upfront.

Anti-Pattern 2: Ignoring Coordinate System Differences

BAD — Assuming GL coordinates work in Metal:

OpenGL:
- Origin: bottom-left
- Y-axis: up
- NDC Z range: [-1, 1]
- Texture origin: bottom-left

Metal:
- Origin: top-left
- Y-axis: down
- NDC Z range: [0, 1]
- Texture origin: top-left

GOOD — Explicit coordinate handling:

// Option 1: Flip Y in vertex shader
vertex float4 vertexShader(VertexIn in [[stage_in]]) {
    float4 pos = uniforms.mvp * float4(in.position, 1.0);
    pos.y = -pos.y;  // Flip Y for Metal's coordinate system
    return pos;
}

// Option 2: Flip texture coordinates in fragment shader
fragment float4 fragmentShader(VertexOut in [[stage_in]],
                                texture2d<float> tex [[texture(0)]],
                                sampler samp [[sampler(0)]]) {
    float2 uv = in.texCoord;
    uv.y = 1.0 - uv.y;  // Flip V for Metal's texture origin
    return tex.sample(samp, uv);
}
// Option 3: Use MTKTextureLoader with origin option
let options: [MTKTextureLoader.Option: Any] = [
    .origin: MTKTextureLoader.Origin.bottomLeft  // Match GL convention
]
let texture = try textureLoader.newTexture(URL: url, options: options)

Time cost: 2-4 hours debugging "upside down" or "mirrored" rendering vs 5 min reading this pattern.

Anti-Pattern 3: No Validation Layer During Development

BAD — Disabling validation for "performance":

// No validation — API misuse silently corrupts or crashes later

GOOD — Always enable during development:

In Xcode: Edit Scheme → Run → Diagnostics
✓ Metal API Validation
✓ Metal Shader Validation
✓ GPU Frame Capture (Metal)

Time cost: Hours debugging silent corruption vs immediate error messages with call stacks.

Anti-Pattern 4: Single Buffer Without Synchronization

BAD — CPU and GPU fight over same buffer:

// Frame N: CPU writes to buffer
// Frame N: GPU reads from buffer
// Frame N+1: CPU writes again — RACE CONDITION
buffer.contents().copyMemory(from: data, byteCount: size)

GOOD — Triple buffering with semaphore:

class TripleBufferedRenderer {
    let inflightSemaphore = DispatchSemaphore(value: 3)
    var buffers: [MTLBuffer] = []
    var bufferIndex = 0

    func draw(in view: MTKView) {
        // Wait for a buffer to become available
        inflightSemaphore.wait()

        let buffer = buffers[bufferIndex]
        // Safe to write — GPU finished with this buffer
        buffer.contents().copyMemory(from: data, byteCount: size)

        let commandBuffer = commandQueue.makeCommandBuffer()!
        commandBuffer.addCompletedHandler { [weak self] _ in
            self?.inflightSemaphore.signal()  // Release buffer
        }

        // ... encode and commit

        bufferIndex = (bufferIndex + 1) % 3
    }
}

Time cost: Hours debugging intermittent visual glitches vs 15 min implementing triple buffering.

Pressure Scenarios

Scenario 1: "Just Ship with MetalANGLE"

Situation: Deadline in 2 weeks. MetalANGLE demo works. PM says ship it.

Pressure: "We can optimize later. Users won't notice 20% overhead."

Why this fails:

  • Translation overhead compounds with complex scenes (visualizers, games)
  • No compute shader support limits future features
  • Technical debt grows — team learns MetalANGLE quirks, not Metal
  • Apple deprecation risk (OpenGL ES deprecated since iOS 12)
  • Battery/thermal complaints from users

Response template:

"MetalANGLE is viable for the demo milestone. For production, I recommend a 3-week buffer to implement native Metal for the render loop. This recovers the 20-30% overhead and eliminates deprecation risk. Can we scope the MVP to fewer visual effects to hit the deadline with native Metal?"

Scenario 2: "Port All Shaders This Sprint"

Situation: 50 GLSL shaders. Sprint is 2 weeks. Manager wants all converted.

Pressure: "They're just text files. How hard can shader conversion be?"

Why this fails:

  • GLSL → MSL isn't 1:1 (precision qualifiers, built-ins, sampling)
  • Each shader needs visual validation, not just compilation
  • Complex shaders need performance profiling
  • Bugs compound — broken shader A masks broken shader B

Response template:

"Shader conversion requires visual validation, not just compilation. I can convert 10-15 shaders/week with confidence. For 50 shaders: (1) Prioritize by usage — convert the 10 most-used first, (2) Automate mappings — type conversions, boilerplate, (3) Parallel validation — run GL and Metal side-by-side. Realistic timeline: 4-5 weeks for full conversion with quality."

Scenario 3: "We Don't Need GPU Frame Capture"

Situation: Developer says "I'll just use print statements to debug shaders."

Pressure: "GPU tools are overkill. I know what I'm doing."

Why this fails:

  • Print statements don't work in shaders
  • Visual bugs require seeing intermediate render targets
  • Performance issues require GPU timeline analysis
  • Metal validation errors need call stack context

Response template:

"GPU Frame Capture is the only way to inspect shader variables, see intermediate textures, and understand GPU timing. It takes 30 seconds to capture a frame. Without it, shader debugging is 10x slower — you're guessing instead of observing."

Pre-Migration Checklist

Before starting any port:

  • Inventory shaders: Count GLSL/HLSL files, complexity (LOC, features used)
  • Identify extensions: Which GL extensions does the code use? Metal equivalents?
  • Audit state management: How stateful is the renderer? Global state count?
  • Check compute usage: Any GL compute shaders? GPGPU? (MetalANGLE won't help)
  • Profile baseline: FPS, frame time, memory, thermal on reference platform
  • Define success criteria: Target FPS, memory budget, thermal envelope
  • Set up A/B testing: Can you run GL and Metal side-by-side for validation?
  • Enable validation: Metal API Validation, Shader Validation, Frame Capture

Post-Migration Checklist

After completing the port:

  • Visual parity: Side-by-side screenshots match reference
  • Performance parity or better: Frame time ≤ GL baseline
  • No validation errors: Clean run with Metal validation enabled
  • Thermal acceptable: Device doesn't throttle during normal use
  • Memory stable: No leaks over extended use
  • All code paths tested: Edge cases, error states, resize/rotate

Resources

WWDC: 2016-00602, 2018-00604, 2019-00611

Docs: /metal/migrating-opengl-code-to-metal, /metal/shader-converter

Tools: MetalANGLE, MoltenVK

Skills: axiom-metal-migration-ref, axiom-metal-migration-diag


Last Updated: 2025-12-29 Platforms: iOS 12+, macOS 10.14+, tvOS 12+ Status: Production-ready Metal migration patterns

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

25.31%
按下载量换算355

Codex

21.8%
按下载量换算305

OpenCode

19.01%
按下载量换算266

Antigravity

12.02%
按下载量换算168

Cursor

7.68%
按下载量换算108

windsurf

3.22%
按下载量换算45

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills