I’ve been working on a Compute Shader performing a GPU simulation for ~6months, but recently the compile time for my shader has been steadily increasing to unmanageable levels (“Compiling Compute Variants”). I’ve gone from 20-30 seconds to 6/7 minutes in a matter of days.
I have tried clearing out my project library with no luck and there have been some suggestions this can get corrupted.
I’ve narrowed done the suspected issue to a specific function I made to create logs in a compute buffer (that can then be read on the CPU side). The function itself is not different to many others I have, but I am calling it much more often from all over the simulation.
I assume unity is trying to do something clever and creating lots of different variants, but I really don’t understand why its deciding to do this suddenly, why it is necessary (since the added code is fundamentally no different to the existing code), or how to avoid it. Any help/suggestions would be appreciated!!
uint AddNotice(uint id, uint type, uint notice, float4 noticeData) {
//Dont bother trying to add if it is known that the buffer is full;
if (GPUnoticeBufferSize > CounterBufferIndex[0].noticeBufferCount) {
bool valid_slot = false;
uint count = 0;
uint currentIndex;
uint noticeIndex;
while (valid_slot == false && count < GPUnoticeBufferSize) {
// Compute the next index (circular) - although current index is used;
InterlockedAdd(CounterBufferIndex[0].noticeIndex, 1, currentIndex); // % projectileBufferSize;
currentIndex = currentIndex % GPUnoticeBufferSize;
//Keep within bounds of buffer size;
if (CounterBufferIndex[0].noticeIndex >= GPUnoticeBufferSize) {
uint expectedValue = CounterBufferIndex[0].noticeIndex;
uint wrappedIndex = expectedValue % GPUnoticeBufferSize;
while (expectedValue != wrappedIndex) {
InterlockedCompareExchange(CounterBufferIndex[0].noticeIndex, expectedValue, wrappedIndex, expectedValue);
expectedValue = CounterBufferIndex[0].noticeIndex;
}
}
noticeIndex = currentIndex;
//If notice slot is empty - then take this slot
if (GPUExtractNoticesBuffer[noticeIndex].noticeRead == 0) {
GPUExtractNoticesBuffer[noticeIndex].notice = notice;
GPUExtractNoticesBuffer[noticeIndex].obj = id;
//CALC COMBINED TYPE
uint objectBaseType = clamp(type, 1, 2);// Ensure objectBaseType is valid (1 for unit, 2 for projectile)
uint actualType = 999999999;
if (objectBaseType == 1) {
actualType = CombinedBuffer[id].CBunitType;
} else if (objectBaseType == 2) {
actualType = CombinedProjectileBuffer[id].PRJtype;
}
uint combinedType = (actualType * 10) + objectBaseType; // Combine the types
GPUExtractNoticesBuffer[noticeIndex].objType = combinedType;
GPUExtractNoticesBuffer[noticeIndex].noticeData = noticeData;
GPUExtractNoticesBuffer[noticeIndex].noticeTime = totalSimTime;
GPUExtractNoticesBuffer[noticeIndex].noticeRead = 1; //0 = No Notice, 1=Awaiting Reading, 2 = Read
//Increase used projectileBuffer counter;
InterlockedAdd(CounterBufferIndex[0].noticeBufferCount, 1);
valid_slot = true;
}
count = count + 1;
}
if (valid_slot == false) {
CounterBufferIndex[0].majorErrorFlagger = 3; //Set major error - 3 = notice buffer full;
return GPUnoticeBufferSize;
} else {
return noticeIndex;
}
} else {
CounterBufferIndex[0].majorErrorFlagger = 3; //Set major error - 3 = notice buffer full;
return GPUnoticeBufferSize;
}
}