Files
lity3d/DESIGN.md
T
shuiyu1123 2d56cb3bc9 MiMoEngine ASM: x86-64 MASM汇编+C混合架构游戏引擎
核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2)
外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言
含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
2026-07-10 19:20:40 +08:00

30 KiB

GameEngineASM - x86-64 MASM + C 混合架构游戏引擎设计

1. 完整目录树

GameEngineASM/
├── GameEngineASM.sln
├── DESIGN.md
│
├── Engine/
│   ├── ASM/                          -- 汇编核心 (4 files)
│   │   ├── math.asm                  -- 向量/矩阵/四元数 SIMD 运算
│   │   ├── memory.asm                -- 对齐内存分配器
│   │   ├── string_ops.asm            -- 高速内存/字符串操作
│   │   └── profiling.asm             -- rdtsc 性能计时
│   │
│   ├── include/                      -- 共享头文件 (6 files)
│   │   ├── asm_math.inc              -- ASM 函数声明 (.inc for MASM)
│   │   ├── asm_math.h                -- C 端数学函数声明
│   │   ├── asm_memory.h              -- C 端内存分配器声明
│   │   ├── asm_string.h              -- C 端字符串操作声明
│   │   ├── asm_profiling.h           -- C 端性能计时声明
│   │   └── engine_types.h            -- 公共类型定义 (vec3, mat4, etc.)
│   │
│   ├── C/                            -- C 外层模块
│   │   ├── core/                     -- 核心系统 (6 files)
│   │   │   ├── engine.h
│   │   │   ├── engine.c
│   │   │   ├── platform.h
│   │   │   ├── platform.c
│   │   │   ├── logger.h
│   │   │   └── logger.c
│   │   │
│   │   ├── rendering/                -- DirectX 11 渲染 (8 files)
│   │   │   ├── renderer.h
│   │   │   ├── renderer.c
│   │   │   ├── dx11_device.h
│   │   │   ├── dx11_device.c
│   │   │   ├── shader.h
│   │   │   ├── shader.c
│   │   │   ├── mesh.h
│   │   │   └── mesh.c
│   │   │
│   │   ├── ecs/                      -- 实体组件系统 (6 files)
│   │   │   ├── ecs.h
│   │   │   ├── ecs.c
│   │   │   ├── component_registry.h
│   │   │   ├── component_registry.c
│   │   │   ├── system_manager.h
│   │   │   └── system_manager.c
│   │   │
│   │   ├── physics/                  -- 物理系统 (4 files)
│   │   │   ├── physics.h
│   │   │   ├── physics.c
│   │   │   ├── collision.h
│   │   │   └── collision.c
│   │   │
│   │   ├── resources/                -- 资源管理 (4 files)
│   │   │   ├── resource_manager.h
│   │   │   ├── resource_manager.c
│   │   │   ├── file_loader.h
│   │   │   └── file_loader.c
│   │   │
│   │   ├── scene/                    -- 场景管理 (4 files)
│   │   │   ├── scene.h
│   │   │   ├── scene.c
│   │   │   ├── scene_node.h
│   │   │   └── scene_node.c
│   │   │
│   │   ├── audio/                    -- XAudio2 音频 (4 files)
│   │   │   ├── audio.h
│   │   │   ├── audio.c
│   │   │   ├── audio_source.h
│   │   │   └── audio_source.c
│   │   │
│   │   ├── ui/                       -- UI 系统 (4 files)
│   │   │   ├── ui.h
│   │   │   ├── ui.c
│   │   │   ├── ui_widget.h
│   │   │   └── ui_widget.c
│   │   │
│   │   └── scripting/                -- Lua 脚本 (4 files)
│   │       ├── scripting.h
│   │       ├── scripting.c
│   │       ├── lua_bindgen.h
│   │       └── lua_bindgen.c
│   │
│   └── lib/                          -- 预编译库 (3 files)
│       ├── lua54.lib
│       ├── d3d11.lib
│       └── d3dcompiler.lib
│
├── Demo/                             -- 演示程序 (3 files)
│   ├── main.c
│   ├── demo_scene.c
│   └── demo_scene.h
│
└── Build/                            -- 构建配置 (3 files)
    ├── GameEngineASM.vcxproj
    ├── GameEngineASM.vcxproj.filters
    └── GameEngineASM.props

总文件数: 58 files


2. 关键 ASM 函数签名

2.1 math.asm — SIMD 数学库

; ============================================================
; math.asm - SSE4.1/AVX2 向量矩阵数学库
; 与 C 互操作: Windows x64 calling convention
; 输入: RCX, RDX, R8, R9 (整数/指针), XMM0-XMM3 (浮点)
; 返回: 整数在 RAX, 浮点在 XMM0
; ============================================================

; --- Vector2 操作 (float x, float y) ---

; float vec2_dot(vec2 a, vec2 b)
; RCX = ptr to vec2 a, RDX = ptr to vec2 b
; Returns: XMM0 = dot product
vec2_dot PROC
    movups  xmm0, xmmword ptr [rcx]      ; load a.x, a.y
    movups  xmm1, xmmword ptr [rdx]      ; load b.x, b.y
    mulps   xmm0, xmm1                    ; element-wise multiply
    ;水 平 求 和: xmm0 = (a.x*b.x, a.y*b.y)
    ; 需要水平加法
    movshdup xmm1, xmm0                   ; xmm1 = (a.y*b.y, a.y*b.y)
    addps   xmm0, xmm1                    ; xmm0 = (a.x*b.x + a.y*b.y, ...)
    ret
vec2_dot ENDP

; void vec2_normalize(vec2* out, vec2 in)
; RCX = ptr out, XMM0 = in.x, XMM1 = in.y
vec2_normalize PROC
    ; pack xmm0,xmm1 -> xmm2
    unpcklps xmm2, xmm0, xmm1            ; xmm2 = (in.x, in.y)
    movaps  xmm3, xmm2                    ; save
    mulps   xmm2, xmm2                    ; square
    ; horizontal sum
    movshdup xmm4, xmm2
    addps   xmm2, xmm4                    ; len_sq
    sqrtss  xmm2, xmm2                    ; len
    shufps  xmm2, xmm2, 0                ; broadcast
    divps   xmm3, xmm2                    ; normalize
    movups  xmmword ptr [rcx], xmm3       ; store
    ret
vec2_normalize ENDP

; --- Vector3 操作 (float x, y, z, pad) ---

; float vec3_dot(vec3 a, vec3 b)
vec3_dot PROC
    movups  xmm0, xmmword ptr [rcx]
    movups  xmm1, xmmword ptr [rdx]
    mulps   xmm0, xmm1
    ; horizontal sum 3 components
    movshdup xmm2, xmm0
    addps   xmm0, xmm2
    movhlps xmm2, xmm0
    addss   xmm0, xmm2
    ret
vec3_dot ENDP

; void vec3_cross(vec3* out, vec3 a, vec3 b)
; RCX = out, XMM0 = a, XMM1 = b (packed xyz)
vec3_cross PROC
    ; a = (ax, ay, az), b = (bx, by, bz)
    ; result = (ay*bz - az*by, az*bx - ax*bz, ax*by - ay*bx)
    movaps  xmm2, xmm0                    ; a
    movaps  xmm3, xmm1                    ; b

    shufps  xmm4, xmm2, xmm2, 0C9h       ; a.yzx
    shufps  xmm5, xmm3, xmm3, 0C9h       ; b.yzx

    mulps   xmm4, xmm3                    ; a.yzx * b
    mulps   xmm5, xmm2                    ; b.yzx * a

    subps   xmm4, xmm5                    ; cross

    ; store xyz
    movlps  qword ptr [rcx], xmm4
    shufps  xmm4, xmm4, 02h
    movss   dword ptr [rcx+8], xmm4
    ret
vec3_cross ENDP

; void vec3_normalize(vec3* out, vec3 v)
vec3_normalize PROC
    movups  xmm0, xmmword ptr [rcx]      ; load v
    movaps  xmm1, xmm0
    mulps   xmm1, xmm1                    ; v*v
    ; horizontal sum
    movshdup xmm2, xmm1
    addps   xmm1, xmm2
    movhlps xmm2, xmm1
    addss   xmm1, xmm2
    sqrtss  xmm1, xmm1                    ; len
    shufps  xmm1, xmm1, 0                ; broadcast
    divps   xmm0, xmm1
    movups  xmmword ptr [rcx], xmm0
    ret
vec3_normalize ENDP

; void vec3_lerp(vec3* out, vec3 a, vec3 b, float t)
; RCX=out, XMM0=a(xyz), XMM1=b(xyz), XMM2=t
vec3_lerp PROC
    subps   xmm1, xmm0                    ; b - a
    shufps  xmm2, xmm2, 0                ; broadcast t
    mulps   xmm1, xmm2                    ; t * (b-a)
    addps   xmm0, xmm1                    ; a + t*(b-a)
    movups  xmmword ptr [rcx], xmm0
    ret
vec3_lerp ENDP

; --- Vector4 操作 ---

; float vec4_dot(vec4 a, vec4 b)
vec4_dot PROC
    movups  xmm0, xmmword ptr [rcx]
    movups  xmm1, xmmword ptr [rdx]
    mulps   xmm0, xmm1
    ; horizontal sum 4
    movhlps xmm1, xmm0
    addps   xmm0, xmm1
    movshdup xmm1, xmm0
    addss   xmm0, xmm1
    ret
vec4_dot ENDP

; --- Matrix4x4 操作 (16 floats, row-major) ---

; void mat4_identity(mat4* out)
mat4_identity PROC
    vxorps  xmm0, xmm0, xmm0
    movups  xmmword ptr [rcx], xmm0
    movups  xmmword ptr [rcx+16], xmm0
    movups  xmmword ptr [rcx+32], xmm0
    movups  xmmword ptr [rcx+48], xmm0
    movss   dword ptr [rcx],    (1.0)     ; [0][0] = 1
    movss   dword ptr [rcx+20], (1.0)     ; [1][1] = 1
    movss   dword ptr [rcx+40], (1.0)     ; [2][2] = 1
    movss   dword ptr [rcx+60], (1.0)     ; [3][3] = 1
    ret
mat4_identity ENDP

; void mat4_multiply(mat4* out, mat4* a, mat4* b)
; AVX2: 8-wide FMA
mat4_multiply PROC
    ; 保存非易失寄存器
    push    rbx
    sub     rsp, 20h

    ; RCX = out, RDX = a, R8 = b
    mov     rbx, rcx
    mov     rsi, rdx
    mov     rdi, r8

    ; 对矩阵 a 的每一行, 与矩阵 b 的所有列做点积
    ; 逐行处理 a
    vmovups ymm0, ymmword ptr [rsi]        ; a row 0 (y0)
    vmovups ymm2, ymmword ptr [rsi+32]     ; a row 1
    vmovups ymm4, ymmword ptr [rsi+64]     ; a row 2
    vmovups ymm6, ymmword ptr [rsi+96]     ; a row 3

    ; 对每一列 b 计算 out 行
    ; Column 0 of b
    vbroadcastss ymm1, dword ptr [rdi]
    vbroadcastss ymm3, dword ptr [rdi+4]
    vbroadcastss ymm5, dword ptr [rdi+8]
    vbroadcastss ymm7, dword ptr [rdi+12]

    vfmadd231ps ymm0, ymm1, ymm0          ; row0 += col0 * row0
    ; ... (简化, 完整实现需 4x4=16 次 FMA)

    vmovups ymmword ptr [rbx], ymm0
    ; ... 其余行

    add     rsp, 20h
    pop     rbx
    ret
mat4_multiply ENDP

; void mat4_transpose(mat4* out, mat4* m)
mat4_transpose PROC
    vmovups ymm0, ymmword ptr [rdx]        ; row 0,1
    vmovups ymm1, ymmword ptr [rdx+32]     ; row 2,3
    vunpcklps ymm2, ymm0, ymm1            ; unpack low
    vunpckhps ymm3, ymm0, ymm1            ; unpack high
    vunpcklps ymm4, ymm2, ymm3
    vunpckhps ymm5, ymm2, ymm3
    vmovups ymmword ptr [rcx], ymm4
    vmovups ymmword ptr [rcx+32], ymm5
    ret
mat4_transpose ENDP

; bool mat4_inverse(mat4* out, mat4* m)  -- 返回是否可逆
; 使用 SIMD 优化的 Gauss-Jordan 消元
mat4_inverse PROC
    ; 完整实现约 200 行, 使用 AVX2 + FMA
    ; 核心: 增广矩阵 [m|I] 行变换
    push    rbx
    push    rbp
    sub     rsp, 40h

    ; ... 完整 SIMD inverse 实现

    mov     al, 1                        ; assume success
    add     rsp, 40h
    pop     rbp
    pop     rbx
    ret
mat4_inverse ENDP

; --- Quaternion 操作 (4 floats: x, y, z, w) ---

; void quat_multiply(quat* out, quat* a, quat* b)
quat_multiply PROC
    movups  xmm0, xmmword ptr [rcx]      ; a = (ax,ay,az,aw)
    movups  xmm1, xmmword ptr [rdx]      ; b = (bx,by,bz,bw)
    ; Hamilton product
    ; result = (aw*b + bw*a + cross(a.xyz, b.xyz), aw*bw - dot(a.xyz,b.xyz))
    movaps  xmm2, xmm0
    shufps  xmm2, xmm2, 0FFh             ; broadcast aw
    mulps   xmm2, xmm1                    ; aw * b

    movaps  xmm3, xmm1
    shufps  xmm3, xmm3, 0FFh             ; broadcast bw
    mulps   xmm3, xmm0                    ; bw * a

    ; cross product of xyz
    ; ... (同 vec3_cross)

    addps   xmm2, xmm3
    ; w = aw*bw - dot(ax*bx + ay*by + az*bz)
    ; store result
    movups  xmmword ptr [rcx], xmm2
    ret
quat_multiply ENDP

; void quat_rotate_vec3(vec3* out, quat* q, vec3* v)
; 使用旋转公式: v' = q * v * q^-1
; 优化公式: v' = v + 2w(q.xyz x v) + 2(q.xyz x (q.xyz x v))
quat_rotate_vec3 PROC
    ; ... AVX2 优化实现
    ret
quat_rotate_vec3 ENDP

2.2 memory.asm — 对齐内存分配器

; ============================================================
; memory.asm - SIMD 对齐内存分配器
; ============================================================

; void* mem_aligned_alloc(size_t size, size_t alignment)
; RCX = size, RDX = alignment (must be power of 2, >= 16)
; Returns: RAX = aligned pointer (or NULL on failure)
; 实现: 分配 size + alignment + sizeof(void*), 返回对齐后的指针
; 在对齐指针前存储原始 malloc 指针
mem_aligned_alloc PROC
    push    rbx
    push    rdi
    sub     rsp, 28h

    mov     rbx, rcx                     ; size
    mov     rdi, rdx                     ; alignment

    ; total = size + alignment + 8 (for storing original ptr)
    lea     rcx, [rbx + rdi + 8]
    call    malloc                       ; 调用 CRT malloc

    test    rax, rax
    jz      .fail

    ; 计算对齐指针
    mov     rcx, rax
    add     rcx, 8                       ; skip storing space
    ; align up
    lea     rdx, [rdi - 1]
    not     rdx
    add     rcx, rdx
    and     rcx, rdx                     ; aligned ptr

    ; 存储原始指针 (aligned_ptr - 8)
    mov     [rcx - 8], rax

    mov     rax, rcx
    jmp     .done

.fail:
    xor     eax, eax

.done:
    add     rsp, 28h
    pop     rdi
    pop     rbx
    ret
mem_aligned_alloc ENDP

; void mem_aligned_free(void* ptr)
; RCX = aligned pointer
mem_aligned_free PROC
    test    rcx, rcx
    jz      .done
    mov     rcx, qword ptr [rcx - 8]    ; recover original ptr
    call    free
.done:
    ret
mem_aligned_free ENDP

; void* mem_aligned_realloc(void* ptr, size_t new_size)
mem_aligned_realloc PROC
    ; ... 类似 alloc 但使用 realloc
    ret
mem_aligned_realloc ENDP

2.3 string_ops.asm — 高速字符串/内存操作

; ============================================================
; string_ops.asm - 高速内存/字符串操作
; 使用 REP MOVSB (ERMS) + SSE 优化
; ============================================================

; void fast_memcpy(void* dst, const void* src, size_t count)
; RCX=dst, RDX=src, R8=count
; 对齐后使用 SSE2 movdqa 批量复制
fast_memcpy PROC
    push    rdi
    push    rsi
    push    rbx

    mov     rdi, rcx
    mov     rsi, rdx
    mov     rcx, r8

    cmp     rcx, 64
    jb      .small_copy

    ; 大块复制: 对齐到 16 字节后用 movdqa
    ; 先复制前几字节直到对齐
    mov     rax, rdi
    and     rax, 0Fh
    jz      .aligned
    mov     rdx, 16
    sub     rdx, rax
    rep     movsb
    sub     rcx, rdx

.aligned:
    ; 以 64 字节为单位批量复制
    mov     rdx, rcx
    shr     rcx, 2                       ; count / 4 (64 bytes each)
    jz      .tail

.loop_64:
    movdqa  xmm0, xmmword ptr [rsi]
    movdqa  xmm1, xmmword ptr [rsi+16]
    movdqa  xmm2, xmmword ptr [rsi+32]
    movdqa  xmm3, xmmword ptr [rsi+48]
    movdqa  xmmword ptr [rdi], xmm0
    movdqa  xmmword ptr [rdi+16], xmm1
    movdqa  xmmword ptr [rdi+32], xmm2
    movdqa  xmmword ptr [rdi+48], xmm3
    add     rsi, 64
    add     rdi, 64
    dec     rcx
    jnz     .loop_64

    and     rdx, 3Fh                     ; remaining bytes
    mov     rcx, rdx

.tail:
    rep     movsb

    pop     rbx
    pop     rsi
    pop     rdi
    ret

.small_copy:
    rep     movsb
    pop     rbx
    pop     rsi
    pop     rdi
    ret
fast_memcpy ENDP

; void fast_memset(void* dst, int val, size_t count)
; 使用 SSE2 批量填充
fast_memset PROC
    push    rdi
    push    rcx

    mov     rdi, rcx
    mov     rax, rdx
    mov     rcx, r8

    ; 广播 val 到 xmm0 的所有字节
    movd    xmm0, edx
    pshufd  xmm0, xmm0, 0

    cmp     rcx, 32
    jb      .small_set

    ; 对齐
    mov     rax, rdi
    and     rax, 0Fh
    jz      .aligned_set
    mov     rdx, 16
    sub     rdx, rax
    rep     stosb
    sub     rcx, rdx

.aligned_set:
    mov     rdx, rcx
    shr     rcx, 1                       ; 32 bytes per iteration

.loop_set:
    movdqa  xmmword ptr [rdi], xmm0
    movdqa  xmmword ptr [rdi+16], xmm0
    add     rdi, 32
    dec     rcx
    jnz     .loop_set

    and     rdx, 1Fh
    mov     rcx, rdx

.small_set:
    rep     stosb

    pop     rcx
    pop     rdi
    ret
fast_memset ENDP

; int fast_strcmp(const char* a, const char* b)
; SSE4.2PCMPESTRI 逐 16 字节比较
fast_strcmp PROC
    push    rbx

.loop_strcmp:
    movdqu  xmm0, xmmword ptr [rcx]
    movdqu  xmm1, xmmword ptr [rdx]

    ; SSE4.2 字符串比较: 找到第一个不匹配位置
    pcmpestrm xmm0, xmm1, 18h          ; EqualAny, unsigned bytes
    ; ... (具体利用 SSE4.2 字符串指令)

    ; 简化版本: 逐字节 fallback
    mov     al, byte ptr [rcx]
    cmp     al, byte ptr [rdx]
    jne     .not_equal
    test    al, al
    jz      .equal
    inc     rcx
    inc     rdx
    jmp     .loop_strcmp

.not_equal:
    movzx   eax, al
    movzx   edx, byte ptr [rdx]
    sub     eax, edx
    pop     rbx
    ret

.equal:
    xor     eax, eax
    pop     rbx
    ret
fast_strcmp ENDP

; size_t fast_strlen(const char* str)
fast_strlen PROC
    mov     rax, rcx
    pxor    xmm0, xmm0

.loop_strlen:
    movdqu  xmm1, xmmword ptr [rax]
    pcmpestrm xmm1, xmm0, 08h          ; Least Significant Byte, imm8=08h
    jc      .found
    add     rax, 16
    jmp     .loop_strlen

.found:
    ; 在返回的掩码中找第一个 1
    pmovmskb edx, xmm1
    tzcnt   edx, edx
    add     rax, rdx
    sub     rax, rcx                     ; length = end - start
    ret
fast_strlen ENDP

2.4 profiling.asm — rdtsc 性能计时

; ============================================================
; profiling.asm - rdtsc 高精度计时
; ============================================================

; uint64_t prof_rdtsc(void)
; 返回 TSC 值
prof_rdtsc PROC
    lfence
    rdtsc
    shl     rdx, 32
    or      rax, rdx
    ret
prof_rdtsc ENDP

; uint64_t prof_rdtscp(void)
; 无序读取, 更快但可能不精确
prof_rdtscp PROC
    rdtscp
    shl     rdx, 32
    or      rax, rdx
    ret
prof_rdtscp ENDP

; double prof_cycles_to_ms(uint64_t cycles)
; 将 TSC cycles 转换为毫秒 (需要 CPU 频率)
; RCX = cycles
; Returns: XMM0 = milliseconds
prof_cycles_to_ms PROC
    vcvttsd2si rax, xmm0               ; ... 保存输入
    ; 假设 CPU 频率存储在全局变量 cpu_freq_ghz
    vmovsd  xmm0, qword ptr [cpu_freq_mhz]
    vcvtsi2sd xmm1, xmm1, rcx
    vdivsd  xmm0, xmm1, xmm0           ; cycles / mhz = ms
    vdivsd  xmm0, xmm0, (1000.0)       ; / 1000 for seconds, but we want ms
    ; 实际: ms = cycles / (cpu_mhz * 1000)
    ret
prof_cycles_to_ms ENDP

; void prof_calibrate_frequency(void)
; 通过 QueryPerformanceCounter 校准 TSC 频率
prof_calibrate_frequency PROC
    sub     rsp, 28h

    ; QueryPerformanceFrequency
    lea     rcx, qword ptr [freq_large]
    call    QueryPerformanceFrequency

    ; 用 rdtsc 采样
    call    prof_rdtsc
    mov     rbx, rax

    ; Sleep(100ms)
    mov     ecx, 100
    call    Sleep

    call    prof_rdtsc
    sub     rax, rbx                     ; elapsed cycles

    ; cpu_mhz = elapsed_cycles / (freq * 0.1s)
    ; ...

    add     rsp, 28h
    ret
prof_calibrate_frequency ENDP

.data
    cpu_freq_mhz  dq 0
    freq_large    dq 0

3. C 端头文件 (暴露 ASM 函数)

3.1 engine_types.h — 公共类型

#ifndef ENGINE_TYPES_H
#define ENGINE_TYPES_H

#include <stdint.h>
#include <stdbool.h>

typedef union Vec2 {
    struct { float x, y; };
    float m[2];
} Vec2;

typedef union Vec3 {
    struct { float x, y, z, _pad; };
    float m[4];  // 16-byte aligned
} Vec3;

typedef union Vec4 {
    struct { float x, y, z, w; };
    float m[4];
} Vec4;

typedef union Mat4 {
    float m[16];
    float mm[4][4];
} Mat4;

typedef union Quat {
    struct { float x, y, z, w; };
    float m[4];
} Quat;

#endif

3.2 asm_math.h

#ifndef ASM_MATH_H
#define ASM_MATH_H

#include "engine_types.h"

#ifdef __cplusplus
extern "C" {
#endif

// Vector2
float   vec2_dot(Vec2 a, Vec2 b);
Vec2    vec2_add(Vec2 a, Vec2 b);
Vec2    vec2_sub(Vec2 a, Vec2 b);
Vec2    vec2_scale(Vec2 v, float s);
Vec2    vec2_normalize(Vec2 v);
float   vec2_length(Vec2 v);

// Vector3
float   vec3_dot(Vec3 a, Vec3 b);
Vec3    vec3_cross(Vec3 a, Vec3 b);
Vec3    vec3_add(Vec3 a, Vec3 b);
Vec3    vec3_sub(Vec3 a, Vec3 b);
Vec3    vec3_scale(Vec3 v, float s);
Vec3    vec3_normalize(Vec3 v);
float   vec3_length(Vec3 v);
Vec3    vec3_lerp(Vec3 a, Vec3 b, float t);

// Vector4
float   vec4_dot(Vec4 a, Vec4 b);
Vec4    vec4_add(Vec4 a, Vec4 b);
Vec4    vec4_sub(Vec4 a, Vec4 b);
Vec4    vec4_scale(Vec4 v, float s);

// Matrix4x4
void    mat4_identity(Mat4* out);
void    mat4_multiply(Mat4* out, Mat4* a, Mat4* b);
void    mat4_transpose(Mat4* out, Mat4* m);
bool    mat4_inverse(Mat4* out, Mat4* m);
void    mat4_translate(Mat4* out, Vec3 v);
void    mat4_scale(Mat4* out, Vec3 s);
void    mat4_rotate_x(Mat4* out, float radians);
void    mat4_rotate_y(Mat4* out, float radians);
void    mat4_rotate_z(Mat4* out, float radians);
Mat4    mat4_perspective(float fov, float aspect, float near, float far);
Mat4    mat4_ortho(float left, float right, float bottom, float top, float near, float far);
Mat4    mat4_look_at(Vec3 eye, Vec3 center, Vec3 up);

// Quaternion
Quat    quat_identity(void);
Quat    quat_multiply(Quat a, Quat b);
Quat    quat_normalize(Quat q);
Quat    quat_conjugate(Quat q);
Quat    quat_from_axis_angle(Vec3 axis, float angle);
Vec3    quat_rotate_vec3(Quat q, Vec3 v);
Mat4    quat_to_mat4(Quat q);

// SSE intrinsics for direct C use (optional, for tight loops)
#ifdef __SSE4_1__
#include <smmintrin.h>
static inline float fast_vec3_dot_sse(Vec3 a, Vec3 b) {
    __m128 va = _mm_load_ps(a.m);
    __m128 vb = _mm_load_ps(b.m);
    __m128 mul = _mm_mul_ps(va, vb);
    __m128 shuf = _mm_movehdup_ps(mul);
    __m128 sums = _mm_add_ps(mul, shuf);
    shuf = _mm_movehl_ps(shuf, sums);
    sums = _mm_add_ss(sums, shuf);
    return _mm_cvtss_f32(sums);
}
#endif

#ifdef __cplusplus
}
#endif

#endif

3.3 asm_memory.h

#ifndef ASM_MEMORY_H
#define ASM_MEMORY_H

#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

void*   mem_aligned_alloc(size_t size, size_t alignment);
void    mem_aligned_free(void* ptr);
void*   mem_aligned_realloc(void* ptr, size_t new_size);
size_t  mem_get_alignment(void* ptr);

// SIMD 块分配: 一次分配多个对齐对象
void*   mem_aligned_alloc_batch(size_t count, size_t elem_size, size_t alignment);

#ifdef __cplusplus
}
#endif

#endif

3.4 asm_string.h

#ifndef ASM_STRING_H
#define ASM_STRING_H

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

void    fast_memcpy(void* dst, const void* src, size_t count);
void    fast_memset(void* dst, int val, size_t count);
int     fast_strcmp(const char* a, const char* b);
int     fast_strncmp(const char* a, const char* b, size_t n);
size_t  fast_strlen(const char* str);
char*   fast_strchr(const char* str, int c);
char*   fast_strcpy(char* dst, const char* src);

#ifdef __cplusplus
}
#endif

#endif

3.5 asm_profiling.h

#ifndef ASM_PROFILING_H
#define ASM_PROFILING_H

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

uint64_t    prof_rdtsc(void);
uint64_t    prof_rdtscp(void);
double      prof_cycles_to_ms(uint64_t cycles);
uint64_t    prof_calibrate_frequency(void);
double      prof_get_cpu_ghz(void);

// 便捷宏
#define PROF_BEGIN()    uint64_t _prof_start = prof_rdtsc()
#define PROF_END()      prof_cycles_to_ms(prof_rdtsc() - _prof_start)

#ifdef __cplusplus
}
#endif

#endif

4. 构建配置 (Visual Studio MASM 集成)

4.1 GameEngineASM.props — MASM 属性表

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemDefinitionGroup>
    <BuildCustomizations>
      <MASm>
        <AdditionalOptions>/Zi /nologo /Fl /Sa</AdditionalOptions>
        <IncludePaths>$(ProjectDir)Engine\include</IncludePaths>
        <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
        <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
        <Optimizations>FullSpeedOptimizations</Optimizations>
      </MASm>
    </BuildCustomizations>

    <ClCompile>
      <AdditionalIncludeDirectories>$(ProjectDir)Engine\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <Optimization>Full</Optimization>
      <AdditionalOptions>/arch:AVX2 /fp:fast</AdditionalOptions>
      <WarningLevel>Level4</WarningLevel>
    </ClCompile>

    <Link>
      <AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;d3d11.lib;xaudio2.lib;lua54.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <AdditionalLibraryDirectories>$(ProjectDir)Engine\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
    </Link>
  </ItemDefinitionGroup>
</Project>

4.2 GameEngineASM.vcxproj — 关键片段

<!-- 引入 MASM 自定义构建规则 -->
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />

<!-- .asm 文件编译 -->
<ItemGroup>
  <MASM Include="Engine\ASM\math.asm">
    <ExcludedFromBuild>false</ExcludedFromBuild>
  </MASM>
  <MASM Include="Engine\ASM\memory.asm" />
  <MASM Include="Engine\ASM\string_ops.asm" />
  <MASM Include="Engine\ASM\profiling.asm" />
</ItemGroup>

<!-- C 源文件 -->
<ItemGroup>
  <ClCompile Include="Engine\C\core\engine.c" />
  <ClCompile Include="Engine\C\core\platform.c" />
  <ClCompile Include="Engine\C\rendering\renderer.c" />
  <!-- ... 其余 C 文件 -->
</ItemGroup>

<!-- 头文件 -->
<ItemGroup>
  <ClInclude Include="Engine\include\*.h" />
  <None Include="Engine\include\asm_math.inc" />
</ItemGroup>

<!-- 导出 MASM 属性 -->
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />

4.3 ml64.exe 编译命令行

ml64.exe /c /nologo /W3 /Zi /Fo"$(OutDir)%(FileName).obj" /Fl"$(OutDir)%(FileName).lst" %(AdditionalInputs) %(AdditionalOptions)

5. 实施顺序 (按依赖关系)

Phase 1: 基础设施 (Week 1)

序号 任务 优先级 预计时间
1.1 创建项目结构和 VS 解决方案 P0 2h
1.2 配置 MASM 构建规则 (.props, .vcxproj) P0 2h
1.3 实现 engine_types.h 公共类型 P0 1h
1.4 实现 string_ops.asm (memcpy/memset/strlen) P0 4h
1.5 实现 memory.asm 对齐分配器 P0 3h
1.6 实现 profiling.asm 计时器 P0 2h

Phase 2: 数学库 (Week 1-2)

序号 任务 优先级 预计时间
2.1 math.asm — Vec2 基础操作 P0 3h
2.2 math.asm — Vec3 基础操作 P0 3h
2.3 math.asm — Vec4 基础操作 P0 2h
2.4 math.asm — Mat4 基础操作 (identity, multiply) P0 6h
2.5 math.asm — Mat4 高级操作 (inverse, look_at, perspective) P1 8h
2.6 math.asm — Quat 操作 P1 4h
2.7 C 端头文件 asm_math.h P0 2h

Phase 3: 核心框架 (Week 2-3)

序号 任务 优先级 预计时间
3.1 platform.c — Win32 窗口管理 P0 6h
3.2 engine.c — 主循环和初始化 P0 4h
3.3 dx11_device.c — DirectX 11 设备初始化 P0 6h
3.4 renderer.c — 基础渲染管线 P0 8h
3.5 shader.c — 着色器管理 P1 4h
3.6 mesh.c — 网格和顶点缓冲 P1 4h

Phase 4: 游戏系统 (Week 3-4)

序号 任务 优先级 预计时间
4.1 ecs.c — 实体组件系统核心 P0 8h
4.2 physics.c — 物理系统 (调用 ASM math) P1 6h
4.3 collision.c — 碰撞检测 P1 6h
4.4 scene.c — 场景图管理 P1 4h
4.5 resource_manager.c — 资源加载 P2 4h
4.6 audio.c — XAudio2 音频 P2 6h
4.7 ui.c — UI 系统 P2 6h
4.8 scripting.c — Lua 绑定 P2 4h

Phase 5: 演示和优化 (Week 4-5)

序号 任务 优先级 预计时间
5.1 Demo/main.c — 主入口 P0 2h
5.2 Demo/demo_scene.c — 演示场景 P1 6h
5.3 SIMD 性能基准测试 P1 4h
5.4 集成测试和调试 P0 8h

总预计工时: ~150 小时 (约 4-5 周)


6. 文件统计

类别 文件数 说明
ASM (.asm) 4 核心热路径
ASM include (.inc) 1 ASM 函数声明
C 头文件 (.h) 19 包含公共类型和模块头文件
C 源文件 (.c) 30 所有模块实现
VS 项目文件 3 .sln, .vcxproj, .props
文档 1 本设计文档
预编译库 (.lib) 3 lua54, d3d11, d3dcompiler
总计 61 —

按模块分布

ASM 核心:      4 文件 (math, memory, string_ops, profiling)
C 核心:        6 文件 (engine, platform, logger)
C 渲染:        8 文件 (renderer, dx11_device, shader, mesh)
C ECS:         6 文件 (ecs, component_registry, system_manager)
C 物理:        4 文件 (physics, collision)
C 资源:        4 文件 (resource_manager, file_loader)
C 场景:        4 文件 (scene, scene_node)
C 音频:        4 文件 (audio, audio_source)
C UI:          4 文件 (ui, ui_widget)
C 脚本:        4 文件 (scripting, lua_bindgen)
头文件:        19 文件 (含 asm_*.h 和模块 .h)
构建/文档:     7 文件 (VS 项目, 设计文档, 库文件)

7. 性能预期

操作 纯 C ASM (SSE4.1) ASM (AVX2) 加速比
Vec4 Dot ~12 ns ~3 ns ~2 ns 4-6x
Mat4 Multiply ~80 ns ~25 ns ~12 ns 4-7x
Mat4 Inverse ~500 ns ~150 ns ~80 ns 3-6x
Quat Multiply ~25 ns ~8 ns ~5 ns 3-5x
memcpy 1KB ~200 ns ~40 ns ~30 ns 5-7x
memset 1KB ~180 ns ~35 ns ~25 ns 5-7x

注意: 实际性能取决于 CPU 微架构、缓存状态和数据对齐情况。


8. 关键设计决策

  1. 调用约定: 严格遵循 Windows x64 ABI, 确保 ASM/C 无缝互操作
  2. 内存对齐: 所有 SIMD 数据使用 16/32 字节对齐, 通过自定义分配器保证
  3. 寄存器保存: ASM 函数正确保存非易失寄存器 (RBX, RBP, RDI, RSI, R12-R15, XMM6-15)
  4. 错误处理: ASM 函数通过返回值 (0/-1 或 NULL) 表示失败, C 端检查
  5. 调试支持: 使用 /Zi 编译, 生成符号信息, 支持 VS 调试器单步进入 ASM
  6. 可移植性: ASM 文件仅用于 x86-64 Windows, C 代码可条件编译到其他平台