Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only.

    Please, do not make any changes to your username or email addresses at id.unity.com during this transition time.

    It's still possible to reply to existing private message conversations during the migration, but any new replies you post will be missing after the main migration is complete. We'll do our best to migrate these messages in a follow-up step.

    On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live.


    Read our full announcement for more information and let us know if you have any questions.

Resolved Async version of Texture2D.GetPixel()

Discussion in 'World Building' started by Heptagram064, Nov 2, 2022.

  1. Heptagram064

    Heptagram064

    Joined:
    Feb 22, 2022
    Posts:
    99
    So, in my project i use textures for my terrain generator, e.g. to determine how much a procedural generation algorithm should blend with others, to create smooth terrain transitions (e.g. 2 different types of Perlin noise algorithms, one for hills and one for mountains).

    The only problem is that i like my terrain generator to compute asynchronously to the main thread. Unfortunately the Texture2D.GetPixel() function can only be used on the main thread;
    complaint.png
    In the current workaround creating a frame drop each time a set of textures is loaded and converted to a Color[ , ] array for the async mesh builder to use.

    I was wondering if there would be a alternate method to Texture2D.GetPixel() that could retrieve pixel information from a texture asynchronously.
     
  2. JasonBooth

    JasonBooth

    Joined:
    Jan 27, 2014
    Posts:
    680
    use GPUAsyncReadbacks instead..
     
  3. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Oh, I see, you're already in CPU land. You can use Native Arrays/GetRawTextureData a to copy the data into a native array and back into textures bypassing the slow Get/SetPixels APIs.
     
  4. Heptagram064

    Heptagram064

    Joined:
    Feb 22, 2022
    Posts:
    99
    So i tried this function;
    Code (CSharp):
    1. private Color32[,] textureData;
    2. private async void ConvertTexture(Texture2D texture2D, Vector2Int textureSize) {
    3.         await Task.Run(() => {
    4.             var data = texture2D.GetRawTextureData<Color32>();
    5.             var output = new Color32[textureSize.x, textureSize.y];
    6.             for (int i = 0, x = 0; x < textureSize.x; i++, x++)
    7.             {
    8.                 for (int y = 0; y < textureSize.y; y++)
    9.                 {
    10.                     if (y != 0) i++;
    11.                     output[x, y] = data[i];
    12.                 }
    13.             }
    14.             textureData = output;
    15.         });
    16.     }
    And i yet, this function is also, only able to be called from the main thread, getting the exact same error as with GetPixel();

    UnityException: get_isReadable can only be called from the main thread.
     
    Last edited: Nov 21, 2022
  5. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    No, you need to use jobs (with burst) and native arrays here, not this. IJobParellelFor is likely what you want..
     
    Heptagram064 likes this.
  6. Heptagram064

    Heptagram064

    Joined:
    Feb 22, 2022
    Posts:
    99
    The jobs and burst systems are both very new to unity (Jobs having been marked 'stable' since only a couple months). For this reason i avoided learning and working with any of the systems rumored to become part of the future unity DOTS, until DOTS gets a stable release out there. (cause why not start learning DOTS when DOTS is actually released). However if using unity jobs is the appropriate way of achieving this, i will read into using it when i get back to my terrain generator.

    In any case, thanks for the help ^.^