Skip to content

Commit 8b3eb5c

Browse files
committed
Refactor Burst jobs
1 parent 8b75fb1 commit 8b3eb5c

File tree

2 files changed

+88
-96
lines changed

2 files changed

+88
-96
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
### Added
33
- Add `CHANGELOG.md`.
44

5+
### Changed
6+
- Refactor Burst jobs.
7+
58
### Fixed
69
- Fix typo in `README.md`.
710
- Fix performance issue when importing PNG without alpha channel.

Runtime/ImageImporter.cs

Lines changed: 85 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,15 @@ int CalculateMipmapCount(bool forceAutoCount = false) {
142142
return mipmapCount;
143143
}
144144

145-
Vector2Int CalculateMipmapDimensions(int mipmapLevel) {
145+
int2 CalculateMipmapDimensions(int mipmapLevel) {
146146
// Base level
147147
if (mipmapLevel == 0) {
148-
return new Vector2Int(_width, _height);
148+
return int2(_width, _height);
149149
} else {
150150
var mipmapFactor = Mathf.Pow(2f, -mipmapLevel);
151151
var mipmapWidth = Mathf.Max(1, Mathf.FloorToInt(mipmapFactor * _width));
152152
var mipmapHeight = Mathf.Max(1, Mathf.FloorToInt(mipmapFactor * _height));
153-
return new Vector2Int(mipmapWidth, mipmapHeight);
153+
return int2(mipmapWidth, mipmapHeight);
154154
}
155155
}
156156

@@ -213,36 +213,26 @@ void ProcessRawTextureData(NativeArray<byte> rawTextureView, int mipmapCount) {
213213
var mipmapSlice = new NativeSlice<byte>(rawTextureView, 0, _pixelSize * mipmapSize);
214214
var mipmapIndex = _pixelSize * mipmapSize;
215215

216-
_finalJob = _textureFormat == TextureFormat.RGBA32 ?
217-
new SwapGBRA32ToRGBA32Job {
218-
mipmapSlice = mipmapSlice
219-
}.Schedule(mipmapSize, 8192) :
220-
new SwapGBR24ToRGB24Job {
221-
mipmapSlice = mipmapSlice
222-
}.Schedule(mipmapSize, 8192);
216+
_finalJob = new BGRToRGBJob {
217+
textureData = mipmapSlice,
218+
processFunction = _textureFormat == TextureFormat.RGBA32 ?
219+
BGRToRGBJob.BGRA32ToRGBA32FP : BGRToRGBJob.BGR24ToRGB24FP
220+
}.Schedule(mipmapSize, 8192);
223221

224222
for (int mipmapLevel = 1; mipmapLevel < mipmapCount; mipmapLevel++) {
225223
var nextMipmapDimensions = CalculateMipmapDimensions(mipmapLevel);
226224
mipmapSize = nextMipmapDimensions.x * nextMipmapDimensions.y;
227225
var nextMipmapSlice = new NativeSlice<byte>(rawTextureView, mipmapIndex, _pixelSize * mipmapSize);
228226
mipmapIndex += _pixelSize * mipmapSize;
229-
_finalJob = _textureFormat == TextureFormat.RGBA32 ?
230-
new FilterMipmapRGBA32Job {
231-
inputWidth = mipmapDimensions.x,
232-
inputHeight = mipmapDimensions.y,
233-
inputMipmap = mipmapSlice.SliceConvert<uint>(),
234-
outputWidth = nextMipmapDimensions.x,
235-
outputHeight = nextMipmapDimensions.y,
236-
outputMipmap = nextMipmapSlice.SliceConvert<uint>(),
237-
}.Schedule(mipmapSize, 1024, _finalJob) :
238-
new FilterMipmapRGB24Job {
239-
inputWidth = mipmapDimensions.x,
240-
inputHeight = mipmapDimensions.y,
241-
inputMipmap = mipmapSlice,
242-
outputWidth = nextMipmapDimensions.x,
243-
outputHeight = nextMipmapDimensions.y,
244-
outputMipmap = nextMipmapSlice,
245-
}.Schedule(mipmapSize, 1024, _finalJob);
227+
228+
_finalJob = new FilterMipmapJob {
229+
inputMipmap = mipmapSlice,
230+
inputDimensions = mipmapDimensions,
231+
outputMipmap = nextMipmapSlice,
232+
outputDimensions = nextMipmapDimensions,
233+
processFunction = _textureFormat == TextureFormat.RGBA32 ?
234+
FilterMipmapJob.FilterMipmapRGBA32FP : FilterMipmapJob.FilterMipmapRGB24FP
235+
}.Schedule(mipmapSize, 1024, _finalJob);
246236

247237
mipmapDimensions = nextMipmapDimensions;
248238
mipmapSlice = nextMipmapSlice;
@@ -251,98 +241,97 @@ void ProcessRawTextureData(NativeArray<byte> rawTextureView, int mipmapCount) {
251241
}
252242

253243
[BurstCompile(CompileSynchronously = true)]
254-
struct SwapGBR24ToRGB24Job : IJobParallelFor {
255-
[NativeDisableParallelForRestriction]
256-
public NativeSlice<byte> mipmapSlice;
244+
struct BGRToRGBJob : IJobParallelFor {
245+
public delegate void BGRToRGBDelegate(ref NativeSlice<byte> textureData, int index);
257246

258-
public void Execute(int index) {
259-
var temp = mipmapSlice[3 * index];
260-
mipmapSlice[3 * index] = mipmapSlice[3 * index + 2];
261-
mipmapSlice[3 * index + 2] = temp;
247+
public static readonly FunctionPointer<BGRToRGBDelegate> BGR24ToRGB24FP = BurstCompiler.CompileFunctionPointer<BGRToRGBDelegate>(BGR24ToRGB24);
248+
public static readonly FunctionPointer<BGRToRGBDelegate> BGRA32ToRGBA32FP = BurstCompiler.CompileFunctionPointer<BGRToRGBDelegate>(BGRA32ToRGBA32);
249+
250+
[BurstCompile(CompileSynchronously = true)]
251+
static void BGR24ToRGB24(ref NativeSlice<byte> textureData, int index) {
252+
var temp = textureData[mad(3, index, 0)];
253+
textureData[mad(3, index, 0)] = textureData[mad(3, index, 2)];
254+
textureData[mad(3, index, 2)] = temp;
255+
}
256+
257+
[BurstCompile(CompileSynchronously = true)]
258+
static void BGRA32ToRGBA32(ref NativeSlice<byte> textureData, int index) {
259+
var temp = textureData[mad(4, index, 0)];
260+
textureData[mad(4, index, 0)] = textureData[mad(4, index, 2)];
261+
textureData[mad(4, index, 2)] = temp;
262262
}
263-
}
264263

265-
[BurstCompile(CompileSynchronously = true)]
266-
struct SwapGBRA32ToRGBA32Job : IJobParallelFor {
267264
[NativeDisableParallelForRestriction]
268-
public NativeSlice<byte> mipmapSlice;
265+
public NativeSlice<byte> textureData;
266+
public FunctionPointer<BGRToRGBDelegate> processFunction;
269267

270-
public void Execute(int index) {
271-
var temp = mipmapSlice[4 * index];
272-
mipmapSlice[4 * index] = mipmapSlice[4 * index + 2];
273-
mipmapSlice[4 * index + 2] = temp;
274-
}
268+
public void Execute(int index) => processFunction.Invoke(ref textureData, index);
275269
}
276270

277271
[BurstCompile(CompileSynchronously = true)]
278-
struct FilterMipmapRGB24Job : IJobParallelFor {
279-
public int inputWidth;
280-
public int inputHeight;
281-
[ReadOnly]
282-
public NativeSlice<byte> inputMipmap;
272+
struct FilterMipmapJob : IJobParallelFor {
273+
public delegate void FilterMipmapDelegate(ref FilterMipmapJob job, int outputIndex);
283274

284-
public int outputWidth;
285-
public int outputHeight;
286-
[WriteOnly, NativeDisableParallelForRestriction]
287-
public NativeSlice<byte> outputMipmap;
275+
public static readonly FunctionPointer<FilterMipmapDelegate> FilterMipmapRGB24FP = BurstCompiler.CompileFunctionPointer<FilterMipmapDelegate>(FilterMipmapRGB24);
276+
public static readonly FunctionPointer<FilterMipmapDelegate> FilterMipmapRGBA32FP = BurstCompiler.CompileFunctionPointer<FilterMipmapDelegate>(FilterMipmapRGBA32);
288277

289-
public void Execute(int index) {
290-
var outputX = index % outputWidth;
291-
var outputY = index / outputWidth;
278+
[BurstCompile(CompileSynchronously = true)]
279+
static void FilterMipmapRGB24(ref FilterMipmapJob job, int outputIndex) {
280+
var outputX = outputIndex % job.outputDimensions.x;
281+
var outputY = outputIndex / job.outputDimensions.x;
292282
var outputColor = new uint3();
293283

294-
for (var offsetX = 0; offsetX < 2; offsetX++) {
295-
for (var offsetY = 0; offsetY < 2; offsetY++) {
296-
var inputX = min(mad(2, outputX, offsetX), inputWidth - 1);
297-
var inputY = min(mad(2, outputY, offsetY), inputHeight - 1);
298-
var inputIndex = mad(inputWidth, inputY, inputX);
299-
outputColor.x += (uint)inputMipmap[mad(3, inputIndex, 0)] >> 2;
300-
outputColor.y += (uint)inputMipmap[mad(3, inputIndex, 1)] >> 2;
301-
outputColor.z += (uint)inputMipmap[mad(3, inputIndex, 2)] >> 2;
284+
for (var offsetY = 0; offsetY < 2; offsetY++) {
285+
for (var offsetX = 0; offsetX < 2; offsetX++) {
286+
var inputX = min(mad(2, outputX, offsetX), job.inputDimensions.x - 1);
287+
var inputY = min(mad(2, outputY, offsetY), job.inputDimensions.y - 1);
288+
var inputIndex = mad(job.inputDimensions.x, inputY, inputX);
289+
outputColor.x += (uint)job.inputMipmap[mad(3, inputIndex, 0)] >> 2;
290+
outputColor.y += (uint)job.inputMipmap[mad(3, inputIndex, 1)] >> 2;
291+
outputColor.z += (uint)job.inputMipmap[mad(3, inputIndex, 2)] >> 2;
302292
}
303293
}
304294

305-
outputMipmap[mad(3, index, 0)] = (byte)outputColor.x;
306-
outputMipmap[mad(3, index, 1)] = (byte)outputColor.y;
307-
outputMipmap[mad(3, index, 2)] = (byte)outputColor.z;
295+
job.outputMipmap[mad(3, outputIndex, 0)] = (byte)outputColor.x;
296+
job.outputMipmap[mad(3, outputIndex, 1)] = (byte)outputColor.y;
297+
job.outputMipmap[mad(3, outputIndex, 2)] = (byte)outputColor.z;
308298
}
309-
}
310299

311-
[BurstCompile(CompileSynchronously = true)]
312-
struct FilterMipmapRGBA32Job : IJobParallelFor {
313-
public int inputWidth;
314-
public int inputHeight;
315-
[ReadOnly]
316-
public NativeSlice<uint> inputMipmap;
317-
318-
public int outputWidth;
319-
public int outputHeight;
320-
[WriteOnly]
321-
public NativeSlice<uint> outputMipmap;
322-
323-
public void Execute(int index) {
324-
var outputX = index % outputWidth;
325-
var outputY = index / outputWidth;
300+
[BurstCompile(CompileSynchronously = true)]
301+
static void FilterMipmapRGBA32(ref FilterMipmapJob job, int outputIndex) {
302+
var outputX = outputIndex % job.outputDimensions.x;
303+
var outputY = outputIndex / job.outputDimensions.x;
326304
var outputColor = new uint4();
327305

328-
for (var offsetX = 0; offsetX < 2; offsetX++) {
329-
for (var offsetY = 0; offsetY < 2; offsetY++) {
330-
var inputX = min(mad(2, outputX, offsetX), inputWidth - 1);
331-
var inputY = min(mad(2, outputY, offsetY), inputHeight - 1);
332-
var inputColor = inputMipmap[mad(inputWidth, inputY, inputX)];
333-
outputColor.x += (inputColor & 0x000000FFu) >> 2;
334-
outputColor.y += (inputColor & 0x0000FF00u) >> 10;
335-
outputColor.z += (inputColor & 0x00FF0000u) >> 18;
336-
outputColor.w += (inputColor & 0xFF000000u) >> 26;
306+
for (var offsetY = 0; offsetY < 2; offsetY++) {
307+
for (var offsetX = 0; offsetX < 2; offsetX++) {
308+
var inputX = min(mad(2, outputX, offsetX), job.inputDimensions.x - 1);
309+
var inputY = min(mad(2, outputY, offsetY), job.inputDimensions.y - 1);
310+
var inputIndex = mad(job.inputDimensions.x, inputY, inputX);
311+
outputColor.x += (uint)job.inputMipmap[mad(4, inputIndex, 0)] >> 2;
312+
outputColor.y += (uint)job.inputMipmap[mad(4, inputIndex, 1)] >> 2;
313+
outputColor.z += (uint)job.inputMipmap[mad(4, inputIndex, 2)] >> 2;
314+
outputColor.w += (uint)job.inputMipmap[mad(4, inputIndex, 3)] >> 2;
337315
}
338316
}
339317

340-
outputMipmap[index] =
341-
(outputColor.x << 0) |
342-
(outputColor.y << 8) |
343-
(outputColor.z << 16) |
344-
(outputColor.w << 24);
318+
job.outputMipmap[mad(4, outputIndex, 0)] = (byte)outputColor.x;
319+
job.outputMipmap[mad(4, outputIndex, 1)] = (byte)outputColor.y;
320+
job.outputMipmap[mad(4, outputIndex, 2)] = (byte)outputColor.z;
321+
job.outputMipmap[mad(4, outputIndex, 3)] = (byte)outputColor.w;
345322
}
323+
324+
[ReadOnly]
325+
public NativeSlice<byte> inputMipmap;
326+
public int2 inputDimensions;
327+
328+
[WriteOnly, NativeDisableParallelForRestriction]
329+
public NativeSlice<byte> outputMipmap;
330+
public int2 outputDimensions;
331+
332+
public FunctionPointer<FilterMipmapDelegate> processFunction;
333+
334+
public void Execute(int outputIndex) => processFunction.Invoke(ref this, outputIndex);
346335
}
347336
}
348337
}

0 commit comments

Comments
 (0)