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

GL_MAP_UNSYNCHRONIZED_BIT与glMapBufferRange的行为合规性问询

GL_MAP_UNSYNCHRONIZED_BIT 与 glDraw 未定义行为判断

OpenGL 4.6 与 OpenGL ES 3.0 对 GL_MAP_UNSYNCHRONIZED_BIT 的定义一致:设置该位后,GL 不会在 Map*BufferRange 返回前尝试同步缓冲区上的待处理操作。若待处理操作的源/修改区域与映射区域重叠,不会触发 GL 错误,但此类先前及后续操作的结果均未定义。


第一段代码分析

// 分配12个颜色的缓冲区并复制12个红色
glBufferData(GL_ARRAY_BUFFER, sizeof(twelveColorsAllRed), twelveColorsAllRed, GL_DYNAMIC_DRAW);

// 映射最后6个颜色
void* p = glMapBufferRange(
    GL_ARRAY_BUFFER,
    sizeOf6Colors,  // 偏移量
    sizeOf6Colors,  // 大小
    GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);

// 更新最后6个颜色
memcpy(p, sixColorsAllGreen, sizeof(sixColorsAllGreen));

glUnmapBuffer(GL_ARRAY_BUFFER);

// 是否为未定义行为?
glDraw(... 使用最后6个颜色的参数与状态 ...)
  • 结论:不属于未定义行为
  • 原因:glBufferData 执行后会隐式同步所有之前的缓冲区操作并完成数据初始化,此时缓冲区无待处理的读写操作。后续映射、修改的区域与 glDraw 使用的区域完全一致,不存在待处理操作与映射区域重叠的情况,符合规范要求,行为确定。

第二段代码分析

// 分配12个颜色的缓冲区并复制12个红色
glBufferData(GL_ARRAY_BUFFER, sizeof(twelveColorsAllRed), twelveColorsAllRed, GL_DYNAMIC_DRAW);

// 安全操作
glDraw(... 使用前6个颜色的参数与状态 ...)

// 映射最后6个颜色
void* p = glMapBufferRange(
    GL_ARRAY_BUFFER,
    sizeOf6Colors,  // 偏移量
    sizeOf6Colors,  // 大小
    GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);

// 更新6个颜色
memcpy(p, sixColorsAllGreen, sizeof(sixColorsAllGreen));

glUnmapBuffer(GL_ARRAY_BUFFER);

// 是否为未定义行为?
glDraw(... 使用最后6个颜色的参数与状态 ...)
  • 结论:不属于未定义行为
  • 原因:中间的 glDraw 使用缓冲区前6个颜色区域,与后续映射、修改的最后6个区域无重叠。映射操作时,待处理的 glDraw 操作和映射区域不冲突,不会触发规范中提到的未定义场景。后续修改完成后执行的 glDraw 使用的是明确更新后的区域,行为确定。

内容的提问来源于stack exchange,提问作者user128511

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 19:06:27