/// <summary> /// Retrieves the specified information about the program build. /// </summary> /// <typeparam name="T">The type of the data that is to be returned.</param> /// <param name="program">The handle to the program for which the build information is to be retrieved.</param> /// <param name="device">The device for which the build information is to be retrieved.</param> /// <param name="programBuildInformation">The kind of information that is to be retrieved.</param> /// <exception cref="OpenClException">If the information could not be retrieved, then an <see cref="OpenClException"/> is thrown.</exception> /// <returns>Returns the specified information.</returns> private T GetProgramBuildInformation <T>(IntPtr program, Device device, ProgramBuildInformation programBuildInformation) { // Retrieves the size of the return value in bytes, this is used to later get the full information Result result = ProgramsNativeApi.GetProgramBuildInformation(program, device.Handle, programBuildInformation, UIntPtr.Zero, null, out UIntPtr returnValueSize); if (result != Result.Success) { throw new OpenClException("The program build information could not be retrieved.", result); } // Allocates enough memory for the return value and retrieves it byte[] output = new byte[returnValueSize.ToUInt32()]; result = ProgramsNativeApi.GetProgramBuildInformation(program, device.Handle, programBuildInformation, new UIntPtr((uint)output.Length), output, out returnValueSize); if (result != Result.Success) { throw new OpenClException("The program build information could not be retrieved.", result); } // Returns the output return(InteropConverter.To <T>(output)); }
/// <summary> /// Disposes of the resources that have been acquired by the program. /// </summary> /// <param name="disposing">Determines whether managed object or managed and unmanaged resources should be disposed of.</param> public override void Dispose() { // Checks if the program has already been disposed of, if not, then the program is disposed of if (!IsDisposed) { ProgramsNativeApi.ReleaseProgram(Handle); } // Makes sure that the base class can execute its dispose logic base.Dispose(); }
/// <summary> /// Disposes of the resources that have been acquired by the program. /// </summary> /// <param name="disposing">Determines whether managed object or managed and unmanaged resources should be disposed of.</param> protected override void Dispose(bool disposing) { // Checks if the program has already been disposed of, if not, then the program is disposed of if (!this.IsDisposed) { ProgramsNativeApi.ReleaseProgram(this.Handle); } // Makes sure that the base class can execute its dispose logic base.Dispose(disposing); }
/// <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; } } }
public void CleanupCLResources() { if (hasClInitialized) { FlushWorkingCache(); foreach (var item in kernels) { KernelsNativeApi.ReleaseKernel(item.Value); } kernels.Clear(); ProgramsNativeApi.ReleaseProgram(clProgram); CommandQueuesNativeApi.ReleaseCommandQueue(commandQueue); ContextsNativeApi.ReleaseContext(clContext); hasClInitialized = false; } }
/// <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); }