CPU và GPU resource trong SDL2
SDL2 phân biệt resource theo hai trục quan trọng: resource nằm ở CPU RAM hay GPU VRAM, và với audio là load full vào RAM hay stream on-demand. Bốn loại resource phổ biến (SDL_Surface, SDL_Texture, Mix_Chunk, Mix_Music) là bốn vị trí trên hai trục đó. Chọn nhầm không gây crash nhưng gây leak RAM hoặc không thể overlap sound — bug “im lặng” khó phát hiện.
Surface và Texture: nơi pixel sống
SDL_Surface giữ pixel data ở CPU RAM. Mọi thao tác (fill rect, blit, alpha blend tay) đều do CPU làm — chậm nhưng kiểm soát từng pixel. SDL_Texture giữ pixel data ở GPU VRAM, hardware-accelerated qua renderer. Render cùng một image bằng texture nhanh hơn surface nhiều lần vì GPU có pipeline song song và memory bandwidth cao.
Quy tắc thực dụng: cái gì render lên screen thì phải là Texture; cái gì cần pixel manipulation thì phải là Surface; chuyển đổi qua SDL_CreateTextureFromSurface.
SDL_ttf minh hoạ điển hình. TTF_RenderText_Blended chỉ tạo Surface vì font rasterization (vẽ glyph từ vector outline thành bitmap) là CPU-bound — phải pass qua CPU memory. Dev có trách nhiệm upload sang Texture rồi free Surface:
SDL_Surface* surf = TTF_RenderText_Blended(font, "Hello", color);
SDL_Texture* tex = SDL_CreateTextureFromSurface(renderer, surf);
SDL_FreeSurface(surf); // bắt buộc, nếu không sẽ leak CPU RAM
Bỏ SDL_FreeSurface là một trong những lỗi rò rỉ phổ biến nhất khi học SDL — code vẫn chạy đúng nhưng leak ~20KB mỗi lần render text mới.
Mix_Chunk và Mix_Music: streaming hay preload
SDL2_mixer phân biệt hai loại audio:
Mix_Chunk (qua Mix_LoadWAV) |
Mix_Music (qua Mix_LoadMUS) |
|
|---|---|---|
| Memory | Decode full vào RAM khi load | Stream on-demand, decode dần |
| Channel | Nhiều channel song song (default 8) | Một music channel duy nhất |
| API play | Mix_PlayChannel(-1, chunk, 0) |
Mix_PlayMusic(music, loops) |
| Phù hợp cho | Sound effect ngắn, có thể overlap | Background music dài |
Hệ quả của “một music channel duy nhất”: gọi Mix_PlayMusic lần hai sẽ cắt music đang chơi. Nếu lỡ dùng Mix_LoadMUS cho sound effect (như tiếng ăn của snake), mỗi lần ăn sẽ cắt music nền — bug rất rõ. Ngược lại, dùng Mix_LoadWAV cho background music dài sẽ load toàn bộ file vào RAM (file 13MB → tốn 13MB RAM cứng) thay vì streaming.
Quy tắc: file ngắn, cần overlap → Chunk; file dài, chỉ chơi một bản tại một thời điểm → Music.
Mỗi loại cần API destroy riêng
Vì C không có destructor tự động, mỗi loại resource có hàm cleanup tương ứng:
SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);
Mix_FreeChunk(chunk);
Mix_FreeMusic(music);
TTF_CloseFont(font);
Gọi nhầm sẽ undefined behavior (ví dụ SDL_FreeSurface lên một Texture pointer). Quy tắc Cấp resource ở đâu, giải phóng ở đó áp dụng nguyên xi: nơi nào Create/Load thì nơi đó phải Free/Destroy, với đúng cặp hàm.
Trải nghiệm cá nhân
Phân biệt này được internalize qua 3 game SDL2 thời 2016–2017 (repo sdl_game). Việc chọn đúng Mix_LoadMUS cho doge.wav (13MB music nền) và Mix_LoadWAV cho eat.wav (66KB sound effect) trong doge_snake/main.cpp:194-195 là quyết định đúng — game audio hoạt động bình thường, không bị cắt nhạc khi ăn. Tuy nhiên SDL_FreeSurface bị quên ở Snake.cpp:16 là một leak ngầm. Chi tiết trong transcript phỏng vấn.
Nguồn tham khảo
- SDL2 Wiki - SDL_Surface
- SDL2 Wiki - SDL_Texture
- SDL Discourse - Is the texture data of SDL_Texture placed in VRAM or RAM?
- SDL2_mixer Wiki - Mix_LoadMUS
- Lazy Foo’ - Sound Effects and Music — tutorial 21 phân biệt Music và Chunk
- Source sdl_game - dẫn chứng dùng đúng cả 4 loại
Liên kết tri thức
- Cấp resource ở đâu, giải phóng ở đó - quy tắc tổng quát áp dụng cho từng cặp Create/Free trong SDL
- Texture leak làm game lag dần - hệ quả thực tế khi quên destroy texture trong game loop
- Game loop cơ bản - vòng lặp render là nơi texture được dùng và là nơi leak biểu hiện rõ nhất
Tags
Cập nhật: 2026-05-29