If you create a Texture2D with mipmaps and then compress it, unity crashes with an access violation. It only seems to happens at sizes of 1024x1024 and larger.
That’s basically all there is to it. Without mipmaps, it doesn’t crash.
Reproduction code: (bug reporter is bugged for me)
Code Simple
using UnityEngine;
public class test : MonoBehaviour
{
public void Start ()
{
Texture2D texture = new Texture2D (2048, 2048, TextureFormat.RGB24, true, true);
texture.LoadRawTextureData (new byte[(2048 * 2048 + 1024 * 1024 + 512 * 512 + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2 + 1 * 1) * 3]);
texture.Compress (true); // this line causes an access violation
}
}
Code Longer
using UnityEngine;
using System.Collections;
using System.IO;
using UnityEngine.UI;
public class test : MonoBehaviour
{
static int MipMapPixels (int width, int height)
{
int pixelCount = 0;
while (true) {
pixelCount += width * height;
if (width == 1 || height == 1) {
return pixelCount;
}
width /= 2;
height /= 2;
}
}
static void FillTextureData (byte[] data, int imageSize, bool mipmaps)
{
int mipmapOffset = 0;
while (true) {
for (int x = 0; x < imageSize; x++) {
for (int y = 0; y < imageSize; y++) {
int index = (x * imageSize + y + mipmapOffset) * 3;
data [index++] = (byte)(255f * x / imageSize);
data [index] = (byte)(255f * y / imageSize);
}
}
if (imageSize == 1 | !mipmaps) {
return;
}
mipmapOffset += imageSize * imageSize;
imageSize /= 2;
}
}
const int ImageSize = 2048;
Texture2D Bug ()
{
Texture2D texture = new Texture2D (ImageSize, ImageSize, TextureFormat.RGB24, true, true);
texture.LoadRawTextureData (new byte[MipMapPixels (ImageSize, ImageSize) * 3]);
texture.Compress (true); // this line causes an access violation
return texture;
}
Texture2D BugFancy ()
{
Texture2D texture = new Texture2D (ImageSize, ImageSize, TextureFormat.RGB24, true, true);
byte[] data = new byte[MipMapPixels (ImageSize, ImageSize) * 3];
FillTextureData (data, ImageSize, true);
texture.LoadRawTextureData (data);
texture.Apply (false, false);
texture.Compress (true); // this line causes an access violation
return texture;
}
Texture2D NoBug ()
{
Texture2D texture = new Texture2D (ImageSize, ImageSize, TextureFormat.RGB24, false, true);
texture.LoadRawTextureData (new byte[ImageSize * ImageSize * 3]);
texture.Compress (true); // this line is OK as no mipmaps
return texture;
}
Texture2D NoBugFancy ()
{
Texture2D texture = new Texture2D (ImageSize, ImageSize, TextureFormat.RGB24, false, true);
byte[] data = new byte[ImageSize * ImageSize * 3];
FillTextureData (data, ImageSize, false);
texture.LoadRawTextureData (data);
texture.Apply (false, false);
texture.Compress (true); // this line is OK as no mipmaps
return texture;
}
public void Start ()
{
GetComponent<RawImage> ().texture = Bug();
}
}
Code has some functions without mipmap that work, and some with it that crash. Also some functions that fill the array before passing it, for the sake of completion.
Create a new scene, and add the script to any object, and it should crash on startup. If you want to check one ofthe NoBug functions, add script to a RawImage.
Sidenote, I didn’t check NPOT sizes.
Some edits: Edited code a bit. Added the simplest version I could make of it, except for simplifying that math, but then it’s not so obvious what it does. Also; 1024x1024 has a chance to output errors in the console instead; 2048x2048 seems to always crash.
Errors: 10x this:
Errors
width <= image->GetWidth() && height <= image->GetHeight()
UnityEngine.Texture2D:INTERNAL_CALL_Compress(Texture2D, Boolean)
UnityEngine.Texture2D:Compress(Boolean) (at C:\buildslave\unity\build\artifacts\generated\common\runtime\TextureBindings.gen.cs:366)
test:Start() (at Assets\test.cs:9)
[c:\buildslave\unity\build\runtime\graphics\SharedTextureData.h line 192]
(Filename: Assets/test.cs Line: 9)
sizeX >= 1 && sizeY >= 1 && sizeX <= width && sizeY <= height
UnityEngine.Texture2D:INTERNAL_CALL_Compress(Texture2D, Boolean)
UnityEngine.Texture2D:Compress(Boolean) (at C:\buildslave\unity\build\artifacts\generated\common\runtime\TextureBindings.gen.cs:366)
test:Start() (at Assets\test.cs:9)
[C:/buildslave/unity/build/Runtime/Graphics/Image.cpp line 143]
(Filename: Assets/test.cs Line: 9)