private static void AssignPointerFields(GPGPU gpu, object hostObject, object deviceObject, List <FieldMapping> pointerFields) { foreach (FieldMapping mapping in pointerFields) { object fieldValue = mapping.HostObjectField.GetValue(hostObject); // Get the IntPtr to the device memory for the array. var devicePointer = TryGetDeviceMemoryFromHostObject(gpu, fieldValue); if (devicePointer == null) { throw new ArgumentException("No device memory allocated for field " + mapping.Name); } // The device object contains this pointer. mapping.DeviceObjectField.SetValue(deviceObject, devicePointer.Pointer); // If the field is an array then set the dimension fields too. if (mapping is ArrayFieldMapping) { ArrayFieldMapping arrayFieldMapping = (ArrayFieldMapping)mapping; Array array = fieldValue as Array; for (int i = 0; i < arrayFieldMapping.ArrayRank; ++i) { arrayFieldMapping.DeviceObjectDimensionFields[i].SetValue(deviceObject, array.GetLength(i)); } } } }
/// <summary> /// Create type that contains pointers to device arrays. /// </summary> private static DeviceTypeInfo CreateDeviceType(Type hostType) { DeviceTypeInfo dummy; if (deviceTypeLookup.TryGetValue(hostType, out dummy)) { return(dummy); } // We are assuming that the device class is standard layout. // We further assume that all array fields are actually pointers to device memory. // For now assume that anything that is not an array is blittable. TypeBuilder tb = moduleBuilder.DefineType("DynamicType" + hostType.Name, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.SequentialLayout | TypeAttributes.Serializable, typeof(ValueType)); var fields = GetFieldsStandardLayout(hostType); var pointerFields = new List <FieldMapping>(); var nonPointerFields = new List <FieldMapping>(); // Any class (i.e. not value type), which includes arrays, is replaced by an IntPtr foreach (var field in fields) { if (field.FieldType.IsClass) { tb.DefineField(field.Name, typeof(IntPtr), FieldAttributes.Public); FieldMapping newPointerFieldMapping; // If this is an array, then we add in int fields to contain the dimensions of the array. if (field.FieldType.IsArray) { newPointerFieldMapping = new ArrayFieldMapping() { Name = field.Name, HostObjectField = field }; ((ArrayFieldMapping)newPointerFieldMapping).ArrayRank = field.FieldType.GetArrayRank(); for (int r = 0; r < field.FieldType.GetArrayRank(); r++) { string dimensionFieldName = String.Format("{0}Len{1}", field.Name, r); tb.DefineField(dimensionFieldName, typeof(int), FieldAttributes.Public); ((ArrayFieldMapping)newPointerFieldMapping).ArrayDimensionNames.Add(dimensionFieldName); } } else { newPointerFieldMapping = new FieldMapping() { Name = field.Name, HostObjectField = field }; } pointerFields.Add(newPointerFieldMapping); } else { tb.DefineField(field.Name, field.FieldType, FieldAttributes.Public); nonPointerFields.Add(new FieldMapping() { Name = field.Name, HostObjectField = field }); } } Type newType = tb.CreateType(); foreach (var pointerField in pointerFields) { pointerField.DeviceObjectField = newType.GetFields().Where(f => f.Name == pointerField.Name).FirstOrDefault(); if (pointerField is ArrayFieldMapping) { foreach (string dimensionName in ((ArrayFieldMapping)pointerField).ArrayDimensionNames) { ((ArrayFieldMapping)pointerField).DeviceObjectDimensionFields.Add( newType.GetFields().Where(f => f.Name == dimensionName).FirstOrDefault()); } } } foreach (var nonPointerField in nonPointerFields) { nonPointerField.DeviceObjectField = newType.GetFields().Where(f => f.Name == nonPointerField.Name).FirstOrDefault(); } var deviceTypeInfo = new DeviceTypeInfo() { DeviceType = newType, NonPointerFields = nonPointerFields, PointerFields = pointerFields }; deviceTypeLookup.Add(hostType, deviceTypeInfo); return(deviceTypeInfo); }