Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CreateFromImageAsync Texture2D does not work async / SupportsTextureFormatNative error #2

Open
nickyonge opened this issue Oct 11, 2021 · 6 comments
Labels
good first issue Good for newcomers wontfix This will not be worked on

Comments

@nickyonge
Copy link

@Looooong I get the following error when calling CreateFromImageAsync from a thread:

UnityException: SupportsTextureFormatNative can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.

Unity 2020.3.1. AFAIK it's impossible to create a new Texture2D on anything but the main thread? Though that seems to render this whole repo useless, which I hope isn't the case cuz it looks GREAT otherwise!

Here's the full stack trace:

UnityException: SupportsTextureFormatNative can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
UnityEngine.EditorSystemInfo.SupportsTextureFormat (UnityEngine.TextureFormat format) (at <10564ed154d647e194bef4aef8878649>:0)
UnityEngine.SystemInfoShimBase.SupportsTextureFormat (UnityEngine.TextureFormat format) (at <10564ed154d647e194bef4aef8878649>:0)
UnityEngine.SystemInfo.SupportsTextureFormat (UnityEngine.TextureFormat format) (at <10564ed154d647e194bef4aef8878649>:0)
UnityEngine.Texture.ValidateFormat (UnityEngine.TextureFormat format) (at <10564ed154d647e194bef4aef8878649>:0)
UnityEngine.Texture2D..ctor (System.Int32 width, System.Int32 height, UnityEngine.TextureFormat textureFormat, System.Int32 mipCount, System.Boolean linear, System.IntPtr nativeTex) (at <10564ed154d647e194bef4aef8878649>:0)
UnityEngine.Texture2D..ctor (System.Int32 width, System.Int32 height, UnityEngine.TextureFormat textureFormat, System.Int32 mipCount, System.Boolean linear) (at <10564ed154d647e194bef4aef8878649>:0)
AsyncImageLoader+ImageImporter+<CreateNewTextureAsync>d__17.MoveNext () (at Assets/UnityAsyncImageLoader/Runtime/ImageImporter.cs:100)
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () (at <eae584ce26bc40229c1b1aa476bfa589>:0)
AsyncImageLoader+<CreateFromImageAsync>d__9.MoveNext () (at Assets/UnityAsyncImageLoader/Runtime/AsyncImageLoader.cs:105)
UnityEngine.Debug:LogException(Exception)
<CreateFromImageAsync>d__9:MoveNext() (at Assets/UnityAsyncImageLoader/Runtime/AsyncImageLoader.cs:108)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()

and the method I'm calling it from:

private static async Task<Texture2D> ByteArrayToTexture2D(byte[] bytes)
{
    return await AsyncImageLoader.CreateFromImageAsync(bytes);
}
@Looooong
Copy link
Owner

Looooong commented Nov 3, 2021

Sorry for the late reply. Looks like Unity is going into a way to make multi-threading even more restrictive. You can try to create an empty texture before hand and use the method variants that update the existing texture. I will look further to see what I can do with this.

@mdsitton
Copy link

@Looooong Try converting the Texture2D creation to using GraphicsFormat instead of TextureFormat it's in the UnityEngine.Experimental.Rendering namespace. I find that it bypasses the SupportsTextureFormat call, so maybe it could bypass this error?

@Looooong
Copy link
Owner

Good call, can you test it and submit a PR for this?

@mdsitton
Copy link

mdsitton commented Apr 13, 2022

UnityException: IsFormatSupported can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
UnityEngine.Texture.ValidateFormat (UnityEngine.Experimental.Rendering.GraphicsFormat format, UnityEngine.Experimental.Rendering.FormatUsage usage) (at <1332c534a8a44623b2e5cc943a0b790e>:0)
UnityEngine.Texture2D.ValidateFormat (UnityEngine.Experimental.Rendering.GraphicsFormat format, System.Int32 width, System.Int32 height) (at <1332c534a8a44623b2e5cc943a0b790e>:0)
UnityEngine.Texture2D..ctor (System.Int32 width, System.Int32 height, UnityEngine.Experimental.Rendering.GraphicsFormat format, UnityEngine.Experimental.Rendering.TextureCreationFlags flags, System.Int32 mipCount, System.IntPtr nativeTex) (at <1332c534a8a44623b2e5cc943a0b790e>:0)
UnityEngine.Texture2D..ctor (System.Int32 width, System.Int32 height, UnityEngine.Experimental.Rendering.GraphicsFormat format, System.Int32 mipCount, UnityEngine.Experimental.Rendering.TextureCreationFlags flags) (at <1332c534a8a44623b2e5cc943a0b790e>:0)
AsyncImageLoader+ImageImporter.CreateNewTextureAsync () (at Library/PackageCache/com.looooong.asyncimageloader@96335b5707/Runtime/ImageImporter.cs:105)
AsyncImageLoader.CreateFromImageAsync (System.Byte[] data, AsyncImageLoader+LoaderSettings loaderSettings) (at Library/PackageCache/com.looooong.asyncimageloader@96335b5707/Runtime/AsyncImageLoader.cs:105)
UnityEngine.Debug:LogException(Exception)
<CreateFromImageAsync>d__9:MoveNext() (at Library/PackageCache/com.looooong.asyncimageloader@96335b5707/Runtime/AsyncImageLoader.cs:108)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()

Just tested it out, and the same error happens. So this doesn't work to fix the issue

@mdsitton
Copy link

Yeah i tried a few other things with the same result. In my game we have a similar library that we put together and we just create the texture2d on the main thread and get GetRawTextureData and give that to a Task to load into without stalling the main thread. The actual calling code isnt async just the internals.

@Looooong
Copy link
Owner

Looooong commented Dec 15, 2022

Now that I take a look at the code again, I find it weird, because new Texture2D() constructor is supposed to be called on the same thread as CreateFromImageAsync function. So if we want new Texture2D() to be called on the main thread, we must call CreateFromImageAsync on the main thread as well. I think that you try to call CreateFromImageAsync on a thread other than the main thread.

Therefore, something like this doesn't work:

  void Start() {
    Task.Run(() => CreateFromImageAsync(data));
  }

But, this works:

  async void Start() {
    await CreateFromImageAsync(data);
  }

I tested the wrong way and reproduced the same error message.

@Looooong Looooong added good first issue Good for newcomers wontfix This will not be worked on labels Dec 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

3 participants