核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2) 外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言 含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
1073 lines
30 KiB
Markdown
1073 lines
30 KiB
Markdown
# 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 数学库
|
|
|
|
```asm
|
|
; ============================================================
|
|
; 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 — 对齐内存分配器
|
|
|
|
```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 — 高速字符串/内存操作
|
|
|
|
```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 性能计时
|
|
|
|
```asm
|
|
; ============================================================
|
|
; 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 — 公共类型
|
|
|
|
```c
|
|
#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
|
|
|
|
```c
|
|
#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
|
|
|
|
```c
|
|
#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
|
|
|
|
```c
|
|
#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
|
|
|
|
```c
|
|
#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
|
|
<?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 — 关键片段
|
|
|
|
```xml
|
|
<!-- 引入 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 代码可条件编译到其他平台
|