/// <summary> /// Creates a program from the provided source codes. The program is created, compiled, and linked. /// </summary> /// <param name="sources">The source codes from which the program is to be created.</param> /// <exception cref="OpenClException"> /// If the program could not be created, compiled, or linked, then an /// <see cref="OpenClException" /> is thrown. /// </exception> /// <returns>Returns the created program.</returns> public Program CreateAndBuildProgramFromString(IEnumerable <string> sources) { // Loads the program from the specified source string IntPtr[] sourceList = sources.Select(source => Marshal.StringToHGlobalAnsi(source)).ToArray(); uint[] sourceLengths = sources.Select(source => (uint)source.Length).ToArray(); IntPtr programPointer = ProgramsNativeApi.CreateProgramWithSource(Handle, 1, sourceList, sourceLengths, out Result result); // Checks if the program creation was successful, if not, then an exception is thrown if (result != Result.Success) { throw new OpenClException("The program could not be created.", result); } // Builds (compiles and links) the program and checks if it was successful, if not, then an exception is thrown result = ProgramsNativeApi.BuildProgram(programPointer, 0, null, null, IntPtr.Zero, IntPtr.Zero); if (result != Result.Success) { // Cycles over all devices and retrieves the build log for each one, so that the errors that occurred can be added to the exception message (if any error occur during the retrieval, the exception is thrown without the log) Dictionary <string, string> buildLogs = new Dictionary <string, string>(); foreach (Device device in Devices) { try { string buildLog = GetProgramBuildInformation <string>(programPointer, device, ProgramBuildInformation.Log) .Trim(); if (!string.IsNullOrWhiteSpace(buildLog)) { buildLogs.Add(device.Name, buildLog); } } catch (OpenClException) { } } // Compiles the build logs into a formatted string and integrates it into the exception message string buildLogString = string.Join( $"{Environment.NewLine}{Environment.NewLine}", buildLogs.Select( keyValuePair => $" Build log for device \"{keyValuePair.Key}\":{Environment.NewLine}{keyValuePair.Value}" ) ); throw new OpenClException( $"The program could not be compiled and linked.{Environment.NewLine}{Environment.NewLine}{buildLogString}", result ); } // Creates the new program and returns it return(new Program(programPointer)); }
public unsafe Program CreateAndBuildProgramFromBinary(byte[] source, Device dev) { fixed(byte *srcptr = source) { IntPtr sourcePtr = new IntPtr(srcptr); // Loads the program from the specified source string Result result; IntPtr[] deviceList = new IntPtr[] { dev.Handle }; UIntPtr[] binSizes = new UIntPtr[] { new UIntPtr((uint)source.Length) }; IntPtr[] sourceList = new IntPtr[] { sourcePtr }; IntPtr programPointer = ProgramsNativeApi.CreateProgramWithBinary(this.Handle, 1, deviceList, binSizes, sourceList, out Result binStatus, out result); // Checks if the program creation was successful, if not, then an exception is thrown if (result != Result.Success) { throw new OpenClException("The program could not be created.", result); } // Builds (compiles and links) the program and checks if it was successful, if not, then an exception is thrown result = ProgramsNativeApi.BuildProgram(programPointer, 0, null, "-cl-std=CL2.0", IntPtr.Zero, IntPtr.Zero); if (result != Result.Success) { // Cycles over all devices and retrieves the build log for each one, so that the errors that occurred can be added to the exception message (if any error occur during the retrieval, the exception is thrown without the log) Dictionary <string, string> buildLogs = new Dictionary <string, string>(); foreach (Device device in this.Devices) { try { string buildLog = this.GetProgramBuildInformation <string>(programPointer, device, ProgramBuildInformation.Log).Trim(); if (!string.IsNullOrWhiteSpace(buildLog)) { buildLogs.Add(device.Name, buildLog); } } catch (OpenClException) { continue; } } // Compiles the build logs into a formatted string and integrates it into the exception message string buildLogString = string.Join($"{Environment.NewLine}{Environment.NewLine}", buildLogs.Select(keyValuePair => $" Build log for device \"{keyValuePair.Key}\":{Environment.NewLine}{keyValuePair.Value}")); throw new OpenClException($"The program could not be compiled and linked.{Environment.NewLine}{Environment.NewLine}{buildLogString}", result); } // Creates the new program and returns it return(new Program(programPointer)); } }
private void InitCL(String[] kernelSource, String[] kernelNames, string compileArguments) { lock (lockObj) { if (!hasClInitialized && clDevice != null) { Result err; var devicesArray = new IntPtr[] { clDevice }; clContext = ContextsNativeApi.CreateContext(IntPtr.Zero, 1, devicesArray, IntPtr.Zero, IntPtr.Zero, out err); if (err != Result.Success) { throw new OpenClException("Failed to create context!", err); } commandQueue = CommandQueuesNativeApi.CreateCommandQueue(clContext, clDevice, CommandQueueProperty.None, out err); if (err != Result.Success) { throw new OpenClException("Failed to create command queue!", err); } IntPtr[] sourceList = kernelSource.Select(source => Marshal.StringToHGlobalAnsi(source)).ToArray(); clProgram = ProgramsNativeApi.CreateProgramWithSource(clContext, 1, sourceList, null, out err); if (err != Result.Success) { throw new OpenClException("Failed to create program!", err); } err = ProgramsNativeApi.BuildProgram(clProgram, 1, new IntPtr[] { clDevice }, compileArguments, IntPtr.Zero, IntPtr.Zero); if (err != Result.Success) { var infoBuffer = GetProgramBuildInformation <string>(clProgram, clDevice, ProgramBuildInformation.Log); if (err != Result.Success) { throw new OpenClException("Failed to build program! " + (infoBuffer == null ? "?" : infoBuffer.ToString()), err); } } foreach (var item in kernelNames) { kernels[item] = KernelsNativeApi.CreateKernel(clProgram, item, out err); if (err != Result.Success) { throw new OpenClException("Failed to create kernel: " + item, err); } } hasClInitialized = true; } } }
/// <summary> /// Creates a program from the provided source codes asynchronously. The program is created, compiled, and linked. /// </summary> /// <param name="sources">The source codes from which the program is to be created.</param> /// <exception cref="OpenClException">If the program could not be created, compiled, or linked, then an <see cref="OpenClException"/> is thrown.</exception> /// <returns>Returns the created program.</returns> public Task <Program> CreateAndBuildProgramFromStringAsync(IEnumerable <string> sources) { // Creates a new task completion source, which is used to signal when the build has completed TaskCompletionSource <Program> taskCompletionSource = new TaskCompletionSource <Program>(); // Loads the program from the specified source string IntPtr[] sourceList = sources.Select(source => Marshal.StringToHGlobalAnsi(source)).ToArray(); uint[] sourceLengths = sources.Select(source => (uint)source.Length).ToArray(); IntPtr programPointer = ProgramsNativeApi.CreateProgramWithSource(Handle, 1, sourceList, sourceLengths, out Result result); // Checks if the program creation was successful, if not, then an exception is thrown if (result != Result.Success) { throw new OpenClException("The program could not be created.", result); } // Builds (compiles and links) the program and checks if it was successful, if not, then an exception is thrown Result result1 = result; result = ProgramsNativeApi.BuildProgram(programPointer, 0, null, null, Marshal.GetFunctionPointerForDelegate(new BuildProgramCallback((builtProgramPointer, userData) => { // Tries to validate the build, if not successful, then an exception is thrown try { // Cycles over all devices and retrieves the build log for each one, so that the errors that occurred can be added to the exception message (if any error occur during the retrieval, the exception is thrown without the log) Dictionary <string, string> buildLogs = new Dictionary <string, string>(); foreach (Device device in Devices) { try { string buildLog = GetProgramBuildInformation <string>(builtProgramPointer, device, ProgramBuildInformation.Log).Trim(); if (!string.IsNullOrWhiteSpace(buildLog)) { buildLogs.Add(device.Name, buildLog); } } catch (OpenClException) { } } // Checks if there were any errors, if so then the build logs are compiled into a formatted string and integrates it into the exception message if (buildLogs.Any()) { string buildLogString = string.Join($"{Environment.NewLine}{Environment.NewLine}", buildLogs.Select(keyValuePair => $" Build log for device \"{keyValuePair.Key}\":{Environment.NewLine}{keyValuePair.Value}")); taskCompletionSource.TrySetException(new OpenClException( $"The program could not be compiled and linked.{Environment.NewLine}{Environment.NewLine}{buildLogString}", result1)); } // Since the build was successful, the program is created and the task completion source is resolved with it Creates the new program and returns it taskCompletionSource.TrySetResult(new Program(builtProgramPointer)); } catch (Exception exception) { taskCompletionSource.TrySetException(exception); } })), IntPtr.Zero); // Checks if the build could be started successfully, if not, then an exception is thrown if (result != Result.Success) { if (result != Result.Success) { taskCompletionSource.TrySetException( new OpenClException("The program could not be compiled and linked.", result)); } } // Returns the task which is resolved when the program was build successful or not return(taskCompletionSource.Task); }