Exemple #1
0
        /// <summary>
        /// Check whether commands implemented by the current driver have a corresponding extension declaring the
        /// support of them.
        /// </summary>
        /// <param name="version">
        /// The <see cref="KhronosVersion" /> currently implemented by the current context on this thread.
        /// </param>
        /// <param name="extensions">
        /// The <see cref="ExtensionsCollection" /> that specifies the extensions supported by the driver.
        /// </param>
        /// <param name="enableExtensions"></param>
        protected static void CheckExtensionCommands(KhronosVersion version, ExtensionsCollection extensions, bool enableExtensions)
        {
            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }
            if (extensions == null)
            {
                throw new ArgumentNullException(nameof(extensions));
            }

            var hiddenVersions   = new Dictionary <string, List <Type> >();
            var hiddenExtensions = new Dictionary <string, bool>();

            foreach (FieldInfo fi in _functionContext.Delegates)
            {
                var  fiDelegateType     = (Delegate)fi.GetValue(null);
                bool commandDefined     = fiDelegateType != null;
                var  supportedByFeature = false;

                // Get the delegate type
                Type delegateType = fi.DeclaringType?.GetNestedType(fi.Name.Substring(1), BindingFlags.Public | BindingFlags.NonPublic);
                if (delegateType == null)
                {
                    continue; // Support fields names not in sync with delegate types
                }
                // TODO Why not use 'fi' directly for getting attributes? They should be in sync
                IEnumerable <object> requiredByFeatureAttributes = delegateType.GetCustomAttributes(typeof(RequiredByFeatureAttribute), false);

                foreach (RequiredByFeatureAttribute requiredByFeatureAttribute in requiredByFeatureAttributes)
                {
                    supportedByFeature |= requiredByFeatureAttribute.IsSupported(version, extensions);
                }

                // Find the underlying extension
                RequiredByFeatureAttribute hiddenVersionAttrib   = null;
                RequiredByFeatureAttribute hiddenExtensionAttrib = null;

                foreach (RequiredByFeatureAttribute requiredByFeatureAttribute in requiredByFeatureAttributes)
                {
                    if (requiredByFeatureAttribute.IsSupportedApi(version.Api) == false)
                    {
                        // Version attribute
                        if (hiddenVersionAttrib == null)
                        {
                            hiddenVersionAttrib = requiredByFeatureAttribute;
                        }
                    }
                    else
                    {
                        // Extension attribute
                        if (hiddenExtensionAttrib == null)
                        {
                            hiddenExtensionAttrib = requiredByFeatureAttribute;
                        }
                    }
                }

                if (commandDefined != supportedByFeature)
                {
                    if (commandDefined)
                    {
                        if (hiddenVersionAttrib != null && hiddenExtensionAttrib == null)
                        {
                            if (hiddenVersions.TryGetValue(hiddenVersionAttrib.FeatureName, out List <Type> versionDelegates) == false)
                            {
                                hiddenVersions.Add(hiddenVersionAttrib.FeatureName, versionDelegates = new List <Type>());
                            }
                            versionDelegates.Add(delegateType);
                        }

                        if (hiddenExtensionAttrib != null) // Eventually leave to false for incomplete extensions
                        {
                            if (hiddenExtensions.ContainsKey(hiddenExtensionAttrib.FeatureName) == false)
                            {
                                hiddenExtensions.Add(hiddenExtensionAttrib.FeatureName, true);
                            }
                        }
                    }
                }

                // Partial extensions are not supported
                if (hiddenExtensionAttrib != null && commandDefined == false && hiddenExtensions.ContainsKey(hiddenExtensionAttrib.FeatureName))
                {
                    hiddenExtensions[hiddenExtensionAttrib.FeatureName] = false;
                }
            }

            if (!enableExtensions)
            {
                return;
            }

            var sync = false;

            foreach (KeyValuePair <string, bool> hiddenExtension in hiddenExtensions.Where(hiddenExtension => hiddenExtension.Value))
            {
                extensions.EnableExtension(hiddenExtension.Key);
                sync = true;
            }

            if (sync)
            {
                extensions.SyncMembers(version);
            }
        }
Exemple #2
0
        /// <summary>
        /// Check whether commands implemented by the current driver have a corresponding extension declaring the
        /// support of them.
        /// </summary>
        /// <typeparam name="T">
        /// The type of the KhronosApi to inspect for commands.
        /// </typeparam>
        /// <param name="version">
        /// The <see cref="KhronosVersion"/> currently implemented by the current context on this thread.
        /// </param>
        /// <param name="extensions">
        /// The <see cref="ExtensionsCollection"/> that specifies the extensions supported by the driver.
        /// </param>
        protected static void CheckExtensionCommands <T>(KhronosVersion version, ExtensionsCollection extensions, bool enableExtensions) where T : KhronosApi
        {
            if (version == null)
            {
                throw new ArgumentNullException("version");
            }
            if (extensions == null)
            {
                throw new ArgumentNullException("extensions");
            }

#if !NETCORE
            Type            apiType         = typeof(T);
            FunctionContext functionContext = GetFunctionContext(apiType);

            Debug.Assert(functionContext != null);
            if (functionContext == null)
            {
                throw new InvalidOperationException("unrecognized API type");
            }

            LogComment("Checking commands for {0}", version);

            Dictionary <string, List <Type> > hiddenVersions   = new Dictionary <string, List <Type> >();
            Dictionary <string, bool>         hiddenExtensions = new Dictionary <string, bool>();

            foreach (FieldInfo fi in functionContext.Delegates)
            {
                Delegate fiDelegateType     = (Delegate)fi.GetValue(null);
                string   commandName        = fi.Name.Substring(3);
                bool     commandDefined     = fiDelegateType != null;
                bool     supportedByFeature = false;

                Type delegateType = fi.DeclaringType.GetNestedType(fi.Name.Substring(1), BindingFlags.Public | BindingFlags.NonPublic);
                IEnumerable <object> requiredByFeatureAttributes = delegateType.GetCustomAttributes(typeof(RequiredByFeatureAttribute), false);

                foreach (RequiredByFeatureAttribute requiredByFeatureAttribute in requiredByFeatureAttributes)
                {
                    supportedByFeature |= requiredByFeatureAttribute.IsSupported(version, extensions);
                }

                // Find the underlying extension
                RequiredByFeatureAttribute hiddenVersionAttrib   = null;
                RequiredByFeatureAttribute hiddenExtensionAttrib = null;

                foreach (RequiredByFeatureAttribute requiredByFeatureAttribute in requiredByFeatureAttributes)
                {
                    if (requiredByFeatureAttribute.IsSupportedApi(version.Api) == false)
                    {
                        // Version attribute
                        if (hiddenVersionAttrib == null)
                        {
                            hiddenVersionAttrib = requiredByFeatureAttribute;
                        }
                    }
                    else
                    {
                        // Extension attribute
                        if (hiddenExtensionAttrib == null)
                        {
                            hiddenExtensionAttrib = requiredByFeatureAttribute;
                        }
                    }
                }

                if (commandDefined != supportedByFeature)
                {
#if DEBUG_VERBOSE
                    string supportString = "any feature";

                    if (hiddenVersionAttrib != null)
                    {
                        supportString = hiddenVersionAttrib.FeatureName;
                        if (hiddenExtensionAttrib != null)
                        {
                            supportString += " or ";
                        }
                    }

                    if (hiddenExtensionAttrib != null)
                    {
                        if (hiddenVersionAttrib == null)
                        {
                            supportString = String.Empty;
                        }
                        supportString += hiddenExtensionAttrib.FeatureName;
                    }
#endif

                    if (commandDefined)
                    {
#if DEBUG_VERBOSE
                        LogComment("The command {0} is defined, but {1} support is not advertised.", commandName, supportString);
#endif
                        if (hiddenVersionAttrib != null && hiddenExtensionAttrib == null)
                        {
                            List <Type> versionDelegates = new List <Type>();

                            if (hiddenVersions.TryGetValue(hiddenVersionAttrib.FeatureName, out versionDelegates) == false)
                            {
                                hiddenVersions.Add(hiddenVersionAttrib.FeatureName, versionDelegates = new List <Type>());
                            }
                            versionDelegates.Add(delegateType);
                        }

                        if (hiddenExtensionAttrib != null)
                        {
                            // Eventually leave to false for incomplete extensions
                            if (hiddenExtensions.ContainsKey(hiddenExtensionAttrib.FeatureName) == false)
                            {
                                hiddenExtensions.Add(hiddenExtensionAttrib.FeatureName, true);
                            }
                        }
                    }
                    else
                    {
#if DEBUG_VERBOSE
                        LogComment("The command {0} is not defined, but required by some feature.", commandName);
#endif
                    }
                }

                // Partial extensions are not supported
                if (hiddenExtensionAttrib != null && commandDefined == false && hiddenExtensions.ContainsKey(hiddenExtensionAttrib.FeatureName))
                {
                    hiddenExtensions[hiddenExtensionAttrib.FeatureName] = false;
                }
            }

            if (hiddenExtensions.Count > 0)
            {
                LogComment("Found {0} experimental extensions:", hiddenExtensions.Count);
                foreach (KeyValuePair <string, bool> hiddenExtension in hiddenExtensions)
                {
                    LogComment("- {0}: {1}", hiddenExtension.Key, hiddenExtension.Value ? "experimental" : "experimental (partial, unsupported)");
                }
            }

            if (hiddenVersions.Count > 0)
            {
                LogComment("Found {0} experimental version commands:", hiddenVersions.Count);
                foreach (KeyValuePair <string, List <Type> > hiddenVersion in hiddenVersions)
                {
                    LogComment("- {0}", hiddenVersion.Key);
                    foreach (Type delegateType in hiddenVersion.Value)
                    {
                        LogComment("    > {0}", delegateType.Name);
                    }
                }
            }

            if (enableExtensions)
            {
                bool sync = false;

                foreach (KeyValuePair <string, bool> hiddenExtension in hiddenExtensions)
                {
                    if (hiddenExtension.Value == false)
                    {
                        continue;                               // Do not enable partial extension
                    }
                    extensions.EnableExtension(hiddenExtension.Key);
                    sync = true;
                }

                if (sync)
                {
                    extensions.SyncMembers(version);
                }
            }
#endif
        }
Exemple #3
0
        /// <summary>
        /// Check whether commands implemented by the current driver have a corresponding extension declaring the
        /// support of them.
        /// </summary>
        /// <typeparam name="T">
        /// The type of the KhronosApi to inspect for commands.
        /// </typeparam>
        /// <param name="version">
        /// The <see cref="KhronosVersion"/> currently implemented by the current context on this thread.
        /// </param>
        /// <param name="extensions">
        /// The <see cref="ExtensionsCollection"/> that specifies the extensions supported by the driver.
        /// </param>
        protected static void CheckExtensionCommands <T>(KhronosVersion version, ExtensionsCollection extensions, bool enableExtensions) where T : KhronosApi
        {
            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }
            if (extensions == null)
            {
                throw new ArgumentNullException(nameof(extensions));
            }

#if NETSTANDARD1_1 || NETSTANDARD1_4 || NETCORE
            throw new NotImplementedException();
#else
            FunctionContext functionContext = GetFunctionContext(typeof(T));
            Debug.Assert(functionContext != null);

            LogComment($"Checking commands for {version}");

            Dictionary <string, List <Type> > hiddenVersions   = new Dictionary <string, List <Type> >();
            Dictionary <string, bool>         hiddenExtensions = new Dictionary <string, bool>();

            foreach (FieldInfo fi in functionContext.Delegates)
            {
                Delegate fiDelegateType     = (Delegate)fi.GetValue(null);
                bool     commandDefined     = fiDelegateType != null;
                bool     supportedByFeature = false;

#if DEBUG_VERBOSE
                string commandName = fi.Name.Substring(3);
#endif
                // Get the delegate type
                Type delegateType = fi.DeclaringType?.GetNestedType(fi.Name.Substring(1), BindingFlags.Public | BindingFlags.NonPublic);
                if (delegateType == null)
                {
                    continue;                                   // Support fields names not in sync with delegate types
                }
                // TODO Why not use 'fi' directly for getting attributes? They should be in sync
                IEnumerable <object> requiredByFeatureAttributes = delegateType.GetCustomAttributes(typeof(RequiredByFeatureAttribute), false);

                foreach (RequiredByFeatureAttribute requiredByFeatureAttribute in requiredByFeatureAttributes)
                {
                    supportedByFeature |= requiredByFeatureAttribute.IsSupported(version, extensions);
                }

                // Find the underlying extension
                RequiredByFeatureAttribute hiddenVersionAttrib   = null;
                RequiredByFeatureAttribute hiddenExtensionAttrib = null;

                foreach (RequiredByFeatureAttribute requiredByFeatureAttribute in requiredByFeatureAttributes)
                {
                    if (!requiredByFeatureAttribute.IsSupportedApi(version.Api))
                    {
                        // Version attribute
                        if (hiddenVersionAttrib == null)
                        {
                            hiddenVersionAttrib = requiredByFeatureAttribute;
                        }
                    }
                    else
                    {
                        // Extension attribute
                        if (hiddenExtensionAttrib == null)
                        {
                            hiddenExtensionAttrib = requiredByFeatureAttribute;
                        }
                    }
                }

                if (commandDefined != supportedByFeature)
                {
#if DEBUG_VERBOSE
                    string supportString = "any feature";

                    if (hiddenVersionAttrib != null)
                    {
                        supportString = hiddenVersionAttrib.FeatureName;
                        if (hiddenExtensionAttrib != null)
                        {
                            supportString += " or ";
                        }
                    }

                    if (hiddenExtensionAttrib != null)
                    {
                        if (hiddenVersionAttrib == null)
                        {
                            supportString = string.Empty;
                        }
                        supportString += hiddenExtensionAttrib.FeatureName;
                    }
#endif

                    if (commandDefined)
                    {
#if DEBUG_VERBOSE
                        LogComment("The command {0} is defined, but {1} support is not advertised.", commandName, supportString);
#endif
                        if (hiddenVersionAttrib != null && hiddenExtensionAttrib == null)
                        {
                            List <Type> versionDelegates;

                            if (!hiddenVersions.TryGetValue(hiddenVersionAttrib.FeatureName, out versionDelegates))
                            {
                                hiddenVersions.Add(hiddenVersionAttrib.FeatureName, versionDelegates = new List <Type>());
                            }
                            versionDelegates.Add(delegateType);
                        }

                        if (hiddenExtensionAttrib != null)
                        {
                            // Eventually leave to false for incomplete extensions
                            if (!hiddenExtensions.ContainsKey(hiddenExtensionAttrib.FeatureName))
                            {
                                hiddenExtensions.Add(hiddenExtensionAttrib.FeatureName, true);
                            }
                        }
                    }
                    else
                    {
#if DEBUG_VERBOSE
                        LogComment("The command {0} is not defined, but required by some feature.", commandName);
#endif
                    }
                }

                // Partial extensions are not supported
                if (hiddenExtensionAttrib != null && !commandDefined && hiddenExtensions.ContainsKey(hiddenExtensionAttrib.FeatureName))
                {
                    hiddenExtensions[hiddenExtensionAttrib.FeatureName] = false;
                }
            }

            if (hiddenExtensions.Count > 0)
            {
                LogComment($"Found {hiddenExtensions.Count} experimental extensions:");
                foreach (KeyValuePair <string, bool> hiddenExtension in hiddenExtensions)
                {
                    LogComment(string.Format($"- {0}: {1}", hiddenExtension.Key, hiddenExtension.Value ? "experimental" : "experimental (partial, unsupported)"));
                }
            }

            if (hiddenVersions.Count > 0)
            {
                LogComment($"Found {hiddenVersions.Count} experimental version commands:");
                foreach (KeyValuePair <string, List <Type> > hiddenVersion in hiddenVersions)
                {
                    LogComment($"- {hiddenVersion.Key}");
                    foreach (Type delegateType in hiddenVersion.Value)
                    {
                        LogComment($"    > {delegateType.Name}");
                    }
                }
            }

            if (enableExtensions)
            {
                bool sync = false;

                foreach (KeyValuePair <string, bool> hiddenExtension in hiddenExtensions)
                {
                    if (!hiddenExtension.Value)
                    {
                        continue;                               // Do not enable partial extension
                    }
                    extensions.EnableExtension(hiddenExtension.Key);
                    sync = true;
                }

                if (sync)
                {
                    extensions.SyncMembers(version);
                }
            }
#endif
        }