我的Android手机(Adreno 530 GPU)上有glCompressedTexSubImage2D
的ASTC 8x8纹理,遇到了一个奇怪的问题。我的安装程序最初包含一个用于促进异步纹理上传的PBO,但我已将其降低到最低限度以重现此问题。请注意,这是内部的团结5.5.2f1托管作为原生的插件,所以团结可以改变我的电话之间的一些状态glCompressedTexSubImage2D
glCompressedTexSubImage2D上具有ASTC 8x8纹理的GL_INVALID_VALUE
要开始我对编译Android平台24有机会获得<GLES3/gl32.h>
现在,并用正确的标志和设置来启用C++ 11功能。
我已经这个结构定义了正被通过插件更新的每个纹理存储状态:
enum texture_format
{
ASTC_RGBA_8x8 = 57,
};
struct texture_data
{
void* ptr;
bool has_initialized;
uint32_t width;
uint32_t height;
texture_format format;
std::vector<uint8_t> cpu_buffer;
std::mutex lock_cpu_buffer;
uint32_t row;
};
我已经证实从Unity数据在正确地被传递,这是(缩短为了清楚起见)函数,它的纹理上传:
data.lock_cpu_buffer.lock();
int bytesPerRow = data.width * 2; //Specific to ASTC 8x8 for now: (width/8) * 16
int num_rows = data.cpu_buffer.size()/bytesPerRow;
if (num_rows <= 0)
{
data.lock_cpu_buffer.unlock();
return;
}
glBindTexture(GL_TEXTURE_2D, (GLuint)data.ptr);
//Just in case Unity is doing something with these
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, data.row, data.width, 8 * num_rows, GL_COMPRESSED_RGBA_ASTC_8x8, bytesPerRow * num_rows, data.cpu_buffer.data());
GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
#if UNITY_ANDROID
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "glCompressedTexSubImage2D error %u", err);
#endif
}
//prepare buffer for future by copying remainder to beginning of vector and resizing (no allocation should happen here)
data.row += num_rows * 8;
std::copy(data.cpu_buffer.begin() + (bytesPerRow * num_rows), data.cpu_buffer.end(), data.cpu_buffer.begin());
data.cpu_buffer.resize(data.cpu_buffer.size() - (bytesPerRow * num_rows));
glBindTexture(GL_TEXTURE_2D, 0);
data.lock_cpu_buffer.unlock();
总之,我推任意数据量从流在Unity到缓冲器中的本地插件(到位映射PBO指针),然后一次上传多行通过glCompressedTexSubImage2D
为了使事情更简单,我跳过了流(文件头)的前16个字节并读取了4096个字节块(恰好是一行的大小)。所以std :: copy的最后一位实际上并不实际复制任何数据。我通过记录尽可能多的数据验证了这一点,缓冲区每次都从4096的精确倍数调整为0。
这个函数写成yOffset = 0
(无论该调用中有多少行上传,8 192个,或8个倍数,根据规范)。在第一次通话之后,所有其他通话都会失败,并显示GL_INVALID_VALUE
。如果我将Y顺序颠倒(yOffset为data.height - (num_rows * 8)
),那么这是唯一成功的最后一个呼叫。
与GL_KHR_debug进一步挖掘,我实现返回“图像大小是压缩纹理无效”:
04-10 18:35:26.218 24522 24541 V AsyncTexUpload: id=102 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 1432, 2048, 96, GL_COMPRESSED_RGBA_ASTC_8x8, 49152, ptr)
04-10 18:35:26.218 24522 24541 V AsyncTexUpload: Logged message 8246, 824C, 7FFFFFFF, 9146, image size is invalid for compressed texture
04-10 18:35:26.218 24522 24541 V AsyncTexUpload: glCompressedTexSubImage2D error 1281
此外,这里的是真的糊涂了,如果我换X偏移的一部分, yOffset,以及宽度和高度,纹理上传没有错误。我的块都在不正确的位置,但是这个错误从未发生。当computing the imageSize from the table in the documentation,这两个变体具有相同的图像大小值。将参数记录下来时,我的imageSize值是相同的。
下面你可以看到,这是原来的代码未初始化的内存过去的第一个上传运行:
而现在,X偏移/ Y偏移和宽度/高度翻转,整个纹理越来越上传但块对齐(你所期望的,如果在上传错误的顺序块)
有没有对ASTC就是Wo任何限制这是否会导致这种行为?有没有其他人遇到过类似的事情?一些论坛帖子提到一些外部状态改变导致上传失败,我还没有找到任何东西(这包括glActiveTexture,未在上面的代码中显示)。为什么交换参数会导致错误消失?
谢谢你的回答!我面临着同样的问题,你的公式解决了Adreno 430上的错误,你是否设法获得了马里设备的模式? –
还没有,到本周末可能会有东西,只是设法从某人那借用一个设备。请注意,在Adreno上,这仅适用于宽度和高度均为64 texels倍数的纹理。我们刚刚决定暂时不支持这些纹理 –
更新:马里接受与imgtec相同的值,但似乎在具有段错误的最后一块上崩溃。进一步了解这一点 –