Search Unity

KTX 2.0 and basis file runtime import with KtxUnity

Discussion in 'Assets and Asset Store' started by tteneder, Nov 13, 2020.

  1. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    Hi fellow pixelpushers,

    Let me introduce to you a Unity Package: KtxUnity

    Basis Universal supercompression by Binomial is some awesome technology that allows fast downloads and low memory footprint textures whilst being platform independent (one texture format that works everywhere).



    BasisU supercompression is supported in KTX 2.0, which is an open texture container format by the Khronos Group (in beta, release imminent). Another Khronos standard, the glTF 3D format supports KTX 2.0 textures as well and so this is of great interest for some industries and tinkerers like us.

    The last months I've been helping Khronos to get KTX-Software (specifically the CMake build) ready and created Unity wrappers and a package for it.

    KtxUnity works on WebGL and the major desktop and mobile platforms. It is pleasently fast due to threading via the C# job system.

    It is actively used in a couple of glTF importers already (like my own, glTFast).

    Some bits and optimizations are missing, but I feel confident enough to promote it at this point.

    I'm glad if it is useful to some and I'm open for feedback and contributions.

    Cheers,
    Andi
     
  2. Kreshi

    Kreshi

    Joined:
    Jan 12, 2015
    Posts:
    445
    Hey tteneder,

    i am using your package in a Unity project for initializing textures that are downloaded from the web (WebGL app).
    It's pretty fast and working very well.
    However, my textures are pretty big and WebGL is not multi-threaded and somehow memory-bottlenecked.
    Initialising big textures (big amout of memory allocation) makes the WebGL app therefore freeze for a short period of time.
    To solve this issue, i had to split the textures into multiple parts and reference all of them in the shader simultaneously.
    I don't like this solution much, however it's the only working solution at the moment.

    So is there any chance that you could introduce a function that doesn't allocate the KTXTexture from the given byte[] at once (the download handler seems to do a pretty good job streaming the content into the byte[]), but, let's say, it only allocates x% per frame? This function would need to be a coroutine that we could wait until it finishes (since WebGL is single-threaded).

    Best Regards,
    Kreshi

    PS: Very very good job! I really appreciate what you have created here!
     
    DerrickBarra likes this.
  3. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    Thanks for the flowers, great to see you can put it to good use!

    Without taking a close look I think what you suggest could be achieved by splitting up the transcoding function. Either on a mipmap level or even more granular, on a block (or block range) level.

    The fact that mipmap are re-sorted in memory after transcoding at the moment is also not great. Transcoding them in the correct order to start with would also improve things.

    Combined with streaming (transcode small mip maps first and add more details as download progresses) would be the ideal solution.

    Thanks for bringing this to my attention!

    That being said: All of this requires deep changes in the underlying KTX-Software lib (maybe even BasisU). There's no plan to do that right now, but I may look into mip-map level transcoding at some point.

    Kind regards,
    Andi
     
  4. MikeIVRE

    MikeIVRE

    Joined:
    Jan 11, 2019
    Posts:
    1
    Hi tteneder,

    We noticed the 64 bit Android plugin is not working on builds in release mode on KTX files, only basis files. Do you know what may be wrong with that?
     
  5. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    Seems like a bug. Follow the GitHub issue for updates.
     
  6. Kreshi

    Kreshi

    Joined:
    Jan 12, 2015
    Posts:
    445
    Splitting it on a block-level would be preferred, since a texture could have no mipmaps and even if it always had mipmpas, the highest resolution mipmap could still be too big to be transcoded at once.


    That's true, it would make mipmaps mandatory but in this case thats perfectly fine anyway.


    I understand. Although I would be very happy about a block-level splitting solution since right now thats a performance bottleneck for high resolution textures :).
    The mipmap streaming part i could potentially workaround myself by creating a custom data-format containing the mipmaps ordered as individual KTXTextures and load / set the newest mipmap as the main texture when ready.

    Best Regards,
    Kreshi
     
    tteneder likes this.
  7. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    865
    I have managed to use ktx2 file on webgl with success but only if there is a few files downloaded at the time, if i have a lot of them then it randomly crashes. i tried to replace tasks with coroutines, it didn't work as someone suggested at git repo issues.

    errors are memory access out of bounds but i have printed current memory consumption in webgl it's rather low. it's hard to track line causes memory out of bounds. can somebody help.

    also i was wondering if i can use basis files instead of ktx2. it might resolve the issue maybe? but i am not sure how to produce basis files. with ktx it's easy to resize the texture and compress with basis i couldnt resize or i am doing something wrong

    thanks!
     
  8. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    865
    here is the log from development build:

    UnityLoader.js:1150 exception thrown: RuntimeError: memory access out of bounds,RuntimeError: memory access out of bounds
    at _free (<anonymous>:wasm-function[102639]:0x1b6e732)
    at __ZN17LowLevelAllocator4FreeEPvm (<anonymous>:wasm-function[9445]:0x35f7db)
    at __ZN21UnityDefaultAllocatorI17LowLevelAllocatorE10DeallocateEPv (<anonymous>:wasm-function[14479]:0x590f23)
    at __ZN13MemoryManager10DeallocateEPvPKci (<anonymous>:wasm-function[5218]:0x2240ea)
    at __ZN13MemoryManager10DeallocateEPvRK10MemLabelIdPKci (<anonymous>:wasm-function[5215]:0x223846)
    at __ZdlPv (<anonymous>:wasm-function[5290]:0x2292bd)
    at _ktxTexture2_TranscodeBasis (<anonymous>:wasm-function[102537]:0x1b3bf15)
    at _KtxNativeInstance_ktxTexture2_TranscodeBasis_mEF854FD64B36B71C37CD79C6BADD8A174F6C688F (<anonymous>:wasm-function[102291]:0x1b27265)
    at _KtxTranscodeJob_Execute_m5D0F41A62046752B7A342892205276225A0382B5 (<anonymous>:wasm-function[102300]:0x1b283e8)
    at _JobStruct_1_Execute_m5900B9D5D53AB2343FDF29E41D32FD1823E211E4_gshared (<anonymous>:wasm-function[86891]:0x17f8dc5)
    at _ExecuteJobFunction_Invoke_m0A741C67F97C0CBA7AA3AAB630DBC79F3342430A_gshared (<anonymous>:wasm-function[86885]:0x17f8913)
    at __Z237RuntimeInvoker_TrueVoid_t22962CB4C05B1D89B55A6E1139F0E87A90987017_RuntimeObject_Int32_t585191389E07734F19F3156FF88FB3EF4800D102_Int32_t585191389E07734F19F3156FF88FB3EF4800D102_RuntimeObject_Int32_t585191389E07734F19F3156FF88FB3EF4800D102PFvvEPK10MethodInfoPvPS4_ (<anonymous>:wasm-function[44548]:0xff246e)
    at dynCall_iiiii (<anonymous>:wasm-function[103255]:0x1b99472)
    at Object.dynCall_iiiii (blob:https://www.replaced.com/04fcea6f-dbba-4376-b5d0-80e364b03f46:27843:40)
    at invoke_iiiii (blob:https://www.replaced.com/04fcea6f-dbba-4376-b5d0-80e364b03f46:17719:33)
    at __ZN6il2cpp2vm7Runtime6InvokeEPK10MethodInfoPvPS5_PP15Il2CppException (<anonymous>:wasm-function[39637]:0xf72e8a)
    at _il2cpp_runtime_invoke (<anonymous>:wasm-function[38611]:0xf50084)
    at __Z23scripting_method_invoke18ScriptingMethodPtr18ScriptingObjectPtrR18ScriptingArgumentsP21ScriptingExceptionPtrb (<anonymous>:wasm-function[5536]:0x23ad0c)
    at __ZN19ScriptingInvocation6InvokeEP21ScriptingExceptionPtrb (<anonymous>:wasm-function[5533]:0x23a86e)
    at __ZL10ExecuteJobP14ManagedJobDataPFvPvS1_S1_S1_iEiPh (<anonymous>:wasm-function[16120]:0x641256)
    at __ZL19ForwardJobToManagedP14ManagedJobData (<anonymous>:wasm-function[16119]:0x64100f)
    at __ZN18JobBatchDispatcher26ScheduleJobDependsInternalER8JobFencePFvPvES2_RKS0_ (<anonymous>:wasm-function[9695]:0x380aaa)
    at __Z18ScheduleManagedJobRK21JobScheduleParametersPv (<anonymous>:wasm-function[16118]:0x640f74)
    at __Z36JobsUtility_CUSTOM_Schedule_InjectedR21JobScheduleParametersR8JobFence (<anonymous>:wasm-function[16664]:0x67a5d3)
    at _JobsUtility_Schedule_Injected_mC918219A2045C68697BD2C7FCE7DCA515CE09C01 (<anonymous>:wasm-function[86969]:0x17fb9df)
    at _JobsUtility_Schedule_m544BE1DBAEFF069809AE5304FD6BBFEE2927D4C3 (<anonymous>:wasm-function[86968]:0x17fb999)
    at _IJobExtensions_Schedule_TisKtxTranscodeJob_t08D80333C4F4CB05B55FF154E746ED8763D84505_m3753A8C2E164F8D930FF6FA5AF0F5C45FB7FEE20_gshared (<anonymous>:wasm-function[58474]:0x125ce63)
    at __Z126IJobExtensions_Schedule_TisKtxTranscodeJob_t08D80333C4F4CB05B55FF154E746ED8763D84505_m3753A8C2E164F8D930FF6FA5AF0F5C45FB7FEE2057KtxTranscodeJob_t08D80333C4F4CB05B55FF154E746ED8763D8450551JobHandle_tDA498A2E49AEDE014468F416A8A98A6B258D73D1PK10MethodInfo (<anonymous>:wasm-function[102287]:0x1b27163)
    at _KtxNativeInstance_LoadBytesJob_m6E4F3394855DF18E768AF070CFA2A4AE52957315 (<anonymous>:wasm-function[102286]:0x1b270e7)
    at _U3CTranscodeU3Ed__1_MoveNext_m265B7CCA22CDEADFC560D6B53BF7154593BF071D (<anonymous>:wasm-function[102296]:0x1b27754)
    at __ZN21InterfaceFuncInvoker0IP64DeserializationContext_t51031F3163BAABA5CC204ACBE71ACE98C86E26D7E6InvokeEjP11Il2CppClassP12Il2CppObject (<anonymous>:wasm-function[30217]:0xd1b209)
    at _SetupCoroutine_InvokeMoveNext_m9106BA4E8AE0E794B17F184F1021A53F1D071F31 (<anonymous>:wasm-function[88817]:0x1832020)
    at __Z164RuntimeInvoker_FalseVoid_t22962CB4C05B1D89B55A6E1139F0E87A90987017_VoidU2A_t3A9D5EB5A83DC9C93DF2C4D6EA67B0F5E885889A_Int32_t585191389E07734F19F3156FF88FB3EF4800D102PFvvEPK10MethodInfoPvPS4_ (<anonymous>:wasm-function[44799]:0xff6f16)
    at dynCall_iiiii (<anonymous>:wasm-function[103255]:0x1b99472)
    at Object.dynCall_iiiii (blob:https://www.replaced.com/04fcea6f-dbba-4376-b5d0-80e364b03f46:27843:40)
    at invoke_iiiii (blob:https://www.replaced.com/04fcea6f-dbba-4376-b5d0-80e364b03f46:17719:33)
    at __ZN6il2cpp2vm7Runtime6InvokeEPK10MethodInfoPvPS5_PP15Il2CppException (<anonymous>:wasm-function[39637]:0xf72e8a)
    at _il2cpp_runtime_invoke (<anonymous>:wasm-function[38611]:0xf50084)
    at __Z23scripting_method_invoke18ScriptingMethodPtr18ScriptingObjectPtrR18ScriptingArgumentsP21ScriptingExceptionPtrb (<anonymous>:wasm-function[5536]:0x23ad0c)
    at __ZN19ScriptingInvocation6InvokeEP21ScriptingExceptionPtrb (<anonymous>:wasm-function[5533]:0x23a86e)
    at __ZN9Coroutine14InvokeMoveNextEP21ScriptingExceptionPtr (<anonymous>:wasm-function[9795]:0x390031)
    at __ZN9Coroutine3RunEPb (<anonymous>:wasm-function[9792]:0x38fd1c)
    at __ZN13MonoBehaviour24TryCreateAndRunCoroutineE18ScriptingObjectPtr18ScriptingMethodPtrPP9Coroutine (<anonymous>:wasm-function[9789]:0x38fc97)
    at __ZN13MonoBehaviour22StartCoroutineManaged2E18ScriptingObjectPtr (<anonymous>:wasm-function[16618]:0x677588)
    at __Z43MonoBehaviour_CUSTOM_StartCoroutineManaged2P12Il2CppObjectS0_ (<anonymous>:wasm-function[17135]:0x68ca99)
    at _MonoBehaviour_StartCoroutineManaged2_m114327BBBA9F208E8BA2F8BBF71FA0E8E996F7B8 (<anonymous>:wasm-function[93412]:0x18f04f8)
    at _MonoBehaviour_StartCoroutine_mBF8044CE06A35D76A69669ADD8977D05956616B7 (<anonymous>:wasm-function[93411]:0x18f0492)
    at _U3CLoadBytesRoutineU3Ed__0_MoveNext_m18CCAD62B38F7581867595F9BDC0E18D4ECB3EE8 (<anonymous>:wasm-function[102294]:0x1b27506)
    at __ZN21InterfaceFuncInvoker0IP64DeserializationContext_t51031F3163BAABA5CC204ACBE71ACE98C86E26D7E6InvokeEjP11Il2CppClassP12Il2CppObject (<anonymous>:wasm-function[30217]:0xd1b209)
    at _SetupCoroutine_InvokeMoveNext_m9106BA4E8AE0E794B17F184F1021A53F1D071F31 (<anonymous>:wasm-function[88817]:0x1832020)
    printErr @ UnityLoader.js:1150
    vendor.abb54bb313dbc1964646.bundle.js:1 ERROR RuntimeError: memory access out of bounds
    at _free (<anonymous>:wasm-function[102639]:0x1b6e732)
    at __ZN17LowLevelAllocator4FreeEPvm (<anonymous>:wasm-function[9445]:0x35f7db)
    at __ZN21UnityDefaultAllocatorI17LowLevelAllocatorE10DeallocateEPv (<anonymous>:wasm-function[14479]:0x590f23)
    at __ZN13MemoryManager10DeallocateEPvPKci (<anonymous>:wasm-function[5218]:0x2240ea)
    at __ZN13MemoryManager10DeallocateEPvRK10MemLabelIdPKci (<anonymous>:wasm-function[5215]:0x223846)
    at __ZdlPv (<anonymous>:wasm-function[5290]:0x2292bd)
    at _ktxTexture2_TranscodeBasis (<anonymous>:wasm-function[102537]:0x1b3bf15)
    at _KtxNativeInstance_ktxTexture2_TranscodeBasis_mEF854FD64B36B71C37CD79C6BADD8A174F6C688F (<anonymous>:wasm-function[102291]:0x1b27265)
    at _KtxTranscodeJob_Execute_m5D0F41A62046752B7A342892205276225A0382B5 (<anonymous>:wasm-function[102300]:0x1b283e8)
    at _JobStruct_1_Execute_m5900B9D5D53AB2343FDF29E41D32FD1823E211E4_gshared (<anonymous>:wasm-function[86891]:0x17f8dc5)
    at _ExecuteJobFunction_Invoke_m0A741C67F97C0CBA7AA3AAB630DBC79F3342430A_gshared (<anonymous>:wasm-function[86885]:0x17f8913)
    at __Z237RuntimeInvoker_TrueVoid_t22962CB4C05B1D89B55A6E1139F0E87A90987017_RuntimeObject_Int32_t585191389E07734F19F3156FF88FB3EF4800D102_Int32_t585191389E07734F19F3156FF88FB3EF4800D102_RuntimeObject_Int32_t585191389E07734F19F3156FF88FB3EF4800D102PFvvEPK10MethodInfoPvPS4_ (<anonymous>:wasm-function[44548]:0xff246e)
    at dynCall_iiiii (<anonymous>:wasm-function[103255]:0x1b99472)
    at Object.dynCall_iiiii (blob:https://www.replaced.com/04fcea6f-dbba-4376-b5d0-80e364b03f46:27843:40)
    at invoke_iiiii (blob:https://www.replaced.com/04fcea6f-dbba-4376-b5d0-80e364b03f46:17719:33)
    at __ZN6il2cpp2vm7Runtime6InvokeEPK10MethodInfoPvPS5_PP15Il2CppException (<anonymous>:wasm-function[39637]:0xf72e8a)
    at _il2cpp_runtime_invoke (<anonymous>:wasm-function[38611]:0xf50084)
    at __Z23scripting_method_invoke18ScriptingMethodPtr18ScriptingObjectPtrR18ScriptingArgumentsP21ScriptingExceptionPtrb (<anonymous>:wasm-function[5536]:0x23ad0c)
    at __ZN19ScriptingInvocation6InvokeEP21ScriptingExceptionPtrb (<anonymous>:wasm-function[5533]:0x23a86e)
    at __ZL10ExecuteJobP14ManagedJobDataPFvPvS1_S1_S1_iEiPh (<anonymous>:wasm-function[16120]:0x641256)
    at __ZL19ForwardJobToManagedP14ManagedJobData (<anonymous>:wasm-function[16119]:0x64100f)
    at __ZN18JobBatchDispatcher26ScheduleJobDependsInternalER8JobFencePFvPvES2_RKS0_ (<anonymous>:wasm-function[9695]:0x380aaa)
    at __Z18ScheduleManagedJobRK21JobScheduleParametersPv (<anonymous>:wasm-function[16118]:0x640f74)
    at __Z36JobsUtility_CUSTOM_Schedule_InjectedR21JobScheduleParametersR8JobFence (<anonymous>:wasm-function[16664]:0x67a5d3)
    at _JobsUtility_Schedule_Injected_mC918219A2045C68697BD2C7FCE7DCA515CE09C01 (<anonymous>:wasm-function[86969]:0x17fb9df)
    at _JobsUtility_Schedule_m544BE1DBAEFF069809AE5304FD6BBFEE2927D4C3 (<anonymous>:wasm-function[86968]:0x17fb999)
    at _IJobExtensions_Schedule_TisKtxTranscodeJob_t08D80333C4F4CB05B55FF154E746ED8763D84505_m3753A8C2E164F8D930FF6FA5AF0F5C45FB7FEE20_gshared (<anonymous>:wasm-function[58474]:0x125ce63)
    at __Z126IJobExtensions_Schedule_TisKtxTranscodeJob_t08D80333C4F4CB05B55FF154E746ED8763D84505_m3753A8C2E164F8D930FF6FA5AF0F5C45FB7FEE2057KtxTranscodeJob_t08D80333C4F4CB05B55FF154E746ED8763D8450551JobHandle_tDA498A2E49AEDE014468F416A8A98A6B258D73D1PK10MethodInfo (<anonymous>:wasm-function[102287]:0x1b27163)
    at _KtxNativeInstance_LoadBytesJob_m6E4F3394855DF18E768AF070CFA2A4AE52957315 (<anonymous>:wasm-function[102286]:0x1b270e7)
    at _U3CTranscodeU3Ed__1_MoveNext_m265B7CCA22CDEADFC560D6B53BF7154593BF071D (<anonymous>:wasm-function[102296]:0x1b27754)
    at __ZN21InterfaceFuncInvoker0IP64DeserializationContext_t51031F3163BAABA5CC204ACBE71ACE98C86E26D7E6InvokeEjP11Il2CppClassP12Il2CppObject (<anonymous>:wasm-function[30217]:0xd1b209)
    at _SetupCoroutine_InvokeMoveNext_m9106BA4E8AE0E794B17F184F1021A53F1D071F31 (<anonymous>:wasm-function[88817]:0x1832020)
    at __Z164RuntimeInvoker_FalseVoid_t22962CB4C05B1D89B55A6E1139F0E87A90987017_VoidU2A_t3A9D5EB5A83DC9C93DF2C4D6EA67B0F5E885889A_Int32_t585191389E07734F19F3156FF88FB3EF4800D102PFvvEPK10MethodInfoPvPS4_ (<anonymous>:wasm-function[44799]:0xff6f16)
    at dynCall_iiiii (<anonymous>:wasm-function[103255]:0x1b99472)
    at Object.dynCall_iiiii (blob:https://www.replaced.com/04fcea6f-dbba-4376-b5d0-80e364b03f46:27843:40)
    at invoke_iiiii (blob:https://www.replaced.com/04fcea6f-dbba-4376-b5d0-80e364b03f46:17719:33)
    at __ZN6il2cpp2vm7Runtime6InvokeEPK10MethodInfoPvPS5_PP15Il2CppException (<anonymous>:wasm-function[39637]:0xf72e8a)
    at _il2cpp_runtime_invoke (<anonymous>:wasm-function[38611]:0xf50084)
    at __Z23scripting_method_invoke18ScriptingMethodPtr18ScriptingObjectPtrR18ScriptingArgumentsP21ScriptingExceptionPtrb (<anonymous>:wasm-function[5536]:0x23ad0c)
    at __ZN19ScriptingInvocation6InvokeEP21ScriptingExceptionPtrb (<anonymous>:wasm-function[5533]:0x23a86e)
    at __ZN9Coroutine14InvokeMoveNextEP21ScriptingExceptionPtr (<anonymous>:wasm-function[9795]:0x390031)
    at __ZN9Coroutine3RunEPb (<anonymous>:wasm-function[9792]:0x38fd1c)
    at __ZN13MonoBehaviour24TryCreateAndRunCoroutineE18ScriptingObjectPtr18ScriptingMethodPtrPP9Coroutine (<anonymous>:wasm-function[9789]:0x38fc97)
    at __ZN13MonoBehaviour22StartCoroutineManaged2E18ScriptingObjectPtr (<anonymous>:wasm-function[16618]:0x677588)
    at __Z43MonoBehaviour_CUSTOM_StartCoroutineManaged2P12Il2CppObjectS0_ (<anonymous>:wasm-function[17135]:0x68ca99)
    at _MonoBehaviour_StartCoroutineManaged2_m114327BBBA9F208E8BA2F8BBF71FA0E8E996F7B8 (<anonymous>:wasm-function[93412]:0x18f04f8)
    at _MonoBehaviour_StartCoroutine_mBF8044CE06A35D76A69669ADD8977D05956616B7 (<anonymous>:wasm-function[93411]:0x18f0492)
    at _U3CLoadBytesRoutineU3Ed__0_MoveNext_m18CCAD62B38F7581867595F9BDC0E18D4ECB3EE8 (<anonymous>:wasm-function[102294]:0x1b27506)
    at __ZN21InterfaceFuncInvoker0IP64DeserializationContext_t51031F3163BAABA5CC204ACBE71ACE98C86E26D7E6InvokeEjP11Il2CppClassP12Il2CppObject (<anonymous>:wasm-function[30217]:0xd1b209)
    at _SetupCoroutine_InvokeMoveNext_m9106BA4E8AE0E794B17F184F1021A53F1D071F31 (<anonymous>:wasm-function[88817]:0x1832020)
     
  9. atteneder

    atteneder

    Unity Technologies

    Joined:
    May 11, 2021
    Posts:
    2
  10. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    865
    Hi @atteneder I am using this plugin and it's working great! Only issue I have is that bigger textures cause stutter on WebGl (4096 textures) so I was wondering is there a way to wait until some flag is true to download or pause download/read (for example when camera is moving, I would delay when camera is not moving and when it's starts to move then to pause again).

    currently I am using this:
    Code (CSharp):
    1.  
    2. private async void DownloadKtxTextureRoutine(LayerTextureJob info, Action onComplete = null)
    3.         {
    4.             var texture = new KtxTexture();
    5.             var result = await texture.LoadFromUrl(info.KtxUrl);
    6.             if (result != null)
    7.             {
    8.                 info.Texture = result.texture;
    9.                 if (info.IsSharedTexture) OnSharedTextureReady(info);
    10.                 else OnTextureReady(info);
    11.             }
    12.         }
    and to start

    Code (CSharp):
    1. private void RequestTextureJob(LayerTextureJob info)
    2. {
    3.          DownloadKtxTextureRoutine(info);
    4. }
    How to start it so it can pause while some flag is true? Can you help me understand how it works, is it possible when download starts to pause it. Maybe decompression is more of a problem?

    Thank you!
     
  11. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    @pretender As far as I see you're wrapping the async LoadFromUrl and effectively make it sync (thus the download is blocking). Please look up how to call async methods properly. Hint: Monobehaviour entry points like Start or Update can be async as well!

    What remains a problem is that transcoding and GPU upload remain blocking the main thread (since WebGL does not offer user threads). Currently there's no way around that, but I'd love to experiment with JS worker threads and a separate transcoding webassembly context at some point.
     
  12. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    865
    in regarding speed what is better option to compress textures without mipmaps (are they going to be generated when texture is used in unity) and how to properly generate mipmaps, what option to use -automipmap, -mipmap or -genmipmap (i want as less as possible of processing in unity)
    thank you!
     
  13. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    @pretender

    KtxUnity will not create mipmaps if the KTX file did not already contain them. Looking it up (KTX spec, Section 3.7) I realize this is a missing feature. I created an issue, but don't plan on implementing it anytime soon.

    Please consult the toktx documentation regarding its parameters. My conclusion:
    • automipmap is about the missing runtime generation, so that won't work with KtxUnity
    • genmipmap creates them and allows customization (choose filter, etc.). Start with this, play with parameters and test if it's working for you.
    • mipmap: if for some reason the genmipmap results are not what you expect, you can manually create individual mipmaps and feed them to toktx. Probably overkill for most use-cases, but good to have.
    hth
     
  14. apprenticegc

    apprenticegc

    Joined:
    Apr 21, 2012
    Posts:
    25
    Hello,

    While trying to use ktx plugin in Unity, I encouter one strange issue. When I format heic format of image to png(using nodejs sharp with custom libvips) and encode it to ktx2 format. This image will have color channel BGR instead of normal RGB. So all blue turns to red and vice versa. Other format, jpg, png show normally without any issue.

    Is there any ktx unity plugin settings to adjust? Or do I miss anything?
     
  15. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    Hi,
    Never experienced that. Would you mind open an issue on GitHub and providing sample images (original heic, png and ktx2)? Which format did you transcode it to?
    Thanks
     
  16. apprenticegc

    apprenticegc

    Joined:
    Apr 21, 2012
    Posts:
    25
    I have created an issue on GitHub.

    I observed that the format ktx plugin import will be either dxt1, rgb565 or b5g6r5(both in Unity editor and windows standalone build). On mobile, currently the format shows astc_4x4. The format astc is correct but while using toktx cli tool, the block size is 6x6. But on mobile, it shows astc_4x4 insteade.

    I just don't know how to deal with random format on Windows standalone build(or Unity editor). Any suggestion?
     
  17. apprenticegc

    apprenticegc

    Joined:
    Apr 21, 2012
    Posts:
    25
    Hello,

    I understand that there are issues 67 and 68 being created to address the target format adjustment for particular platform. Just note down the observation that certain ktx2 format even being specified as ASTC in player setting(Texture compression format) for mobile, It will be loaded as ETC2_RGB.

    Besides the format, that --bcmp flag used during "toktx" command, if applied the astc parameters are not being applied

    ``toktx ignores all ASTC parameters and only takes --bcmp``

    I then remove --bcmp(without it or replacing with zcmp), the output file could not be read by KtxUnity plugin. It says the image need to be super compression. I just wonder what the correct flags should be used during "toktx" command so astc parameters are kept and the output file can be read by KtxUnity.
     
  18. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    Sorry for the late reply.

    KTX is a container format capable of delivering uncompressed formats, compressed formats (like ASTC) and super-compression (BasisUniversal), all with optional ZStandard compression on top.

    KtxUnity was initially created to load BasisUniversal compressed KTX files and up until now cannot load other formats. So the problem is likely not the way you invoke toktx, but a missing feature in KtxUnity.

    I'd love to have this lacking features added to KtxUnity, but to me it's not a priority at the moment. Happy to review pull requests though.

    hth
     
  19. hexdecc

    hexdecc

    Joined:
    Oct 24, 2014
    Posts:
    146
  20. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    Where exactly do you struggle?

    I recommend going with KTX 2.0, but if you want to convert to .basis files, you need the basisu command line utility from here:

    https://github.com/BinomialLLC/basis_universal/releases

    There's the KTX Tools guide and the KTX artist guide. Both easily discoverable on KTX' main site.
     
  21. hexdecc

    hexdecc

    Joined:
    Oct 24, 2014
    Posts:
    146
    tteneder likes this.
  22. ConorsFlying

    ConorsFlying

    Joined:
    Apr 26, 2018
    Posts:
    8
    I’m trying to figure out if this we’ll help reduce memory usage for a mobile WebGL build.

    I know WebGL only supports limited texture formats. Do the basis universal files just get decompressed at runtime to regular formats anyway? Meaning there would be no benefit over just compressing them in the build or bundle.

    Possible there is something else I’m not understanding, looks very cool
     
  23. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    TL;DR: It depends (which platforms do you target?) and your mileage may vary, so test for yourself.

    Long:
    Afaik WebGL (i.e. the API) supports plenty of formats, but given the vast device fragmentation you'll have a hard time finding a compressed format that works everywhere.

    The default approach many choose nowadays is pick ASTC as texture format, as it works on most modern mobile devices. If the device does not support ASTC, it'll get decoded into bitmaps, which use up a lot of GPU memory. Since this is mostly the case with desktop browsers, this isn't too much of a concern there (they have tons of memory compared to mobiles). This approach won't work well with older mobile devices though.

    The advantage of Basis Universal super compression (with KTX 2.0) is that it can be transcoded to a variety of (still) compressed formats at runtime, reducing the memory consumption, even on older devices.
     
    ConorsFlying likes this.
  24. Firewalker

    Firewalker

    Joined:
    Mar 30, 2012
    Posts:
    39
    Hi,

    I have a problem on MacBook Pro M2. It seems that DLLs wouldn't load.
    It crashes in ktx_basisu_create_basis();

    I presume it is the DLL problem:
    [DllImport(KtxNativeInstance.INTERFACE_DLL)]
    private static unsafe extern System.IntPtr ktx_basisu_create_basis();


    What shall we do? and thanks a million ofc
     
  25. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    Ops, seems like a vital bug fixed in 2.0.1 hasn't been back-ported to 1.3.x. Can you confirm you're using 1.3.x?
     
  26. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    @Firewalker I've just released KtxUnity 1.3.2, which should solve your problem. If it did not, please let me know which exact version of Unity and KtxUnity you're using.

    Thanks
     
  27. smash-ter

    smash-ter

    Joined:
    Sep 6, 2020
    Posts:
    22
    Which version should be used for targeting both PCVR (DX11) and Android (Quest)? The naming structure on the Github releases is a bit confusing
     
  28. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    Currently it depends on your Unity version. If you're using Unity 2021.2 or newer, pick KtxUnity 2.x.
    If you're using an older version, stay with 1.x (to ensure WebGL builds work; otherwise they're identical).

    We're aware that this is confusing. The upcoming major version will be a on-fits-all release again.
     
  29. smash-ter

    smash-ter

    Joined:
    Sep 6, 2020
    Posts:
    22
    I think it's cool that this stuff exists, but I'm trying to figure out if there are any other major performance benefits for using .ktx2 and .basis files, especially for Unity. I want to pitch this to other game devs to integrate this into the platform as I would like to lower the file size and memory impact from textures on both the CPU and GPU. I saw the demo for the iPhone but how useful would it be for Quest or even PC?
     
  30. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    @smash-ter
    I think KTX2/BasisU is super helpful whenever you run into memory limits, which I assume can be an issue, even on Quest. Most PCs have plenty of VRAM, but ambitious projects that are pushing the limits are a reality, so why not use KTX there as well?
    Whenever you want to load dynamic content, KTX2 flat out beats JPG/PNG loading for sure. Asset Bundles/Adressables is a different thing. They are well integrated and might be preferable, depending on your workflows. If you're in a pure Unity workflow and don't mind creating per-platform asset bundles, you might want to stick to that.
     
  31. smash-ter

    smash-ter

    Joined:
    Sep 6, 2020
    Posts:
    22
    @tteneder so for a bit of context I'm someone that works on avatars and worlds for VRChat. I've been wanting to find methods of improving overall performance when it comes to the game overall for a better user experience. I've tried KtxUnity and it works when uploading to vrchat with no issues, and actually lowers the file size of the total build compared to using png textures. Although it transcodes UASTC back to BC7 and gets turned into a Texture2D asset, would the benefits of .ktx2 still work or would there have to be other things added to the compiler?
     
  32. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    I described my observations regarding KTX2 performance in the previous post. Those observations factored in transcoding (to BC7, for example) and creating Texture2Ds. So yes, it should give you performance upside (again, compared to Jpeg/PNG: definitely; compared to asset bundles: it depends).

    Can you elaborate what you mean with "adding to the compiler"? Which compiler? And what to add to it potentially?

    When in doubt I for one create a benchmark (e.g. a performance unit test) to measure for my particular use-case myself. I'd recommend that to you as well. Feel free to share results.
     
  33. StephenWalkerGM

    StephenWalkerGM

    Joined:
    Dec 13, 2023
    Posts:
    3
    I'm having some difficulties getting KTX textures working in Unity (using KTX for Unity 3.2.2, using Unity 2022.3.13). I have a collection of sample KTX 2.0 texture files downloaded from github and many of them work, however many show the error upon import and are unrecognized:

    unknown texture format (KTX)
    Unsupported Assets/Platform/Textures/test.ktx file.


    I was hoping to convert existing texture files (from PNG, JPEG, EXR) using KTX-Software 4.2.1 command line tool toktx, however when I convert a jpeg file (256x256 pixels containing only a basic gradient), the resulting file is unreadable and shows the same errors as above.

    This is the command and it executes without any errors, but the file can't be read in Unity:

    C:\Users\Walker>toktx "C:\Work\Unity\PlatformMaster\Assets\Platform\Textures\jpegTest.ktx" "C:\Work\Unity\PlatformMaster\Assets\Platform\Textures\jpegTest.jpg"

    For some reason ktx validate is throwing a dll error, but I am able to use ktxinfo on the file if this sheds any light:
    identifier: «KTX 11»\r\n\x1A\n
    endianness: 0x4030201
    glType: 0x1401
    glTypeSize: 1
    glFormat: 0x1907
    glInternalformat: 0x8c41
    glBaseInternalformat: 0x1907
    pixelWidth: 256
    pixelHeight: 256
    pixelDepth: 0
    numberOfArrayElements: 0
    numberOfFaces: 1
    numberOfMipLevels: 1
    bytesOfKeyValueData: 28

    Key/Value Data

    KTXorientation: S=r,T=d

    Data Sizes (bytes)
    ------------------
    Level 0: 196608

    Total: 196608
    Any thoughts or suggestions?
     
  34. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    @StephenWalkerGM :

    *KTX for Unity* does not support KTX versions older than 2.0.

    You can enforce this by passing the `--t2` parameter to `toktx`.

    I also recommend taking a detailed look into toktx (e.g. read the manual `toktx --help` ouputs). You'll learn about compression options that can further optimize your textures.

    hth
     
  35. StephenWalkerGM

    StephenWalkerGM

    Joined:
    Dec 13, 2023
    Posts:
    3
    Thanks for the help! Unfortunately I am still unable to get a readable texture using the --t2 flag. The resulting .ktx file upon import into Unity produces the the error: Not a valid KTX file.

    There is nothing special about the input file. I've tried both PNG and JPEG images. I also tried different encodings (uastc, etc1s), but no luck. I'm using the latest repo of KTX-Software and most current version of KTX for Unity (3.2.2).

    This the output from ktxinfo:
    identifier: «KTX 20»\r\n\x1A\n
    vkFormat: VK_FORMAT_ASTC_6x6_SRGB_BLOCK
    typeSize: 1
    pixelWidth: 1024
    pixelHeight: 1024
    pixelDepth: 0
    layerCount: 0
    faceCount: 1
    levelCount: 1
    supercompressionScheme: KTX_SS_NONE
    dataFormatDescriptor.byteOffset: 0x68
    dataFormatDescriptor.byteLength: 44
    keyValueData.byteOffset: 0x94
    keyValueData.byteLength: 108
    supercompressionGlobalData.byteOffset: 0
    supercompressionGlobalData.byteLength: 0

    Level Index

    Level0.byteOffset: 0x100
    Level0.byteLength: 467856
    Level0.uncompressedByteLength: 467856

    Data Format Descriptor

    DFD total bytes: 44
    BDB descriptor type 0x0000 vendor id = 0x00000
    Descriptor block size 40 (1 samples) versionNumber = 0x0002
    Flags 0x00 Xfer 02 Primaries 01 Model 162
    Dimensions: 6,6,1,1
    Plane bytes: 16,0,0,0,0,0,0,0
    Sample 0
    Qualifiers 0 Channel 0x0 (R) Length 128 bits Offset 0
    Position: 0,0,0,0
    Lower 0x00000000
    Upper 0xffffffff

    Key/Value Data

    KTXorientation: rd
    KTXwriter: toktx v4.2.0~11 / libktx v4.2.1~1
    KTXwriterScParams: --encode astc
     
  36. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    @StephenWalkerGM I think there's a conceptual misunderstanding.

    Although KTX for Unity is primarily designed for runtime loading, it provides an importer that targets files with a ".ktx2" extension. Unity itself comes with a KTX 1.x importer built-in that imports all files with a ".ktx" extension (which you mentioned you use).

    So if my assumption is correct and you're doing Editor importing, fixing the file extension will fix this.

    The problem with importing GPU texture formats is that both the development computer and target devie has to support said format. Not sure what workflow you're trying to accomplish, but feel free to elaborate.

    hth
     
  37. StephenWalkerGM

    StephenWalkerGM

    Joined:
    Dec 13, 2023
    Posts:
    3
    Ok yep that fixed it! Thanks.

    At this stage I am only assessing KTX 2.0 for its potential to optimize textures included in glTF models, which may be created from both outside or within the app. I was just trying to get things working in the Unity editor first to test. Target platforms are still being determined but from what I have read it seems that KTX 2.0 is supported.
     
    tteneder likes this.
  38. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    I see. Some thoughts:

    At the moment there is no generic KTX support in glTF. What you're likel using is the KHR_texture_basisu extension, which is limited to Basis Universal super compression. So a KTX file with an ASTC texture is outside of the glTF specification and ratified extensions.

    Speaking of BasisU, I highly recommend using that anyways, as it allows transcoding to a lot of GPU compressed target formats, essentially supporting all devices imaginable. There's even two flavors (ETC1s and UASTC) with varying compression rates and quality.

    hth
     
    StephenWalkerGM likes this.