[unity] Fixed profiler samplers array out of bounds access at threaded update system. Closes #2981.

This commit is contained in:
Harald Csaszar 2025-11-26 17:47:47 +01:00
parent 8fdbf055f2
commit 370c74edb4

View File

@ -155,7 +155,7 @@ namespace Spine.Unity {
volatile protected int numExceptionsSet = 0; volatile protected int numExceptionsSet = 0;
protected int usedThreadCount = -1; protected int usedThreadCount = -1;
public void DeferredLogException(Exception exc, UnityEngine.Object context, int threadIndex) { public void DeferredLogException (Exception exc, UnityEngine.Object context, int threadIndex) {
exceptions[threadIndex] = exc; exceptions[threadIndex] = exc;
exceptionObjects[threadIndex] = context; exceptionObjects[threadIndex] = context;
numExceptionsSet++; numExceptionsSet++;
@ -287,7 +287,12 @@ namespace Spine.Unity {
genericSkeletonTasks[t] = new WorkerPoolTask(); genericSkeletonTasks[t] = new WorkerPoolTask();
} }
} }
#if ENABLE_THREAD_PROFILING
if (profilerSamplerUpdate == null) {
profilerSamplerUpdate = new CustomSampler[numThreads];
}
#endif
for (int t = 0; t < updateDone.Count; ++t) { for (int t = 0; t < updateDone.Count; ++t) {
updateDone[t].Reset(); updateDone[t].Reset();
} }
@ -388,7 +393,7 @@ namespace Spine.Unity {
}; };
UpdateSkeletonsAsyncSplit(range, t); UpdateSkeletonsAsyncSplit(range, t);
start = end; start = end;
if (start >= skeletonEnd) { if (start >= skeletonEnd) {
while (++t < numAsyncThreads) { while (++t < numAsyncThreads) {
@ -422,7 +427,7 @@ namespace Spine.Unity {
// The explicit memory barrier below is added to ensure a memory barrier is in place on the many // The explicit memory barrier below is added to ensure a memory barrier is in place on the many
// Unity target platforms. // Unity target platforms.
Thread.MemoryBarrier(); Thread.MemoryBarrier();
// process main thread callback part // process main thread callback part
anyWorkLeft = UpdateSkeletonsMainThreadSplit(skeletons, endIndexThreaded, Time.deltaTime, Time.frameCount); anyWorkLeft = UpdateSkeletonsMainThreadSplit(skeletons, endIndexThreaded, Time.deltaTime, Time.frameCount);
isFirstIteration = false; isFirstIteration = false;
@ -472,7 +477,12 @@ namespace Spine.Unity {
genericSkeletonTasks[t] = new WorkerPoolTask(); genericSkeletonTasks[t] = new WorkerPoolTask();
} }
} }
#if ENABLE_THREAD_PROFILING
if (profilerSamplerLateUpdate == null) {
profilerSamplerLateUpdate = new CustomSampler[numThreads];
}
#endif
for (int t = 0; t < lateUpdateDone.Count; ++t) { for (int t = 0; t < lateUpdateDone.Count; ++t) {
lateUpdateDone[t].Reset(); lateUpdateDone[t].Reset();
} }
@ -481,7 +491,7 @@ namespace Spine.Unity {
lateUpdateDone.Add(new ResetEvent(false)); lateUpdateDone.Add(new ResetEvent(false));
} }
} }
int rangePerThread = Mathf.CeilToInt((float)skeletonRenderers.Count / (float)numThreads); int rangePerThread = Mathf.CeilToInt((float)skeletonRenderers.Count / (float)numThreads);
int skeletonEnd = skeletonRenderers.Count; int skeletonEnd = skeletonRenderers.Count;
#if DONT_WAIT_FOR_ALL_LATEUPDATE_TASKS #if DONT_WAIT_FOR_ALL_LATEUPDATE_TASKS
@ -638,8 +648,8 @@ namespace Spine.Unity {
} }
#if ENABLE_THREAD_PROFILING #if ENABLE_THREAD_PROFILING
CustomSampler[] profilerSamplerUpdate = new CustomSampler[16]; CustomSampler[] profilerSamplerUpdate = null;
CustomSampler[] profilerSamplerLateUpdate = new CustomSampler[16]; CustomSampler[] profilerSamplerLateUpdate = null;
#endif #endif
/// <summary>Perform Update at all SkeletonRenderers asynchronously.</summary> /// <summary>Perform Update at all SkeletonRenderers asynchronously.</summary>
@ -689,7 +699,7 @@ namespace Spine.Unity {
/// <summary>Perform Update at all SkeletonRenderers asynchronously and split off at /// <summary>Perform Update at all SkeletonRenderers asynchronously and split off at
/// main-thread callbacks.</summary> /// main-thread callbacks.</summary>
void UpdateSkeletonsAsyncSplit (SkeletonUpdateRange range, int threadIndex) { void UpdateSkeletonsAsyncSplit (SkeletonUpdateRange range, int threadIndex) {
#if ENABLE_THREAD_PROFILING #if ENABLE_THREAD_PROFILING
if (profilerSamplerUpdate[threadIndex] == null) { if (profilerSamplerUpdate[threadIndex] == null) {
profilerSamplerUpdate[threadIndex] = CustomSampler.Create("Spine Update " + threadIndex); profilerSamplerUpdate[threadIndex] = CustomSampler.Create("Spine Update " + threadIndex);
@ -763,7 +773,7 @@ namespace Spine.Unity {
void UpdateSkeletonsSynchronous (List<SkeletonAnimationBase> skeletons, SkeletonUpdateRange range) { void UpdateSkeletonsSynchronous (List<SkeletonAnimationBase> skeletons, SkeletonUpdateRange range) {
int start = range.rangeStart; int start = range.rangeStart;
int end = range.rangeEndExclusive; int end = range.rangeEndExclusive;
for (int r = start; r < end; ++r) { for (int r = start; r < end; ++r) {
skeletons[r].UpdateInternal(range.deltaTime, range.frameCount, calledFromOnlyMainThread: true); skeletons[r].UpdateInternal(range.deltaTime, range.frameCount, calledFromOnlyMainThread: true);
} }