Beispiel #1
0
        private void InitVendorFeatures()
        {
            // Check major vendor features
            if (CLAPI.GetDeviceInfo(
                    DeviceId,
                    CLDeviceInfoType.CL_DEVICE_WARP_SIZE_NV,
                    out int warpSize) == CLError.CL_SUCCESS)
            {
                // Nvidia platform
                WarpSize = warpSize;
                Vendor   = CLAcceleratorVendor.Nvidia;

                int major = CLAPI.GetDeviceInfo <int>(
                    DeviceId,
                    CLDeviceInfoType.CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV);
                int minor = CLAPI.GetDeviceInfo <int>(
                    DeviceId,
                    CLDeviceInfoType.CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV);
                if (major < 7 || major == 7 && minor < 5)
                {
                    MaxNumThreadsPerMultiprocessor *= 2;
                }
            }
            else if (CLAPI.GetDeviceInfo(
                         DeviceId,
                         CLDeviceInfoType.CL_DEVICE_WAVEFRONT_WIDTH_AMD,
                         out int wavefrontSize) == CLError.CL_SUCCESS)
            {
                // AMD platform
                WarpSize = wavefrontSize;
                Vendor   = CLAcceleratorVendor.AMD;
            }
            else
            {
                Vendor = VendorName.Contains(CLAcceleratorVendor.Intel.ToString()) ?
                         CLAcceleratorVendor.Intel :
                         CLAcceleratorVendor.Other;

                // Compile dummy kernel to resolve additional information
                CLException.ThrowIfFailed(CLKernel.LoadKernel(
                                              this,
                                              DummyKernelSource,
                                              out IntPtr programPtr,
                                              out IntPtr kernelPtr));
                try
                {
                    // Resolve information
                    WarpSize = CLAPI.GetKernelWorkGroupInfo <IntPtr>(
                        kernelPtr,
                        DeviceId,
                        CLKernelWorkGroupInfoType.CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE).ToInt32();
                }
                finally
                {
                    CLException.ThrowIfFailed(
                        CLAPI.ReleaseKernel(kernelPtr) |
                        CLAPI.ReleaseProgram(programPtr));
                }
            }
        }
Beispiel #2
0
        /// <summary cref="DisposeBase.Dispose(bool)"/>
        protected override void Dispose(bool disposing)
        {
            CLException.ThrowIfFailed(
                CLAPI.ReleaseKernel(kernelPtr) |
                CLAPI.ReleaseProgram(programPtr));

            programPtr = IntPtr.Zero;
            kernelPtr  = IntPtr.Zero;
        }
Beispiel #3
0
        private void InitSubGroupSupport(CLAcceleratorId acceleratorId)
        {
            // Check sub group support
            if (!(SubGroupSupport = acceleratorId.HasAnyExtension(SubGroupExtensions)))
            {
                return;
            }

            // Verify support using a simple kernel
            if (CLKernel.LoadKernel(
                    this,
                    DummySubGroupKernelSource,
                    CVersion,
                    out IntPtr programPtr,
                    out IntPtr kernelPtr,
                    out var _) == CLError.CL_SUCCESS)
            {
                // Some drivers return an internal handler delegate
                // that crashes during invocation instead of telling that the
                // sub-group feature is not supported
                try
                {
                    var localGroupSizes = new IntPtr[]
                    {
                        new IntPtr(MaxNumThreadsPerGroup)
                    };
                    SubGroupSupport = acceleratorId.TryGetKernelSubGroupInfo(
                        kernelPtr,
                        DeviceId,
                        CLKernelSubGroupInfoType
                        .CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE_KHR,
                        localGroupSizes,
                        out IntPtr subGroupSize);
                    WarpSize = subGroupSize.ToInt32();
                }
                catch (AccessViolationException)
                {
                    // This exception can be raised due to driver issues
                    // on several platforms -> we will just disable sub-group
                    // support for these platforms
                    SubGroupSupport = false;
                }
                finally
                {
                    CLException.ThrowIfFailed(
                        CLAPI.ReleaseKernel(kernelPtr));
                    CLException.ThrowIfFailed(
                        CLAPI.ReleaseProgram(programPtr));
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Loads the given OpenCL kernel.
        /// </summary>
        /// <param name="accelerator">The associated accelerator.</param>
        /// <param name="source">The OpenCL source code.</param>
        /// <param name="version">The OpenCL C version.</param>
        /// <param name="programPtr">The created program pointer.</param>
        /// <param name="kernelPtr">The created kernel pointer.</param>
        /// <param name="errorLog">The error log (if any).</param>
        /// <returns>True, if the program and the kernel could be loaded successfully.</returns>
        internal static CLError LoadKernel(
            CLAccelerator accelerator,
            string source,
            CLCVersion version,
            out IntPtr programPtr,
            out IntPtr kernelPtr,
            out string errorLog)
        {
            errorLog  = null;
            kernelPtr = IntPtr.Zero;
            var programError = CLAPI.CreateProgram(
                accelerator.ContextPtr,
                source,
                out programPtr);

            if (programError != CLError.CL_SUCCESS)
            {
                return(programError);
            }

            // Specify the OpenCL C version.
            string options = "-cl-std=" + version.ToString();

            var buildError = CLAPI.BuildProgram(
                programPtr,
                accelerator.DeviceId,
                options);

            if (buildError != CLError.CL_SUCCESS)
            {
                CLException.ThrowIfFailed(
                    CLAPI.GetProgramBuildLog(
                        programPtr,
                        accelerator.DeviceId,
                        out errorLog));
                CLException.ThrowIfFailed(
                    CLAPI.ReleaseProgram(programPtr));
                programPtr = IntPtr.Zero;
                return(buildError);
            }

            return(CLAPI.CreateKernel(
                       programPtr,
                       CLCompiledKernel.EntryName,
                       out kernelPtr));
        }
Beispiel #5
0
        /// <summary>
        /// Loads the given OpenCL kernel.
        /// </summary>
        /// <param name="accelerator">The associated accelerator.</param>
        /// <param name="source">The OpenCL source code.</param>
        /// <param name="programPtr">The created program pointer.</param>
        /// <param name="kernelPtr">The created kernel pointer.</param>
        /// <returns>True, if the program and the kernel could be loaded successfully.</returns>
        internal static CLError LoadKernel(
            CLAccelerator accelerator,
            string source,
            out IntPtr programPtr,
            out IntPtr kernelPtr)
        {
            kernelPtr = IntPtr.Zero;
            var error = CLAPI.CreateProgram(
                accelerator.ContextPtr,
                source,
                out programPtr);

            if (error != CLError.CL_SUCCESS)
            {
                return(error);
            }

            // TODO: OpenCL compiler options
            string options = string.Empty;

            error |= CLAPI.BuildProgram(
                programPtr,
                accelerator.DeviceId,
                options);

            error |= CLAPI.CreateKernel(
                programPtr,
                CLCompiledKernel.EntryName,
                out kernelPtr);

            if (error != CLError.CL_SUCCESS)
            {
                CLException.ThrowIfFailed(
                    CLAPI.ReleaseProgram(programPtr));
                programPtr = IntPtr.Zero;
            }
            return(error);
        }