Example #1
0
        private void RenderButtonBars(float width, BurstCompileTarget target, out bool doRefresh, out bool doCopy, out int fontIndex)
        {
            float remainingWidth = width;

            var contentDisasm         = new GUIContent("Enhanced Disassembly");
            var contentSafety         = new GUIContent("Safety Checks");
            var contentOptimizations  = new GUIContent("Optimizations");
            var contentFastMath       = new GUIContent("Fast Math");
            var contentCodeGenOptions = new GUIContent("Auto");
            var contentLabelFontSize  = new GUIContent("Font Size");
            var contentFontSize       = new GUIContent("99");
            var contentRefresh        = new GUIContent("Refresh Disassembly");
            var contentCopyToClip     = new GUIContent("Copy to Clipboard");

            GUILayout.BeginHorizontal();

            _enhancedDisassembly = GUILayout.Toggle(_enhancedDisassembly, contentDisasm, EditorStyles.toggle);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.toggle, contentDisasm);
            _safetyChecks = GUILayout.Toggle(_safetyChecks, contentSafety, EditorStyles.toggle);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.toggle, contentSafety);
            _optimizations = GUILayout.Toggle(_optimizations, contentOptimizations, EditorStyles.toggle);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.toggle, contentOptimizations);
            _fastMath = GUILayout.Toggle(_fastMath, contentFastMath, EditorStyles.toggle);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.toggle, contentFastMath);

            EditorGUI.BeginDisabledGroup(!target.IsSupported);
            _codeGenOptions = EditorGUILayout.Popup(_codeGenOptions, CodeGenOptions, EditorStyles.popup);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.popup, contentCodeGenOptions);

            GUILayout.Label("Font Size", EditorStyles.label);
            fontIndex = EditorGUILayout.Popup(_fontSizeIndex, _fontSizesText, EditorStyles.popup);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.label, contentLabelFontSize);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.popup, contentFontSize);

            doRefresh = GUILayout.Button(contentRefresh, EditorStyles.miniButton);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.miniButton, contentRefresh);

            doCopy = GUILayout.Button(contentCopyToClip, EditorStyles.miniButton);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.miniButton, contentCopyToClip);
            EditorGUI.EndDisabledGroup();

            GUILayout.EndHorizontal();

            _disasmKind = (DisassemblyKind)GUILayout.Toolbar((int)_disasmKind, DisassemblyKindNames, GUILayout.Width(width));
        }
        private void RenderButtonBars(float width, BurstCompileTarget target, out bool doCopy, out int fontIndex)
        {
            float remainingWidth = width;

            var contentDisasm         = new GUIContent("Enhanced Disassembly");
            var contentSafety         = new GUIContent("Safety Checks");
            var contentCodeGenOptions = new GUIContent("Auto");
            var contentLabelFontSize  = new GUIContent("Font Size");
            var contentFontSize       = new GUIContent("99");
            var contentCopyToClip     = new GUIContent("Copy to Clipboard");

            GUILayout.BeginHorizontal();

            _assemblyKind = EditorGUILayout.Popup(_assemblyKind, AssemblyOptions, EditorStyles.popup);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.popup, contentDisasm);

            _safetyChecks = GUILayout.Toggle(_safetyChecks, contentSafety, EditorStyles.toggle);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.toggle, contentSafety);

            EditorGUI.BeginDisabledGroup(!target.HasRequiredBurstCompileAttributes);

            _targetCpu = (TargetCpu)EditorGUILayout.Popup((int)_targetCpu, TargetCpuNames, EditorStyles.popup);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.popup, contentCodeGenOptions);

            GUILayout.Label("Font Size", EditorStyles.label);
            fontIndex = EditorGUILayout.Popup(_fontSizeIndex, _fontSizesText, EditorStyles.popup);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.label, contentLabelFontSize);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.popup, contentFontSize);

            doCopy = GUILayout.Button(contentCopyToClip, EditorStyles.miniButton);
            FlowToNewLine(ref remainingWidth, width, EditorStyles.miniButton, contentCopyToClip);
            EditorGUI.EndDisabledGroup();

            GUILayout.EndHorizontal();

            _disasmKind = (DisassemblyKind)GUILayout.Toolbar((int)_disasmKind, DisassemblyKindNames, GUILayout.ExpandWidth(true), GUILayout.MinWidth(5 * 10));
        }
        public static List <BurstCompileTarget> FindExecuteMethods(AssembliesType assemblyTypes)
        {
            var methodsToCompile    = new List <BurstCompileTarget>();
            var methodsToCompileSet = new HashSet <MethodInfo>();

            var valueTypes          = new List <TypeToVisit>();
            var interfaceToProducer = new Dictionary <Type, Type>();

            var assemblyList = GetAssemblyList(assemblyTypes);
            //Debug.Log("Filtered Assembly List: " + string.Join(", ", assemblyList.Select(assembly => assembly.GetName().Name)));

            // Find all ways to execute job types (via producer attributes)
            var typesVisited = new HashSet <string>();
            var typesToVisit = new HashSet <string>();

            foreach (var assembly in assemblyList)
            {
                var types = new List <Type>();
                try
                {
                    types.AddRange(assembly.GetTypes());
                    // Collect all generic type instances (excluding indirect instances)
                    CollectGenericTypeInstances(assembly, types);
                }
                catch (Exception ex)
                {
                    Debug.LogWarning("Unexpected exception while collecting types in assembly `" + assembly.FullName + "` Exception: " + ex);
                }

                for (var i = 0; i < types.Count; i++)
                {
                    var t = types[i];
                    if (typesToVisit.Add(t.FullName))
                    {
                        // Because the list of types returned by CollectGenericTypeInstances does not detect nested generic classes that are not
                        // used explicitly, we need to create them if a declaring type is actually used
                        // so for example if we have:
                        // class MyClass<T> { class MyNestedClass { } }
                        // class MyDerived : MyClass<int> { }
                        // The CollectGenericTypeInstances will return typically the type MyClass<int>, but will not list MyClass<int>.MyNestedClass
                        // So the following code is correcting this in order to fully query the full graph of generic instance types, including indirect types
                        var nestedTypes = t.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
                        foreach (var nestedType in nestedTypes)
                        {
                            if (t.IsGenericType && !t.IsGenericTypeDefinition)
                            {
                                var parentGenericTypeArguments = t.GetGenericArguments();
                                // Only create nested types that are closed generic types (full generic instance types)
                                // It happens if for example the parent class is `class MClass<T> { class MyNestedGeneric<T1> {} }`
                                // In that case, MyNestedGeneric<T1> is closed in the context of MClass<int>, so we don't process them
                                if (nestedType.GetGenericArguments().Length == parentGenericTypeArguments.Length)
                                {
                                    var instanceNestedType = nestedType.MakeGenericType(parentGenericTypeArguments);
                                    types.Add(instanceNestedType);
                                }
                            }
                            else
                            {
                                types.Add(nestedType);
                            }
                        }
                    }
                }

                foreach (var t in types)
                {
                    // If the type has been already visited, don't try to visit it
                    if (!typesVisited.Add(t.FullName) || (t.IsGenericTypeDefinition && !t.IsInterface))
                    {
                        continue;
                    }

                    try
                    {
                        // collect methods with types having a [BurstCompile] attribute
                        bool visitStaticMethods = HasBurstCompileAttribute(t);
                        bool isValueType        = false;

                        if (t.IsInterface)
                        {
                            object[] attrs = t.GetCustomAttributes(typeof(JobProducerTypeAttribute), false);
                            if (attrs.Length == 0)
                            {
                                continue;
                            }

                            JobProducerTypeAttribute attr = (JobProducerTypeAttribute)attrs[0];

                            interfaceToProducer.Add(t, attr.ProducerType);

                            //Debug.Log($"{t} has producer {attr.ProducerType}");
                        }
                        else if (t.IsValueType)
                        {
                            // NOTE: Make sure that we don't use a value type generic definition (e.g `class Outer<T> { struct Inner { } }`)
                            // We are only working on plain type or generic type instance!
                            if (!t.IsGenericTypeDefinition)
                            {
                                isValueType = true;
                            }
                        }

                        if (isValueType || visitStaticMethods)
                        {
                            valueTypes.Add(new TypeToVisit(t, visitStaticMethods));
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.LogWarning("Unexpected exception while inspecting type `" + t +
                                         "` IsConstructedGenericType: " + t.IsConstructedGenericType +
                                         " IsGenericTypeDef: " + t.IsGenericTypeDefinition +
                                         " IsGenericParam: " + t.IsGenericParameter +
                                         " Exception: " + ex);
                    }
                }
            }

            //Debug.Log($"Mapped {interfaceToProducer.Count} producers; {valueTypes.Count} value types");

            // Revisit all types to find things that are compilable using the above producers.
            foreach (var typePair in valueTypes)
            {
                var type = typePair.Type;

                // collect static [BurstCompile] methods
                if (typePair.CollectStaticMethods)
                {
                    try
                    {
                        var methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                        foreach (var method in methods)
                        {
                            if (HasBurstCompileAttribute(method))
                            {
                                var target = new BurstCompileTarget(method, type, null, true);
                                methodsToCompile.Add(target);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.LogException(ex);
                    }
                }

                // If the type is not a value type, we don't need to proceed with struct Jobs
                if (!type.IsValueType)
                {
                    continue;
                }

                // Otherwise try to find if we have an interface producer setup on the class
                foreach (var interfaceType in type.GetInterfaces())
                {
                    var genericLessInterface = interfaceType;
                    if (interfaceType.IsGenericType)
                    {
                        genericLessInterface = interfaceType.GetGenericTypeDefinition();
                    }

                    Type foundProducer;
                    if (interfaceToProducer.TryGetValue(genericLessInterface, out foundProducer))
                    {
                        var genericParams = new List <Type> {
                            type
                        };
                        if (interfaceType.IsGenericType)
                        {
                            genericParams.AddRange(interfaceType.GenericTypeArguments);
                        }

                        try
                        {
                            var executeType   = foundProducer.MakeGenericType(genericParams.ToArray());
                            var executeMethod = executeType.GetMethod("Execute");
                            if (executeMethod == null)
                            {
                                throw new InvalidOperationException($"Burst reflection error. The type `{executeType}` does not contain an `Execute` method");
                            }

                            // We will not try to record more than once a method in the methods to compile
                            // This can happen if a job interface is inheriting from another job interface which are using in the end the same
                            // job producer type
                            if (methodsToCompileSet.Add(executeMethod))
                            {
                                var target = new BurstCompileTarget(executeMethod, type, interfaceType, false);
                                methodsToCompile.Add(target);
                            }
                        }
                        catch (Exception ex)
                        {
                            Debug.LogException(ex);
                        }
                    }
                }
            }

            return(methodsToCompile);
        }