From d0889cec553f30627b6d6f2e62b739a969516c69 Mon Sep 17 00:00:00 2001 From: Andreas Atteneder Date: Fri, 21 May 2021 18:21:02 +0200 Subject: [PATCH] fix: Managed Delegates don't work in Burst, so I converted the index value conversion into a Burst FunctionPointer (sigh) --- CHANGELOG.md | 4 ++ Runtime/Scripts/Draco.asmdef | 3 +- Runtime/Scripts/DracoNative.cs | 114 +++++++++++++++++++++++---------- package.json | 4 +- 4 files changed, 88 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2075e1e..1bddfe7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.1] - 2021-05-21 +### Fixed +- AOT Burst compilation errors + ## [2.0.0] - 2021-05-17 ### Added - Experimental encoding support (ability to convert Unity Meshes into compressed Draco) diff --git a/Runtime/Scripts/Draco.asmdef b/Runtime/Scripts/Draco.asmdef index 47edf6e..890f3a6 100644 --- a/Runtime/Scripts/Draco.asmdef +++ b/Runtime/Scripts/Draco.asmdef @@ -1,7 +1,8 @@ { "name": "Draco", + "rootNamespace": "", "references": [ - "GUID:2665a8d13d1b3f18800f46e256720795" + "Unity.Burst" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Runtime/Scripts/DracoNative.cs b/Runtime/Scripts/DracoNative.cs index dd12f0f..5daa216 100644 --- a/Runtime/Scripts/DracoNative.cs +++ b/Runtime/Scripts/DracoNative.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using AOT; using Unity.Burst; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; @@ -66,6 +67,7 @@ enum AttributeType { GENERIC } + [BurstCompile] unsafe internal class DracoNative { #if UNITY_EDITOR_OSX || UNITY_WEBGL || UNITY_IOS @@ -86,6 +88,14 @@ unsafe internal class DracoNative { const int decoderPtrIndex = 1; const int bufferPtrIndex = 2; + // Cached function pointers + static FunctionPointer GetIndexValueInt8Method; + static FunctionPointer GetIndexValueUInt8Method; + static FunctionPointer GetIndexValueInt16Method; + static FunctionPointer GetIndexValueUInt16Method; + static FunctionPointer GetIndexValueInt32Method; + static FunctionPointer GetIndexValueUInt32Method; + /// /// If true, coordinate space is converted from right-hand (like in glTF) to left-hand (Unity). /// @@ -433,7 +443,8 @@ public JobHandle DecodeVertexData( indicesAttribute = boneIndexMap.dracoAttribute, weightsAttribute = boneWeightMap.dracoAttribute, bonesPerVertex = bonesPerVertex, - boneWeights = boneWeights + boneWeights = boneWeights, + indexValueConverter = GetIndexValueConverter(boneIndexMap.format) }; jobHandles[jobIndex] = job.Schedule(decodeVerticesJobHandle); } @@ -567,6 +578,50 @@ public void DisposeBoneWeightData() { boneWeightMap = null; } + /// + /// Returns Burst compatible function that converts a (bone) index + /// of type `format` into an int + /// + /// Data type of bone index + /// Burst Function Pointer to correct conversion function + /// + static FunctionPointer GetIndexValueConverter(VertexAttributeFormat format) { + switch (format) { + case VertexAttributeFormat.UInt8: + if (!GetIndexValueUInt8Method.IsCreated) { + GetIndexValueUInt8Method = BurstCompiler.CompileFunctionPointer(GetDracoBonesJob.GetIndexValueUInt8); + } + return GetIndexValueUInt8Method; + case VertexAttributeFormat.SInt8: + if (!GetIndexValueInt8Method.IsCreated) { + GetIndexValueInt8Method = BurstCompiler.CompileFunctionPointer(GetDracoBonesJob.GetIndexValueInt8); + } + return GetIndexValueInt8Method; + case VertexAttributeFormat.UInt16: + if (!GetIndexValueUInt16Method.IsCreated) { + GetIndexValueUInt16Method = BurstCompiler.CompileFunctionPointer(GetDracoBonesJob.GetIndexValueUInt16); + } + return GetIndexValueUInt16Method; + case VertexAttributeFormat.SInt16: + if (!GetIndexValueInt16Method.IsCreated) { + GetIndexValueInt16Method = BurstCompiler.CompileFunctionPointer(GetDracoBonesJob.GetIndexValueInt16); + } + return GetIndexValueInt16Method; + case VertexAttributeFormat.UInt32: + if (!GetIndexValueUInt32Method.IsCreated) { + GetIndexValueUInt32Method = BurstCompiler.CompileFunctionPointer(GetDracoBonesJob.GetIndexValueUInt32); + } + return GetIndexValueUInt32Method; + case VertexAttributeFormat.SInt32: + if (!GetIndexValueInt32Method.IsCreated) { + GetIndexValueInt32Method = BurstCompiler.CompileFunctionPointer(GetDracoBonesJob.GetIndexValueInt32); + } + return GetIndexValueInt32Method; + default: + throw new ArgumentOutOfRangeException(nameof(format), format, null); + } + } + // The order must be consistent with C++ interface. [StructLayout (LayoutKind.Sequential)] public struct DracoData { @@ -877,6 +932,10 @@ public void Execute() { [BurstCompile] struct GetDracoBonesJob : IJob { + public delegate int GetIndexValueDelegate(IntPtr baseAddress, int index); + + public FunctionPointer indexValueConverter; + [ReadOnly] public NativeArray result; [ReadOnly] @@ -910,39 +969,14 @@ public void Execute() { DracoData* weightsData = null; GetAttributeData(dracoMesh, weightsAttribute, &weightsData, false); var weightSize = DataTypeSize((DataType)weightsData->dataType) * weightsAttribute->numComponents; - - Func indexValueConverter = null; - switch (indicesDataType) { - case DataType.DT_INT8: - indexValueConverter = GetIndexValueInt8; - break; - case DataType.DT_UINT8: - indexValueConverter = GetIndexValueUInt8; - break; - case DataType.DT_INT16: - indexValueConverter = GetIndexValueInt16; - break; - case DataType.DT_UINT16: - indexValueConverter = GetIndexValueUInt16; - break; - case DataType.DT_INT32: - indexValueConverter = GetIndexValueInt32; - break; - case DataType.DT_UINT32: - indexValueConverter = GetIndexValueUInt32; - break; - default: - Debug.LogError($"Unsupported indicesDataType {indicesDataType}"); - return; - } - + for (var v = 0; v < dracoMesh->numVertices; v++) { bonesPerVertex[v] = (byte) indicesAttribute->numComponents; var indicesPtr = (IntPtr) (((byte*)indicesData->data) + (indexSize * v)); var weightsPtr = (float*) (((byte*)weightsData->data) + (weightSize * v)); for (var b = 0; b < indicesAttribute->numComponents; b++) { boneWeights[v * indicesAttribute->numComponents + b] = new BoneWeight1 { - boneIndex = indexValueConverter(indicesPtr,b), + boneIndex = indexValueConverter.Invoke(indicesPtr,b), weight = *(weightsPtr + b) }; } @@ -951,27 +985,39 @@ public void Execute() { ReleaseDracoData(&weightsData); } - static int GetIndexValueUInt8(IntPtr baseAddress, int index) { + [BurstCompile] + [MonoPInvokeCallback(typeof(GetIndexValueDelegate))] + public static int GetIndexValueUInt8(IntPtr baseAddress, int index) { return *((byte*)baseAddress+index); } - static int GetIndexValueInt8(IntPtr baseAddress, int index) { + [BurstCompile] + [MonoPInvokeCallback(typeof(GetIndexValueDelegate))] + public static int GetIndexValueInt8(IntPtr baseAddress, int index) { return *(((sbyte*)baseAddress)+index); } - static int GetIndexValueUInt16(IntPtr baseAddress, int index) { + [BurstCompile] + [MonoPInvokeCallback(typeof(GetIndexValueDelegate))] + public static int GetIndexValueUInt16(IntPtr baseAddress, int index) { return *(((ushort*)baseAddress)+index); } - static int GetIndexValueInt16(IntPtr baseAddress, int index) { + [BurstCompile] + [MonoPInvokeCallback(typeof(GetIndexValueDelegate))] + public static int GetIndexValueInt16(IntPtr baseAddress, int index) { return *(((short*)baseAddress)+index); } - static int GetIndexValueUInt32(IntPtr baseAddress, int index) { + [BurstCompile] + [MonoPInvokeCallback(typeof(GetIndexValueDelegate))] + public static int GetIndexValueUInt32(IntPtr baseAddress, int index) { return (int) *(((uint*)baseAddress)+index); } - static int GetIndexValueInt32(IntPtr baseAddress, int index) { + [BurstCompile] + [MonoPInvokeCallback(typeof(GetIndexValueDelegate))] + public static int GetIndexValueInt32(IntPtr baseAddress, int index) { return *(((int*)baseAddress)+index); } } diff --git a/package.json b/package.json index 5e982f0..dd930be 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "com.atteneder.draco", - "version": "2.0.0", + "version": "2.0.1", "displayName": "Draco 3D Data Compression", "description": "Apply Draco compression to meshes and load them at runtime.", "unity": "2019.3", "dependencies": { - "com.unity.burst": "1.4.4" + "com.unity.burst": "1.4.8" }, "keywords": [ "mesh",