Chapter 96 · 图像与纹理

Fallback 与上传队列

TextureFallback 提供加载失败时的占位纹理;UploadQueue 将纹理上传延迟到渲染线程执行,避免主线程卡顿。

96

概念

Fallback:当纹理加载失败时,引擎自动使用全局 Fallback 纹理(如紫色棋盘格), 避免渲染崩溃或黑块。
UploadQueue:将纹理 GPU 上传操作加入队列,在渲染线程统一执行, 主线程无需等待 GPU 同步。

API 速查

函数说明
int xgeTextureFallbackSetRGBA(int iWidth, int iHeight, const void* pPixels)设置全局 Fallback 纹理
int xgeTextureFallbackGet(xge_texture pTexture)获取 Fallback 纹理
void xgeTextureFallbackClear(void)清除 Fallback
int xgeTextureUploadQueue(xge_texture pTexture)将纹理加入上传队列
int xgeTextureUploadFlush(void)刷新上传队列

编译本章示例

gcc -O2 -I. -o ch96.exe ch96_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch96.exe

示例:异步加载 + Fallback

// 设置 Fallback:1×1  magenta 像素
uint8_t magenta[4] = { 255, 0, 255, 255 };
xgeTextureFallbackSetRGBA(1, 1, magenta);

// 加载纹理(失败时自动使用 Fallback)
xge_texture_t tex;
int ret = xgeTextureLoad(&tex, "missing.png");
if (ret != 0) {
    // 获取 Fallback 作为占位
    xgeTextureFallbackGet(&tex);
}

// 上传队列:后台线程解码完成后
xgeTextureCreateRGBA(&tex, w, h, pixels);
xgeTextureUploadQueue(&tex); // 入队

// 渲染线程每帧调用
xgeTextureUploadFlush(); // 批量上传

完整代码

将以下代码保存为 ch96_main.c,编译后运行即可看到 Fallback 纹理与上传队列效果:

#include "xge.h"
#include <string.h>

static xge_texture_t g_texGood;
static xge_texture_t g_texFallback;
static int g_hasGood = 0;
static xge_font g_font = NULL;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);

    // 刷新上传队列(异步加载的纹理在此帧可用)
    xgeTextureUploadFlush();

    // 绘制成功加载的纹理
    if (g_hasGood)
        xgeDraw(&g_texGood, 50.0f, 50.0f);

    // 绘制 Fallback 纹理(加载失败的占位)
    xgeDraw(&g_texFallback, 50.0f, 250.0f);

    xgeTextDraw(g_font, "Top: loaded | Bottom: fallback (magenta)",
        50.0f, 450.0f, 0xFFFFFFFF)

    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch96 - Fallback & Upload Queue";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);

    xgeFontLoad(&g_font, "Roboto.ttf", 18.0f);

    // 设置全局 Fallback:1x1 magenta 像素
    uint8_t magenta[4] = { 255, 0, 255, 255 };
    xgeTextureFallbackSetRGBA(1, 1, magenta);

    // 尝试加载纹理(成功)
    if (xgeTextureLoad(&g_texGood, "assets/logo.png") == 0)
        g_hasGood = 1;

    // 尝试加载不存在的文件(失败 → 使用 Fallback)
    if (xgeTextureLoad(&g_texFallback, "missing.png") != 0)
        xgeTextureFallbackGet(&g_texFallback);

    xgeRun(onFrame, NULL);

    if (g_hasGood) xgeTextureFree(&g_texGood);
    xgeTextureFallbackClear();
    xgeFontFree(g_font);
    xgeUnit();
    return 0;
}

代码讲解

  • FallbackSetRGBA:设置全局占位纹理,加载失败时自动使用,避免渲染崩溃。
  • FallbackGet:获取 Fallback 纹理句柄,用于绘制占位图。
  • UploadFlush:在渲染循环开始处调用,将异步解码完成的纹理批量上传 GPU。
  • FallbackClear:程序退出前清理 Fallback 资源,避免泄漏。

要点与陷阱

  • Fallback 全局唯一:所有加载失败的纹理共享同一 Fallback。
  • UploadQueue:适合异步加载场景——工作线程解码,渲染线程上传。
  • Flush 时机:在渲染循环开始处调用,确保本帧可用。
  • FallbackClear:程序退出前清理,避免泄漏。

进阶练习

  1. 实现异步纹理加载器:线程池解码 → UploadQueue → 回调通知。
  2. 自定义 Fallback:生成带 "Missing" 文字的占位图。
Fallback 与上传队列效果
图:Fallback 与上传队列渲染效果