Hi! Let me know if this is in the wrong place.
Imagine you’re writing a job that has first some set-up code, then a hot loop. Inside the loop you might want to do either A or B, say call either one method or another.
You have two alternatives: either you accept a branch in your hot loop, or you write two jobs where everything except that inner method call is identical. This is what I have been doing, but maintaining duplicate code is sub-optimal.
Instead, I’d like to be able to tell the burst compiler that I promise it a certain variable won’t ever change while inside the job, that the variable is fixed on schedule time. This would allow the compiler to get rid of branches based on that variable, and the hot loop could run branch-less.
Example:
[BurstCompile]
struct BlurJob : IJobParallelForBatch
{
[ReadOnly] public float valueA;
[ReadOnly] public float valueB;
[ReadOnly] public float valueC;
[ReadOnly] public NativeArray<float4> pixelsIn;
[WriteOnly] public NativeArray<float4> pixelsOut;
enum FilterType { HQ, LQ };
[SheduleTimeStatic] public FilterType _fType;
public void Execute(int startIndex, int batchSize) {
//this set up code is the same for all versions of the job
float d = valueA + valueB;
float e = d + valueC;
//so is this loop
for (int i = startIndex; i < startIndex + batchSize; i++) {
float f = e + i;
//this is different for each of the two versions of the job. The job is
//re-compiled for each novel value of this, so the condition is never
//checked in run-time
switch(_fType){
case HQ: pixelsOut[i] = HighQualityBlur(pixelsIn[i], f); break;
case LQ: pixelsOut[i] = LowQualityBlur(pixelsIn[i], f); break;
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static float4 HighQualityBlur(float4 in, float something)
{
...
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static float4 LowQualityBlur(float4 in, float something)
{
...
}
}
The compiler would basically create 2 different versions of the above job, where only what happened in the loop would be different. It would be able to do this because the [SheduleTimeStatic] tag promises it that the value won’t change inside the job, so it could treat it as a compile time constant.
As you’re aware, there are a multitude of other cases where the compiler can do a much better job if it knows what a value is at compile-time. Such as more efficient vectorization if it knows the iteration count when looping over an array, and more efficient division/multiplication if it knows that it’s dealing with a power of two.
If the specific hardware it’s compiling for doesn’t support this for any reason, it could just fall back on ignoring the [SheduleTimeStatic] symbol. This would mean checking the condition in run-time, which would be slower but produce an identical result.
Thank you for your time!