You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否更新纹理并将其用于预录制的vkCmdDraw调用?

问题:文本图集渲染终端屏幕的方案可行性

我尝试使用文本图集渲染终端屏幕(本质是文本矩阵)。我的方案是遍历每个字符:若字符已在图集中,则传递其纹理坐标等参数并调用vkCmdDraw;若未在图集中,则传递该字符即将添加的字形位置坐标,并将该字符加入列表。我想在绘制结束后重新创建纹理并绑定,使本次绘制使用更新后的纹理,请问这是否可行?

// 伪代码,便于理解场景
start_drawing();

for (line : terminal_buffer){

   for (char : line){

     vec2 position = texture_contains(char) ? get_position(char) : get_last_position_and_add_to_list(char);
     push_data(position);
     
     draw();
    }

}

if(regen_texture) regen_texture();

end drawing();

回答

这个方案不可行,核心原因在于Vulkan的渲染命令执行逻辑:

  • 你在start_drawing()到end drawing()之间记录的所有vkCmdDraw命令,会被存入命令缓冲;这些命令要等到后续提交到GPU队列时才会实际执行。而你在命令记录完成后才调用regen_texture()更新纹理,此时命令缓冲里的绘制指令已经绑定了旧的纹理资源——GPU执行这些命令时,访问的还是更新前的纹理数据,新字符对应的预留坐标区域根本没有有效像素,最终渲染出的新字符会是空白或错误内容。
  • 如果你是直接销毁旧纹理再重建,还会导致命令缓冲里的指令引用无效资源,触发GPU错误甚至程序崩溃。

正确的实现思路

应该把纹理更新放在绘制命令记录之前,步骤调整为:

  1. 遍历整个终端缓冲区,收集所有需要渲染的字符,筛选出图集中没有的新字符。
  2. 更新纹理图集:将新字符的字形写入纹理,同步更新字符到纹理坐标的映射表。
  3. 开始记录绘制命令,遍历终端缓冲区,用更新后的映射表获取每个字符的纹理坐标,依次调用vkCmdDraw完成所有绘制指令的记录。
  4. 提交命令缓冲到GPU队列执行渲染。

调整后的伪代码示例:

// 正确流程的伪代码
// 第一步:收集所有需要的字符
unordered_set<char> needed_chars;
for (line : terminal_buffer) {
    for (char : line) {
        needed_chars.insert(char);
    }
}

// 第二步:更新纹理图集(如果有新字符)
vector<char> new_chars = get_new_chars(needed_chars);
if (!new_chars.empty()) {
    regen_texture(new_chars);
    update_char_position_map(new_chars);
}

// 第三步:记录绘制命令
start_drawing();
for (line : terminal_buffer) {
    for (char : line) {
        vec2 position = get_position(char);
        push_data(position);
        draw();
    }
}
end drawing();

// 提交命令缓冲执行渲染
submit_command_buffer();

内容的提问来源于stack exchange,提问作者F00L.r

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 12:40:00