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

glCompressedTexSubImage2D何时需传入行首对齐的imageSize参数

ASTC纹理glCompressedTexSubImage2D参数适配方案

没有官方公开的OpenGL/OpenGL ES API可以直接查询设备对glCompressedTexSubImage2D的imageSize参数校验规则,这个差异本质是部分老旧Adreno GPU的驱动bug,不是标准规定的可查询特性,你遇到的RedMI 4(搭载Adreno 505 GPU)就在受影响设备范围内。

受影响设备范围

这个bug基本只出现在2018年之前发布的、搭载Adreno 5xx及更早系列GPU的安卓设备上,ARM Mali、Imagination PowerVR系列GPU,以及Adreno 6xx及之后的新GPU驱动都不存在这个问题,会正确按照OpenGL ES规范校验实际数据尺寸。

通用适配方案

因为没有可直接查询的设备参数,最稳妥的方案是做运行时轻量探测,无额外性能开销:

  • 完成ASTC纹理初始化后,第一次调用glCompressedTexSubImage2D做数据更新前,先发起一次无副作用的测试调用:将x偏移设为1个块宽度(对ASTC_RGBA_6x6格式就是xoffset=6),更新6x6像素大小的区域,传入符合规范的块大小16字节作为imageSize。如果驱动触发参数校验错误,这次调用会直接返回,不会写入任何纹理数据,不存在副作用。
  • 调用完成后立刻执行glGetError(),如果返回GL_INVALID_VALUE,标记当前设备需要传行首对齐尺寸;如果没有报错,后续所有更新都传实际数据尺寸即可。

两类尺寸的计算方式

以ASTC_RGBA_6x6格式为例,单块固定占16字节,块像素维度为6x6:

  1. 符合规范的实际数据尺寸
    先把更新区域的偏移、宽高对齐到块边界,再计算大小:
    const int blockPixelW = 6, blockPixelH = 6;
    const int blockBytes = 16;
    int updateBlockX = (updateWidth + blockPixelW - 1) / blockPixelW;
    int updateBlockY = (updateHeight + blockPixelH - 1) / blockPixelH;
    int validImageSize = updateBlockX * updateBlockY * blockBytes;
    
  2. 驱动bug要求的行首对齐尺寸
    这类驱动校验imageSize时,不会扣减x方向偏移对应的块宽度,会默认从纹理最左边缘开始计算横向块数:
    int alignedBlockX = (xOffset + updateWidth + blockPixelW - 1) / blockPixelW;
    int alignedBlockY = (updateHeight + blockPixelH - 1) / blockPixelH;
    int bugCompatImageSize = alignedBlockX * alignedBlockY * blockBytes;
    

注意:有bug的驱动仅在参数校验阶段用到这个对齐尺寸,实际读取纹理数据时还是会按正确的块偏移访问,所以哪怕传入的imageSize比实际数据大,也不会出现内存越界、渲染错误的问题。

兜底快速适配方案

如果不想做运行时探测,可以直接通过GPU厂商字符串做判断:调用glGetString(GL_VENDOR)获取厂商字符串,如果返回值包含Qualcomm,再进一步判断GPU型号为Adreno 5xx及更早型号,直接使用行首对齐尺寸传参即可覆盖绝大多数问题设备。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:24:16