我的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相同的值,但似乎在具有段錯誤的最後一塊上崩潰。進一步瞭解這一點 –