Skip to content

Conversation

@isHarryh
Copy link
Contributor

@isHarryh isHarryh commented Jan 26, 2025

Summary

This PR mainly fixes the concurrent issue of ASTC context in Texture2DConverter. By the way, it also fixes some type errors and type hints in Texture2DConverter.

1. ASTC Context Concurrent Issue

How do I discovered this issue:

After upgrading UnityPy (from 1.18 to 1.20) in my project ArkUnpacker, I noticed that, when using multithreading to extract images, the application has an unpredictable chance to crash without any stacktrace (just like you shutdown the application in the Task Manager forcibly).

With the extensive debugging, I finally determined that it is the asynchronous access to the ASTC context that causes the problem.

This issue was caused by this commit d38b5f6 which introduced astc_encoder for texture decoding.

How to fix it:

Simply adding a threading.Lock to the dict ASTC_CONTEXTS.

2. Type Errors

There are two potential type errors. See my commit for detailed changes. Here comes the explanation:

  1. In this case, texture_format may be an integer.
        raise NotImplementedError(
-            f"Not implemented texture format: {texture_format.name}"
+            f"Not implemented texture format: {texture_format}"
        )
  1. In this case, bytes cannot be divided by integer.
    rgb_data = b"".join(
        stream.read(padding_size * 2) + padding
-        for _ in range(image_data / (2 * padding_size))
+        for _ in range(len(image_data) // (2 * padding_size))
    )

if len(selection) == 0:
raise NotImplementedError(
f"Not implemented texture format: {texture_format.name}"
f"Not implemented texture format: {texture_format}"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I forgot that texture_format could still be an int.
As the int number isn't that telling imo, it would be better to cast the format to the enum and print it's name if possible, and only show the number if that is not possible.

Copy link
Contributor Author

@isHarryh isHarryh Jan 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the int can be cast to the enum, it is very likely to be a known format that has been implemented. In other words, the unimplemented texture format is very likely to be not castable. So showing the int value is enough.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all of them are implemented atm, but so far I haven't seen any of those in the wild either.
So I guess it's indeed fine to keep it as is as int.

Copy link
Owner

@K0lb3 K0lb3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR and the fixes.
I just want to see two little changes overall, reducing the lock scope to the specific context usage and replacing Union[foo, None] with Optional[foo].

@K0lb3
Copy link
Owner

K0lb3 commented Feb 3, 2025

Thanks a lot 👍

@K0lb3 K0lb3 merged commit d317594 into K0lb3:master Feb 3, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants