Exemplo n.º 1
0
        private static ResourceRecord GetResource(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            ResourceRecord result;

            if (_impls.TryGetValue(type, out result))
            {
                return(result);
            }

            var assemblyName = new AssemblyName {
                Name = "tmp_" + type.Name
            };
            var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
            var module          = assemblyBuilder.DefineDynamicModule("tmpModule");
            var typeBuilder     = module.DefineType(type.Name + "SharedSingletonWrapper", TypeAttributes.Public | TypeAttributes.Class, type);

            var baseDispose = type.GetMethod("Dispose", BindingFlags.Public | BindingFlags.Instance);

            if (baseDispose.IsFinal)
            {
                throw new Exception(type.Name + ".Dispose() is final");
            }

            var disposeFun     = typeBuilder.DefineMethod("Dispose", MethodAttributes.Virtual | MethodAttributes.Public, typeof(void), Type.EmptyTypes);
            var disposeBaseFun = typeBuilder.DefineMethod("DisposeBase", MethodAttributes.Public, typeof(void), Type.EmptyTypes);

            typeBuilder.DefineField("key", typeof(AllocationKey), FieldAttributes.Public);

            var ilDispose = disposeFun.GetILGenerator();

            var release = ReflectionMarkerAttribute.FindMethod(
                typeof(ResourceManager), ReflectionToken.ResourceHelperRelease);

            ilDispose.Emit(OpCodes.Ldarg, 0);
            ilDispose.Emit(OpCodes.Call, release);
            ilDispose.Emit(OpCodes.Ret);

            var ilDisposeBase = disposeBaseFun.GetILGenerator();

            ilDisposeBase.Emit(OpCodes.Ldarg, 0);
            ilDisposeBase.Emit(OpCodes.Call, type.GetMethod("Dispose", BindingFlags.Public | BindingFlags.Instance));
            ilDisposeBase.Emit(OpCodes.Ret);

            foreach (var tctor in type.GetConstructors(BindingFlagsAny))
            {
                if (tctor.IsPrivate)
                {
                    continue;
                }

                // create a default ctor for T'
                var tparams = tctor.GetParameters();
                var nparams = new Type[tparams.Length];
                for (var i = 0; i < tparams.Length; i++)
                {
                    nparams[i] = tparams[i].ParameterType;
                }

                var ttctor = typeBuilder.DefineConstructor(MethodAttributes.Public, tctor.CallingConvention, nparams);
                var cil    = ttctor.GetILGenerator();
                for (var i = 0; i < tparams.Length + 1; i++)
                {
                    cil.Emit(OpCodes.Ldarg, i);
                }

                cil.Emit(OpCodes.Call, tctor);
                cil.Emit(OpCodes.Ret);
            }

            result = new ResourceRecord
            {
                Implementation = typeBuilder.CreateType()
            };
            _impls[type] = result;

            return(result);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Reflection utility that implements a shader around any user defined shader.
        /// Creating code for any uniform defined.
        /// </summary>
        /// <param name="type">The shader type to derive from</param>
        /// <returns>A constructor to the derived type</returns>
        private static ConstructorInfo GetConstructor(Type type)
        {
            var baseBegin = ReflectionMarkerAttribute.FindMethod(
                typeof(Shader), ReflectionToken.ShaderBegin);

            if (type.IsNotPublic)
            {
                throw new Exception("Type " + type.Name + " must be public");
            }

            ConstructorInfo ctor;

            if (_ctors.TryGetValue(type, out ctor))
            {
                try
                {
                    return(ctor);
                }
                catch (Exception e)
                {
                    throw e.InnerException;
                }
            }

            var assemblyName = new AssemblyName {
                Name = "tmp_" + type.Name
            };
            var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
            var module          = assemblyBuilder.DefineDynamicModule("tmpModule");
            var typeBuilder     = module.DefineType(type.Name + "_impl", TypeAttributes.Public | TypeAttributes.Class, type);

            var beginFun = typeBuilder.DefineMethod(baseBegin.Name, MethodAttributes.Virtual | MethodAttributes.Public, typeof(void), Type.EmptyTypes);
            var ilBeg    = beginFun.GetILGenerator();

            var getName = ReflectionMarkerAttribute.FindProperty(
                typeof(Shader), ReflectionToken.ShaderName).GetGetMethod();

            var nameIndex = ilBeg.DeclareLocal(typeof(IProgram)).LocalIndex;

            var shaderActivate = ReflectionMarkerAttribute.FindMethod(
                typeof(Shader), ReflectionToken.ShaderActivate);

            ilBeg.Emit(OpCodes.Ldarg, 0);
            ilBeg.Emit(OpCodes.Call, shaderActivate);
            ilBeg.Emit(OpCodes.Ldarg, 0);
            ilBeg.Emit(OpCodes.Call, getName);
            ilBeg.Emit(OpCodes.Stloc, nameIndex);

            foreach (var prop in type.GetProperties(BindingFlagsAny))
            {
                var attr = prop.GetCustomAttributes(typeof(UniformAttribute), false);
                if (attr.Length == 0)
                {
                    continue;
                }

                var info = TypeMap[prop.PropertyType.MetadataToken];

                var uniformCall = Binding.Resolve(info.Token);


                var f = typeBuilder.DefineField("m_" + prop.Name, typeof(int), FieldAttributes.Private);
                //var visibility = prop.PropertyType.IsPublic ? MethodAttributes.Public : MethodAttributes.Family;
                const MethodAttributes visibility = MethodAttributes.Public;

                var getter = prop.GetSetMethod() != null?prop.GetGetMethod().Name : "get_" + prop.Name;

                var setter = prop.GetSetMethod() != null?prop.GetSetMethod().Name : "set_" + prop.Name;

                var m   = typeBuilder.DefineMethod(setter, MethodAttributes.Virtual | visibility, typeof(void), new[] { prop.PropertyType });
                var ilg = m.GetILGenerator();

                ilg.Emit(OpCodes.Ldarg, 0);
                ilg.Emit(OpCodes.Ldfld, f);

                if (uniformCall.GetParameters().Length == 2)
                {
                    ilg.Emit(OpCodes.Ldarg, 1);
                }

                ilg.Emit(OpCodes.Call, uniformCall);
                ilg.Emit(OpCodes.Ret);

                m   = typeBuilder.DefineMethod(getter, MethodAttributes.Virtual | visibility, prop.PropertyType, Type.EmptyTypes);
                ilg = m.GetILGenerator();

                ilg.Emit(OpCodes.Newobj, typeof(NotImplementedException));
                ilg.Emit(OpCodes.Throw);
            }

            ilBeg.Emit(OpCodes.Ldarg, 0);
            ilBeg.Emit(OpCodes.Call, type.GetMethod(baseBegin.Name, Type.EmptyTypes));
            ilBeg.Emit(OpCodes.Ret);

            // implement in accessors
            foreach (var prop in type.GetProperties(BindingFlagsAny))
            {
                var attr = prop.GetCustomAttributes(typeof(VertexInAttribute), false);
                if (attr.Length == 0)
                {
                    continue;
                }

                var getter = prop.GetSetMethod() != null?prop.GetGetMethod().Name : "get_" + prop.Name;

                var setter = prop.GetSetMethod() != null?prop.GetSetMethod().Name : "set_" + prop.Name;

                //var visibility = prop.PropertyType.IsPublic ? MethodAttributes.Public : MethodAttributes.Family;
                const MethodAttributes visibility = MethodAttributes.Public;

                var m   = typeBuilder.DefineMethod(setter, MethodAttributes.Virtual | visibility, typeof(void), new[] { prop.PropertyType });
                var ilg = m.GetILGenerator();
                ilg.Emit(OpCodes.Newobj, typeof(NotImplementedException));
                ilg.Emit(OpCodes.Throw);

                m   = typeBuilder.DefineMethod(getter, MethodAttributes.Virtual | visibility, prop.PropertyType, Type.EmptyTypes);
                ilg = m.GetILGenerator();
                ilg.Emit(OpCodes.Newobj, typeof(NotImplementedException));
                ilg.Emit(OpCodes.Throw);
            }

            var timpl = typeBuilder.CreateType();

            ctor         = timpl.GetConstructor(Type.EmptyTypes);
            _ctors[type] = ctor;

            return(ctor);
        }