Search Unity

Graphics.CopyTexture prints out warnings, even though it should not?

Discussion in 'Scripting' started by vladim0105, Sep 18, 2016.

  1. vladim0105

    vladim0105

    Joined:
    Sep 17, 2016
    Posts:
    5
    Code (CSharp):
    1. Graphics.CopyTexture with a region will not copy readable texture data for compressed formats (source texture format 12)
    2. UnityEngine.Graphics:CopyTexture(Texture, Int32, Int32, Int32, Int32, Int32, Int32, Texture, Int32, Int32, Int32, Int32)
    Is the warning I am getting. I am trying to copy from a DXT5 texture to a bigger DXT5 texture, the textures are both multiples of 4 (exactly as the documentation states).

    Normally this wouldnt be a problem, since everything comes out the way I wanted to. But because I do this operation hundreds of thousands of times, it really slows down the performance. Does anyone have any idea of what I am doing wrong? Or is this a bug?

    Code (CSharp):
    1.  
    2. public void generateTileFast(int x, int y, int level, TileData tileData, TileMap map)
    3.     {
    4.         this.tileData = tileData;
    5.         Texture2D tileTexture = ResourceManager.textures[tileData.texture];
    6.  
    7.         Graphics.CopyTexture(tileTexture, 0, 0, 0, 0, tileTexture.width, tileTexture.height, TileMap.textures[level], 0, 0, x, y);
    8.     }
    9.  
    where tileTexture is 64px by 64px and TileMap.textures[level] is 6400px by 6400px, the x and y are multiples of 64 (64, 128, 192, ...)
     
    Last edited: Sep 18, 2016
    iileychen likes this.
  2. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    The warning tells you exactly what the problem is... It can't copy from a compressed texture and DXT5 is a compressed texture format. Why in the world are you copying textures hundreds of thousands of times?!
     
  3. vladim0105

    vladim0105

    Joined:
    Sep 17, 2016
    Posts:
    5
    If you read the documentation, then it clearly states that it can copy from compressed to compressed formats. Besides, it works, no artifacts or anything.
    The reason I am copying the textures hundreds of thousands of times is because I am creating a proceduraly generated tilemap. I estimate that it can copy 200k textures in maybe less than 15 secs, if it wasn't for that warning slowing it down.
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    So having textures be readable means that Unity has a different copy in memory - which is bigger or slower or whatever. Unity's complaining that it can't copy the "readable texture data" here.

    You could try two things:
    - check that all of your textures are set to readable. It might be a problem where one isn't, and you're getting a bad error.
    - if not, try to set all of the textures to not readable. That might get you around the problem.

    Note that this slowdown won't happen in a full build, as Unity doesn't have the same Debug.Log slowdown.
     
    Bunny83 likes this.
  5. vladim0105

    vladim0105

    Joined:
    Sep 17, 2016
    Posts:
    5
    All textures are external or created through code, and I am getting this error for EVERY operation (if I have 200k textures, then it will log 200k times). I am able to run GetPixels (which requires the textures to have Read/Write enabled) without any errors, which hints that they are all readable (Read/Write = readable?)
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    You can check and set read/write-enabled for files in the editor with the AssetImporter class. If these are runtime textures, you're going to run into a huge problem - Unity has no way to create readable textures at runtime.

    Is this a runtime script?
     
  7. vladim0105

    vladim0105

    Joined:
    Sep 17, 2016
    Posts:
    5
  8. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Nope. Unity will puke out each of those warnings no matter what you do.

    Have you considered doing a Get/Set-pixels based workaround? Or is that too slow?
     
    AlterMannn and AggressiveMastery like this.
  9. vladim0105

    vladim0105

    Joined:
    Sep 17, 2016
    Posts:
    5
    That is what I initially did. It is slower, yes, but that is not the main problem. The main problem is that Get/Set pixels does not support compressed formats, and I am working with a very big texture. My 8gigs of ram does not stand a chance. I did try using https://docs.unity3d.com/ScriptReference/Graphics.Blit.html but it was even slower than Get/Set Pixels32. Is there any other way to copy and paste compressed textures? Because if not, than I may have to move over to LibGDX.

    Is it perhaps possible to remove a texture from Scene memory? I have 2 ref Counts on a 200mb texture, making it 400mb (if that is how it works. One is a Material, while the other is ManagedStaticReferences())
     
    Last edited: Sep 18, 2016
  10. JasonWorks

    JasonWorks

    Joined:
    Dec 1, 2016
    Posts:
    14
    vladim0105, I'm getting the same issue - did you ever resolve? And if so, how?
     
  11. JasonWorks

    JasonWorks

    Joined:
    Dec 1, 2016
    Posts:
    14
    For me, I wasn't even able to get the CopyTexture to work with compressed regions - it simply gave the warning log. Baste's suggestion to make my new Texture2D readonly before the call to CopyTexture was the only way I could get the CopyTexture region to work (still with the warning log). I ended up using Texture2D.Apply(false, true) to force the readonly after creation - which worked very well.

    I'd still like to know why I'm getting the warning as all permutations of readonly/non-readonly for both source and destination continue to give the warning. If anyone has come up with the correct solution, the please post it here.
     
  12. KureKureciCZ

    KureKureciCZ

    Joined:
    Jan 5, 2017
    Posts:
    2
    Cool, I've never even touched anything related to textures and I get this error outside of play mode. 2019.2.6f1
     
    AlterMannn likes this.
  13. fortgreeneVR

    fortgreeneVR

    Joined:
    Sep 5, 2018
    Posts:
    50
    Question for the Unity folks reading this.
    It's been a while so perhaps in the mean time it has become possible to kill the CPU memory of dynamically generated textures, make them unreadable and avoid this message?
    Thanks.
     
  14. joshuacwilde

    joshuacwilde

    Joined:
    Feb 4, 2018
    Posts:
    726
    Any updates here? This is causing us major problems just from the cpu usage of so many logs. It would be really great to just be able to force that logging off somewhere. The actual graphics copy texture works great, but the logs are going to prevent us from using it if we silence them.

    It is happening with unreadable textures for us, and I haven't tested if making them readable will fix anything as that isn't a solution for us. The point is to save on memory so they are only gpu readable. We also don't want to do any copying cpu side.
     
  15. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    I'd recommend filing a bug report for the unnecessary logging. You're unlikely to get traction otherwise, unless you're lucky enough for the right dev to happen to log into the forums and happen to have extra time on his/her hands.

    https://unity3d.com/unity/qa/bug-reporting
     
  16. iileychen

    iileychen

    Joined:
    Oct 13, 2015
    Posts:
    110
    Any updates now? We have encounter this issue too, the huge warning logs very annoying.
     
  17. iileychen

    iileychen

    Joined:
    Oct 13, 2015
    Posts:
    110
    No one cares?
     
  18. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,990
    Well, what you have to understand is that Texture2Ds in Unity can have its data be stored in two places at the same time. For once there's the texture data on the GPU itself. That's the one used to render the image. On the other hand there's the loaded data in RAM that your CPU can access. DXT5 textures are a special compression format that is directly interpreted by the GPU.

    Now the issue is when a texture is "readable", which means Unity stores the texture on both sides (GPU and CPU), when you "copy" a texture into another, Unity would need to copy both, the texture in video memory and that in normal RAM. Just copying the data is not an issue. However when you use CopyTexture with a region it means the image data has to be interpolated per-pixel. For that the image needs to be decompressed on the CPU side, interpolated and recompressed. The GPU doesn't have an issue with that since the compression is hardware-implemented. So CopyTexture does not copy the "readable" part of your texture that's stored in RAM, but only the actual texture on the GPU. That of course causes a split in the representation of the texture. That's why you get the warning.

    As @Baste mentioned, you can mark your textures as readonly which should get rid of the warning. I'm not sure if just calling Apply(false, true); in Start would already be enough. You should do it anyways if you do not need to access the pixel data on the CPU as it actually reduces the memory overhead on the CPU / RAM.

    CopyTexture is mainly meant to work on the GPU data only. I think it depends on which version of CopyTexture you're using.
     
  19. iileychen

    iileychen

    Joined:
    Oct 13, 2015
    Posts:
    110
    Yes, you are right.
    But, my src texture is readable and dst texture is NOT readable, so it means we already know the CPU/RAM part will not be copied. It do not need warnning.
     
  20. iileychen

    iileychen

    Joined:
    Oct 13, 2015
    Posts:
    110
    Code (CSharp):
    1. Debug.unityLogger.logEnabled = false;
    Will not prevent this warnning logs, why?

    We really want to disable this warnning, it makes the console nasty.