CS0453 - Generisch Parameter setzen - T : Struct - T Unbekannt

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 27 Antworten in diesem Thema. Der letzte Beitrag () ist von Facebamm.

    CS0453 - Generisch Parameter setzen - T : Struct - T Unbekannt

    Hallo zusammen,
    ich hab folgendes Problem.

    Ich hab eine Methode mit dem Parameter params object[] parameter und muss nun die parameter Objekte in eine generische Methode bringen mit where T : struct ,
    dabei ist zu unterscheiden ob das Object ein struct-Array oder nur ein struct ist.
    also so zu sagen ist parameter ein tuple mit unbekannten typen.

    a(T item) where T : struct
    a(IList<T> items) where T : struct
    a(T[] items) where T : struct

    dazu kommt das Object, Class ist und nicht Struct
    e.g.:

    C#-Quellcode

    1. params object[] parameter = new []{ 1, 0.5f, new string[] {"Hello", "World"}, new Unknow(10, 20)};


    Hat jm. für mich einen anderen Ansatz bzw. eine idee wie ich object zu "Unknow" T gekomme ?

    Ich hoffe ihr versteht mein Problem :/
    String ist kein struct, daher macht das für mich schon mal keinen Sinn.
    Problem ist halt auch, dass das relativ unperformant ist, aber gut. Musst halt dann wieder casten und vmtl. mit Reflection ran.

    Allgemein wäre jetzt aber die Frag, was Du genau machen willst.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Ich hab es noch nicht getestet aber das zeigt so ziemlich genau was ich machen möchte.
    Spoiler anzeigen

    C#-Quellcode

    1. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    2. public byte[] ExecuteWithImage(byte[] source, ImageFormat imageFormat, MemFlags flags, int imageWidthPx, int imageHeightPx, IntPtr[] originPtr, IntPtr[] regionPtr, IntPtr[] workGroupSizePtr, params object[] parameter) {
    3. byte[] buffer = new byte[source.Length];
    4. using(var inputImage2DBuffer = Cl.CreateImage2D(_context, flags, imageFormat, (IntPtr)imageWidthPx, (IntPtr)imageHeightPx, (IntPtr)0, source, out _)) {
    5. using(var outputImage2DBuffer = Cl.CreateImage2D(_context, flags, imageFormat, (IntPtr)imageWidthPx, (IntPtr)imageHeightPx, (IntPtr)0, buffer, out _)) {
    6. Cl.SetKernelArg(_kernel, 0, (IntPtr)IntPtr.Size, inputImage2DBuffer);
    7. Cl.SetKernelArg(_kernel, 1, (IntPtr)IntPtr.Size, outputImage2DBuffer);
    8. int n = parameter.Length;
    9. for(uint i = 2; i < n; i++) {
    10. //SetKernalArg<T>(_kernel, i,parameter[i -2]); //error 453
    11. ExpressionSetKernelArgs(parameter[i -2 ], i);
    12. }
    13. Cl.EnqueueWriteImage(_commandQueue, inputImage2DBuffer, Bool.True, originPtr, regionPtr, IntPtr.Zero, IntPtr.Zero, source, 0, null, out _);
    14. Cl.EnqueueNDRangeKernel(_commandQueue, _kernel, 2, null, workGroupSizePtr, null, 0, null, out _);
    15. Cl.EnqueueReadImage(_commandQueue, outputImage2DBuffer, Bool.True, originPtr, regionPtr, IntPtr.Zero, IntPtr.Zero, buffer, 0, null, out _);
    16. Cl.Finish(_commandQueue);
    17. }
    18. }
    19. return buffer;
    20. }
    21. private void ExpressionSetKernelArgs(object val, uint index) {
    22. Type type = val.GetType();
    23. //paramter
    24. ParameterExpression paramKernel = Expression.Parameter(typeof(Kernel), "kern");
    25. ParameterExpression paramIndex = Expression.Parameter(typeof(uint), "intex");
    26. ParameterExpression paramItem = Expression.Parameter(type, "item");
    27. Expression block = Expression.Block(
    28. new[] {
    29. Expression.Call(null, typeof(OpenClBright)
    30. .GetMethod(
    31. "SetKernalArg",
    32. new Type[] { typeof(Kernel), typeof(uint), paramItem.Type}),
    33. new [] {paramKernel, paramIndex, paramItem}
    34. )
    35. }
    36. );
    37. Expression.Lambda<Action<Kernel, uint, object>>(block).Compile()(_kernel, index, val);
    38. }
    39. private void SetKernalArg<T>(ref Kernel kernel, uint index, T item) where T : struct
    40. => Cl.SetKernelArg<T>(kernel, index, value: item);
    41. private void SetKernerlArg<T>(ref Kernel kernel, uint index, IList<T> items) where T : struct {
    42. T[] genItems = items.ToArray() ?? new T[0];
    43. IMem<T> memBuffer = Cl.CreateBuffer(_context, MemFlags.CopyHostPtr, hostData: genItems, out _);
    44. Cl.SetKernelArg(kernel, index, memBuffer);
    45. }
    46. private void SetKernerlArg<T>(ref Kernel kernel, uint index, T[] items) where T : struct {
    47. T[] genItems = items ?? new T[0];
    48. IMem<T> memBuffer = Cl.CreateBuffer(_context, MemFlags.CopyHostPtr, hostData: genItems, out _);
    49. Cl.SetKernelArg(kernel, index, memBuffer);
    50. }
    @Facebamm Falls das im Konstruktor einer generischen Klasse steht, poste mal die Klasse.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Facebamm Hab ich gesehen.
    Kannst Du mal die Deklarationen der fehlenden Klassen posten bzw. das, was erforderlich ist?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Das sollte alles ein, hoffe ich

    C# teil und du benötigst OpenCl.Net - Nuget
    Spoiler anzeigen

    C#-Quellcode

    1. using OpenCL.Net;
    2. using System;
    3. using System.Collections.Generic;
    4. using System.Drawing;
    5. using SystemGDI = System.Drawing.Imaging;
    6. using System.Linq;
    7. using System.Linq.Expressions;
    8. using System.Reflection;
    9. using System.Runtime.CompilerServices;
    10. using System.Runtime.InteropServices;
    11. namespace ShortCl {
    12. public class GpuCodeDbg {
    13. public readonly static MemFlags MemoryFlag;
    14. public readonly static ImageFormat ImageFormat;
    15. public readonly static IntPtr[] OriginPtr;
    16. private static Device _device;
    17. private static Context _context;
    18. private static CommandQueue _commandQueue;
    19. static GpuCodeDbg() {
    20. Platform[] platforms = Cl.GetPlatformIDs(out ErrorCode error);
    21. if(error != ErrorCode.Success) {
    22. throw new GPUException("Paltform", error.ToString());
    23. }
    24. List<Device> devices = new List<Device>();
    25. if(platforms.Length > 0) {
    26. foreach(Platform platform in platforms) {
    27. foreach(Device device in Cl.GetDeviceIDs(platform, DeviceType.Gpu, out error)) {
    28. if(error != ErrorCode.Success) {
    29. throw new GPUException("Device", error.ToString());
    30. }
    31. devices.Add(device);
    32. }
    33. }
    34. }
    35. if(devices.Count > 0) {
    36. foreach(Device device in devices) {
    37. if(Cl.GetDeviceInfo(device, DeviceInfo.ImageSupport, out error).CastTo<bool>()) {
    38. Context context = Cl.CreateContext(null, 1, new[] { device }, null, IntPtr.Zero, out error);
    39. if(error != ErrorCode.Success) {
    40. throw new GPUException("Init", error.ToString());
    41. }
    42. _device = device;
    43. _context = context;
    44. _commandQueue = Cl.CreateCommandQueue(_context, _device, CommandQueueProperties.ProfilingEnable, out _);
    45. }
    46. }
    47. }
    48. #region Init Basic
    49. MemoryFlag = MemFlags.CopyHostPtr;
    50. ImageFormat = new ImageFormat(ChannelOrder.BGRA, ChannelType.Unsigned_Int8);
    51. OriginPtr = new[] { (IntPtr)0, (IntPtr)0, (IntPtr)0 };
    52. #endregion
    53. }
    54. /// <summary>
    55. /// The executing function must be named by "run"
    56. /// </summary>
    57. /// <param name="sourceGpuCode"></param>
    58. /// <returns></returns>
    59. public static OpenClBright CompileProgramFromSource(string sourceGpuCode) {
    60. #region create program
    61. Program program = Cl.CreateProgramWithSource(_context, 1, new[] { sourceGpuCode }, null, out ErrorCode error);
    62. if(error != ErrorCode.Success) {
    63. throw new GPUException("Compile", Cl.GetProgramBuildInfo(program, _device, ProgramBuildInfo.Log, out error).ToString());
    64. }
    65. if(Cl.BuildProgram(program, 1, new[] { _device }, string.Empty, null, IntPtr.Zero) != ErrorCode.Success) {
    66. throw new GPUException("Compile", Cl.GetProgramBuildInfo(program, _device, ProgramBuildInfo.Log, out error).ToString());
    67. }
    68. if(Cl.GetProgramBuildInfo(program, _device, ProgramBuildInfo.Status, out error).CastTo<BuildStatus>() != BuildStatus.Success) {
    69. throw new GPUException("Compile", Cl.GetProgramBuildInfo(program, _device, ProgramBuildInfo.Log, out error).ToString());
    70. }
    71. #endregion
    72. #region create kernal
    73. Kernel kernel = Cl.CreateKernel(program, "run", out error);
    74. if(error != ErrorCode.Success) {
    75. throw new GPUException("Compile", error.ToString());
    76. }
    77. return new OpenClBright(ref _context, ref _commandQueue, kernel);
    78. #endregion
    79. }
    80. }
    81. [Serializable]
    82. public class GPUException : Exception {
    83. public GPUException(string name, string errorStrg, [CallerFilePath] string path = "", [CallerLineNumber] int lineNumber = 0, [CallerMemberName] string methode = "")
    84. : this($"ERROR:[{path}:{methode}({lineNumber})] {name} ({errorStrg})") {
    85. }
    86. public GPUException([CallerFilePath] string path = "", [CallerLineNumber] int lineNumber = 0, [CallerMemberName] string methode = "")
    87. : this($"ERROR:[{path}:{methode}({lineNumber})]") {
    88. }
    89. public GPUException(string message) : base(message) {
    90. }
    91. }
    92. public struct OpenClBright {
    93. private Kernel _kernel;
    94. private CommandQueue _commandQueue;
    95. private Context _context;
    96. public IntPtr[] OriginPtr { get; }
    97. public OpenClBright(ref Context context, ref CommandQueue commandQueue, Kernel kernel) {
    98. _kernel = kernel;
    99. _context = context;
    100. _commandQueue = commandQueue;
    101. OriginPtr = new[] { (IntPtr)0, (IntPtr)0, (IntPtr)0 };
    102. }
    103. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    104. public byte[] ExecuteWithImage(byte[] source, ImageFormat imageFormat, MemFlags flags, int imageWidthPx, int imageHeightPx, IntPtr[] originPtr, IntPtr[] regionPtr, IntPtr[] workGroupSizePtr, params object[] parameter) {
    105. byte[] buffer = new byte[source.Length];
    106. using(var inputImage2DBuffer = Cl.CreateImage2D(_context, flags, imageFormat, (IntPtr)imageWidthPx, (IntPtr)imageHeightPx, (IntPtr)0, source, out _)) {
    107. using(var outputImage2DBuffer = Cl.CreateImage2D(_context, flags, imageFormat, (IntPtr)imageWidthPx, (IntPtr)imageHeightPx, (IntPtr)0, buffer, out _)) {
    108. Cl.SetKernelArg(_kernel, 0, (IntPtr)IntPtr.Size, inputImage2DBuffer);
    109. Cl.SetKernelArg(_kernel, 1, (IntPtr)IntPtr.Size, outputImage2DBuffer);
    110. int n = parameter.Length;
    111. for(uint i = 2; i < n; i++) {
    112. ExpressionSetKernelArgs(parameter[i - 2], i);
    113. }
    114. Cl.EnqueueWriteImage(_commandQueue, inputImage2DBuffer, Bool.True, originPtr, regionPtr, IntPtr.Zero, IntPtr.Zero, source, 0, null, out _);
    115. Cl.EnqueueNDRangeKernel(_commandQueue, _kernel, 2, null, workGroupSizePtr, null, 0, null, out _);
    116. Cl.EnqueueReadImage(_commandQueue, outputImage2DBuffer, Bool.True, originPtr, regionPtr, IntPtr.Zero, IntPtr.Zero, buffer, 0, null, out _);
    117. Cl.Finish(_commandQueue);
    118. }
    119. }
    120. return buffer;
    121. }
    122. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    123. public byte[] ExecuteWithImage(byte[] source, ImageFormat imageFormat, int imageWidthPx, int imageHeightPx, IntPtr[] originPtr, IntPtr[] regionPtr, IntPtr[] workGroupSizePtr, params object[] parameter)
    124. => ExecuteWithImage(source, imageFormat, GpuCodeDbg.MemoryFlag, imageWidthPx, imageHeightPx, originPtr, regionPtr, workGroupSizePtr, parameter);
    125. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    126. public byte[] ExecuteWithImage(byte[] source, MemFlags flags, int imageWidthPx, int imageHeightPx, IntPtr[] originPtr, IntPtr[] regionPtr, IntPtr[] workGroupSizePtr, params object[] parameter)
    127. => ExecuteWithImage(source, GpuCodeDbg.ImageFormat, flags, imageWidthPx, imageHeightPx, originPtr, regionPtr, workGroupSizePtr, parameter);
    128. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    129. public byte[] ExecuteWithImage(byte[] source, int imageWidthPx, int imageHeightPx, IntPtr[] originPtr, IntPtr[] regionPtr, IntPtr[] workGroupSizePtr, params object[] parameter)
    130. => ExecuteWithImage(source, GpuCodeDbg.ImageFormat, GpuCodeDbg.MemoryFlag, imageWidthPx, imageHeightPx, originPtr, regionPtr, workGroupSizePtr, parameter);
    131. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    132. public byte[] ExecuteWithImage(byte[] source, int imageWidthPx, int imageHeightPx, IntPtr[] regionPtr, IntPtr[] workGroupSizePtr, params object[] parameter)
    133. => ExecuteWithImage(source, GpuCodeDbg.ImageFormat, GpuCodeDbg.MemoryFlag, imageWidthPx, imageHeightPx, GpuCodeDbg.OriginPtr, regionPtr, workGroupSizePtr, parameter);
    134. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    135. public void ExecuteWithImage(ref Bitmap bmp) {
    136. SystemGDI.PixelFormat format = bmp.PixelFormat;
    137. if(format != SystemGDI.PixelFormat.Format32bppArgb) {
    138. throw new GPUException($"ImageFormat {format} is not Supported, only {SystemGDI.PixelFormat.Format32bppArgb} is supported");
    139. }
    140. Rectangle bmpRect = new Rectangle(Point.Empty, bmp.Size);
    141. SystemGDI.BitmapData bmpData = bmp.LockBits(bmpRect, SystemGDI.ImageLockMode.ReadWrite, format);
    142. IntPtr bmpPtr = bmpData.Scan0;
    143. int byteCount = bmpData.Stride * bmp.Height;
    144. byte[] buffer = new byte[byteCount];
    145. Marshal.Copy(bmpPtr, buffer, 0, byteCount);
    146. var tool = new[] { (IntPtr)bmp.Width, (IntPtr)bmp.Height, (IntPtr)1 };
    147. buffer = ExecuteWithImage(buffer, bmp.Width, bmp.Height, tool, tool, );
    148. Marshal.Copy(buffer, 0, bmpPtr, byteCount);
    149. bmp.UnlockBits(bmpData);
    150. }
    151. private void ExpressionSetKernelArgs(object val, uint index) {
    152. Type type = val.GetType();
    153. //paramter
    154. ParameterExpression paramKernel = Expression.Parameter(typeof(Kernel), "kern");
    155. ParameterExpression paramIndex = Expression.Parameter(typeof(uint), "intex");
    156. ParameterExpression paramItem = Expression.Parameter(type, "item");
    157. Type OpenClBrightType = typeof(OpenClBright);
    158. //info always null //TODO FIX
    159. MethodInfo info = OpenClBrightType.GetMethod(
    160. "SetKernalArg",
    161. BindingFlags.Instance | BindingFlags.NonPublic,
    162. null,
    163. new Type[] { typeof(Kernel).MakeByRefType(), typeof(uint), val.GetType()},
    164. null
    165. );
    166. Expression expressionCall = Expression.Call(null, info);
    167. // .GetMethod(
    168. // "SetKernalArg",
    169. // new Type[] { typeof(Kernel), typeof(uint), paramItem.Type }),
    170. // new[] { paramKernel, paramIndex, paramItem }
    171. //);
    172. Expression block = Expression.Block(
    173. new[] {
    174. expressionCall
    175. }
    176. );
    177. Expression.Lambda<Action<Kernel, uint, object>>(block).Compile()(_kernel, index, val);
    178. }
    179. private void SetKernalArg<T>(ref Kernel kernel, uint index, T item) where T : struct
    180. => Cl.SetKernelArg<T>(kernel, index, value: item);
    181. private void SetKernerlArg<T>(ref Kernel kernel, uint index, IList<T> items) where T : struct {
    182. T[] genItems = items.ToArray() ?? new T[0];
    183. IMem<T> memBuffer = Cl.CreateBuffer(_context, MemFlags.CopyHostPtr, hostData: genItems, out _);
    184. Cl.SetKernelArg(kernel, index, memBuffer);
    185. }
    186. private void SetKernerlArg<T>(ref Kernel kernel, uint index, T[] items) where T : struct {
    187. T[] genItems = items ?? new T[0];
    188. IMem<T> memBuffer = Cl.CreateBuffer(_context, MemFlags.CopyHostPtr, hostData: genItems, out _);
    189. Cl.SetKernelArg(kernel, index, memBuffer);
    190. }
    191. }
    192. }



    CL - Code - Als Ressource
    Spoiler anzeigen

    C-Quellcode

    1. __constant sampler_t smp = CLK_NORMALIZED_COORDS_FALSE | //Natural coordinates
    2. CLK_ADDRESS_CLAMP_TO_EDGE | //Clamp to zeros
    3. CLK_FILTER_LINEAR;
    4. __kernel
    5. void run(
    6. __read_only image2d_t src,
    7. __read_write image2d_t dst,
    8. int size
    9. ) {
    10. int x = get_global_id(0);
    11. int y = get_global_id(1);
    12. int2 cord = (int2) (x, y);
    13. float4 locPx = read_imagef(src, smp, cord );
    14. locPx.x = locPx.x * 0.11f; //B
    15. locPx.y = locPx.y * 0.59f; //G
    16. locPx.z = locPx.z * 0.3f; //R
    17. write_imagef(dst, cord, locPx);
    18. }


    using
    Spoiler anzeigen

    C#-Quellcode

    1. Bitmap bmp = new Bitmap("Path to image");
    2. string code = Encoding.Default.GetString(Properties.Resources.grayscale);
    3. OpenClBright bright = GpuCodeDbg.CompileProgramFromSource(code);
    4. bright.ExecuteWithImage(bmp, 50);

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Facebamm“ ()

    @Facebamm Das wird zu groß.
    Probier mal, das ganze flach und elementar zu implementieren,
    die eine Routine und feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Dir gehts um performance, aber dann sowas :D

    Außerdem ist Inlining für Methoden die so groß sind eher hinderlich als hilfreich. Wenn es die performance nicht verschlechtert, dann wird sie zumindest nicht besser...

    Was spricht denn gegen soetwas?:

    Quellcode

    1. PrepareKernel();
    2. //hier deine params ohne langsames object[] boxing oder was auch immer
    3. SetKernelArg(...)
    4. SetKernelArg(...);
    5. RunKernel();

    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @ErfinderDesRades, guter Einwand, wollt ich noch machen, aber musste dann gestern los, deswegen mach ich das jetzt.

    Was ich machen möchte ist eine einfacher Klasse zur Kommunikation zur GPU mit OpenCL.
    Die ganzen Methoden aus der DLL hab ich mir wrappen lassen mit dem Nuget "OpenCL.Net", nur finde ich das Handeln mit OpenCL.Net etwas anstrengend und wollte ein paar dinge vereinfachen.

    GpuCodeDbg soll mir Mein Programm soweit vorbereiten, das ich nur noch die Parameter setzen muss und es ausführen kann. Wie so eine art Action :D
    OpenClBridge (Jetzt rightig geschrieben) soll das Compilierte Programm speichern bis ich die Parameter setze und es Ausführe.

    @RodFromGermany Wie meinst du das genau, "Das wird zu groß." Oo

    RodFromGermany schrieb:

    das ganze flach und elementar zu implementieren,

    Also alles in eine Methode oder wie (vorerst) :/


    @jvbsl Das kommt später mit der Performance, erstmal muss es funktionieren.

    Ich glaub auch nicht das Expression "ultra performance" mit sich bringt :P

    Das ist gar nicht mal so verkehrt dein Ansatz.

    Note: Beim nächsten Post ist Doku dabei :D.

    Facebamm schrieb:

    "Das wird zu groß."
    um das nachzuvollziehen.
    Kannst Du eine kleine Testklasse schreiben, in der solch genau einmal vorkommt?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    es ist zwar nicht die Welt an Doku aber jetzt kann ich etwas leichter mit der GPU "reden".

    Spoiler anzeigen

    C#-Quellcode

    1. using OpenCL.Net;
    2. using System;
    3. using System.Collections.Generic;
    4. using System.Diagnostics.Contracts;
    5. using System.Drawing;
    6. using System.Linq;
    7. using System.Runtime.CompilerServices;
    8. using System.Runtime.InteropServices;
    9. using SystemGDI = System.Drawing.Imaging;
    10. namespace ShortCl {
    11. /// <summary>
    12. /// Holding GPU, Content, Queue and CLCompiler
    13. /// </summary>
    14. public static class ClCompiler {
    15. private static MemFlags _memFlags;
    16. private static ImageFormat _imageFormat;
    17. private static IntPtr[] _originPtr;
    18. public static ref readonly MemFlags MemFlags => ref _memFlags;
    19. public static ref readonly ImageFormat ImageFormat => ref _imageFormat;
    20. public static ref readonly IntPtr[] OriginPtr => ref _originPtr;
    21. private static Device _device;
    22. private static Context _context;
    23. private static CommandQueue _commandQueue;
    24. public static ref readonly Device Device => ref _device;
    25. public static ref readonly Context Context => ref _context;
    26. public static ref readonly CommandQueue CommandQueue => ref _commandQueue;
    27. /// <summary>
    28. /// Laden der GPU und Eigenschaften
    29. /// </summary>
    30. static ClCompiler() {
    31. Platform[] platforms = Cl.GetPlatformIDs(out ErrorCode error);
    32. if(error != ErrorCode.Success) {
    33. throw new GPUException("Paltform", error.ToString());
    34. }
    35. List<Device> devices = new List<Device>();
    36. if(platforms.Length > 0) {
    37. foreach(Platform platform in platforms) {
    38. foreach(Device device in Cl.GetDeviceIDs(platform, DeviceType.Gpu, out error)) {
    39. if(error != ErrorCode.Success) {
    40. throw new GPUException("Device", error.ToString());
    41. }
    42. devices.Add(device);
    43. }
    44. }
    45. }
    46. if(devices.Count > 0) {
    47. foreach(Device device in devices) {
    48. if(Cl.GetDeviceInfo(device, DeviceInfo.ImageSupport, out error).CastTo<bool>()) {
    49. Context context = Cl.CreateContext(null, 1, new[] { device }, null, IntPtr.Zero, out error);
    50. if(error != ErrorCode.Success) {
    51. throw new GPUException("Init", error.ToString());
    52. }
    53. _device = device;
    54. _context = context;
    55. _commandQueue = Cl.CreateCommandQueue(_context, _device, CommandQueueProperties.ProfilingEnable, out _);
    56. }
    57. }
    58. }
    59. #region Init Basic
    60. _memFlags = MemFlags.CopyHostPtr;
    61. _imageFormat = new ImageFormat(ChannelOrder.BGRA, ChannelType.Unsigned_Int8);
    62. _originPtr = new[] { (IntPtr)0, (IntPtr)0, (IntPtr)0 };
    63. #endregion
    64. }
    65. /// <summary>
    66. /// Executing function must be named by "run"
    67. /// </summary>
    68. /// <param name="sourceGpuCode"></param>
    69. /// <returns></returns>
    70. public static OpenClBridge CompileProgramFromSource(string sourceGpuCode) {
    71. #region create program
    72. Program program = Cl.CreateProgramWithSource(Context, 1, new[] { sourceGpuCode }, null, out ErrorCode error);
    73. if(error != ErrorCode.Success) {
    74. throw new GPUException("Compile", Cl.GetProgramBuildInfo(program, Device, ProgramBuildInfo.Log, out error).ToString());
    75. }
    76. if(Cl.BuildProgram(program, 1, new[] { Device }, string.Empty, null, IntPtr.Zero) != ErrorCode.Success) {
    77. throw new GPUException("Compile", Cl.GetProgramBuildInfo(program, Device, ProgramBuildInfo.Log, out error).ToString());
    78. }
    79. if(Cl.GetProgramBuildInfo(program, Device, ProgramBuildInfo.Status, out error).CastTo<BuildStatus>() != BuildStatus.Success) {
    80. throw new GPUException("Compile", Cl.GetProgramBuildInfo(program, Device, ProgramBuildInfo.Log, out error).ToString());
    81. }
    82. #endregion
    83. #region create kernal
    84. Kernel kernel = Cl.CreateKernel(program, "run", out error);
    85. if(error != ErrorCode.Success) {
    86. throw new GPUException("Compile", error.ToString());
    87. }
    88. return new OpenClBridge(kernel);
    89. #endregion
    90. }
    91. /// <summary>
    92. /// Convert GID pixelformat to GPU pixelformat
    93. /// </summary>
    94. /// <param name="format"></param>
    95. /// <returns></returns>
    96. public static ImageFormat ToGPU(this SystemGDI.PixelFormat format) {
    97. switch(format) {
    98. case SystemGDI.PixelFormat.Format32bppArgb:
    99. case SystemGDI.PixelFormat.Format32bppPArgb:
    100. return new ImageFormat(ChannelOrder.ARGB, ChannelType.Unsigned_Int8);
    101. case SystemGDI.PixelFormat.Format32bppRgb:
    102. return new ImageFormat(ChannelOrder.RGBA, ChannelType.Unsigned_Int8);
    103. case SystemGDI.PixelFormat.Format24bppRgb:
    104. return new ImageFormat(ChannelOrder.RGB, ChannelType.Unsigned_Int8);
    105. case SystemGDI.PixelFormat.Format16bppArgb1555:
    106. return new ImageFormat(ChannelOrder.ARGB, ChannelType.Unorm_Short555);
    107. default:
    108. throw new NotSupportedException();
    109. }
    110. }
    111. }
    112. [Serializable]
    113. public class GPUException : Exception {
    114. public GPUException(string name, string errorStrg, [CallerFilePath] string path = "", [CallerLineNumber] int lineNumber = 0, [CallerMemberName] string methode = "")
    115. : this($"ERROR:[{path}:{methode}({lineNumber})] {name} ({errorStrg})") {
    116. }
    117. public GPUException([CallerFilePath] string path = "", [CallerLineNumber] int lineNumber = 0, [CallerMemberName] string methode = "")
    118. : this($"ERROR:[{path}:{methode}({lineNumber})]") {
    119. }
    120. public GPUException(string message) : base(message) {
    121. }
    122. }
    123. /// <summary>
    124. /// Hold bitmap statistics for the GPU
    125. /// </summary>
    126. public class KernelImage {
    127. public int ParameterIndex { get; private set; }
    128. public ImageFormat ImageFormat { get; private set; }
    129. /// <summary>
    130. /// Image width in px
    131. /// </summary>
    132. public int Width { get; private set; }
    133. /// <summary>
    134. /// Image height in px
    135. /// </summary>
    136. public int Height { get; private set; }
    137. /// <summary>
    138. /// raw image format
    139. /// </summary>
    140. public byte[] Source { get; private set; }
    141. public IMem GpuBuffer { get; private set; }
    142. public MemFlags Flags { get; private set; }
    143. public IntPtr[] WorkGroupSizePtr { get; private set; }
    144. public IntPtr[] RegionPtr { get; private set; }
    145. private KernelImage(int index, MemFlags flags, SystemGDI.PixelFormat format, int width, int height) {
    146. ParameterIndex = index;
    147. Flags = flags;
    148. ImageFormat = format.ToGPU();
    149. Width = width;
    150. Height = height;
    151. RegionPtr = new[] { (IntPtr)Width, (IntPtr)Height, (IntPtr)0 };
    152. WorkGroupSizePtr = new[] { (IntPtr)Width, (IntPtr)Height, (IntPtr)1 };
    153. }
    154. public KernelImage(int index, MemFlags flags, Bitmap bmp) : this(index, flags, bmp.PixelFormat, bmp.Width, bmp.Height) {
    155. Rectangle bmpRect = new Rectangle(Point.Empty, bmp.Size);
    156. SystemGDI.BitmapData bmpData = bmp.LockBits(bmpRect, SystemGDI.ImageLockMode.ReadWrite, bmp.PixelFormat);
    157. IntPtr bmpPtr = bmpData.Scan0;
    158. int byteCount = bmpData.Stride * Height;
    159. Source = new byte[byteCount];
    160. Marshal.Copy(bmpPtr, Source, 0, byteCount);
    161. bmp.UnlockBits(bmpData);
    162. GpuBuffer = Cl.CreateImage2D(ClCompiler.Context, Flags, ImageFormat, (IntPtr)Width, (IntPtr)Height, (IntPtr)0, Source, out _);
    163. }
    164. public KernelImage(int index, MemFlags flags, byte[] bytes, SystemGDI.PixelFormat pixelFormat, int width, int height)
    165. : this(index, flags, pixelFormat, width, height) {
    166. Source = bytes;
    167. GpuBuffer = Cl.CreateImage2D(ClCompiler.Context, Flags, ImageFormat, (IntPtr)Width, (IntPtr)Height, (IntPtr)0, Source, out _);
    168. }
    169. public KernelImage(int index, byte[] bytes, int width, int height, SystemGDI.PixelFormat pixelFormat)
    170. : this(index, MemFlags.ReadWrite, bytes, pixelFormat, width, height) {
    171. }
    172. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    173. public void SetSource(byte[] source) {
    174. if(source.Length != Source.Length) {
    175. throw new ArithmeticException();
    176. }
    177. Source = source;
    178. GpuBuffer = Cl.CreateImage2D(ClCompiler.Context, Flags, ImageFormat, (IntPtr)Width, (IntPtr)Height, (IntPtr)0, Source, out _);
    179. }
    180. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    181. public void SetSource(Bitmap bmp) {
    182. Rectangle bmpRect = new Rectangle(Point.Empty, bmp.Size);
    183. SystemGDI.BitmapData bmpData = bmp.LockBits(bmpRect, SystemGDI.ImageLockMode.ReadWrite, bmp.PixelFormat);
    184. IntPtr bmpPtr = bmpData.Scan0;
    185. SetSource(bmpPtr);
    186. bmp.UnlockBits(bmpData);
    187. }
    188. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    189. public void SetSource(IntPtr sourcePtr) {
    190. Marshal.Copy(sourcePtr, Source, 0, Source.Length);
    191. GpuBuffer = Cl.CreateImage2D(ClCompiler.Context, Flags, ImageFormat, (IntPtr)Width, (IntPtr)Height, (IntPtr)0, Source, out _);
    192. }
    193. }
    194. /// <summary>
    195. /// Hold the GPU program ready to run
    196. /// </summary>
    197. public struct OpenClBridge {
    198. public Kernel Kernel { get; private set; }
    199. public OpenClBridge(Kernel kernel) => Kernel = kernel;
    200. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    201. public void SetKernelArg<T>(int index, T item) where T : struct
    202. => Cl.SetKernelArg(Kernel, (uint)index, item);
    203. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    204. public void SetKernelArg<T>(int index, IList<T> items) where T : struct
    205. => SetKernelArg(index, items.ToArray(), MemFlags.CopyHostPtr);
    206. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    207. public void SetKernelArg<T>(int index, T[] items) where T : struct
    208. => SetKernelArg(index, items, MemFlags.CopyHostPtr);
    209. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    210. public void SetKernelArg<T>(int index, IList<T> items, MemFlags flags) where T : struct
    211. => SetKernelArg(index, items.ToArray(), flags);
    212. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    213. public void SetKernelArg<T>(int index, T[] items, MemFlags flags) where T : struct {
    214. IMem<T> memBuffer = Cl.CreateBuffer(ClCompiler.Context, flags, items, out _);
    215. Cl.SetKernelArg(Kernel, (uint)index, memBuffer);
    216. }
    217. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    218. public void SetKernerArgImg2D(KernelImage image, IntPtr[] originPtr) {
    219. Contract.Requires(originPtr.Length == 3, "stackoverflow in originPtr");
    220. Cl.SetKernelArg(Kernel, (uint)image.ParameterIndex, (IntPtr)IntPtr.Size, image.GpuBuffer);
    221. Cl.EnqueueWriteImage(ClCompiler.CommandQueue, image.GpuBuffer, Bool.True, originPtr, image.RegionPtr, IntPtr.Zero, IntPtr.Zero, image.Source, 0, null, out _);
    222. }
    223. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    224. private void Execute()
    225. => Execute(new IntPtr[0]);
    226. /// <summary>
    227. /// Runing the GPU program
    228. /// </summary>
    229. /// <param name="workGroupSizePtr">image dimention in 3D (z = 1)</param>
    230. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    231. public void Execute(IntPtr[] workGroupSizePtr) {
    232. Cl.EnqueueNDRangeKernel(ClCompiler.CommandQueue, Kernel, 2, null, workGroupSizePtr, null, 0, null, out _);
    233. Cl.Finish(ClCompiler.CommandQueue);
    234. }
    235. /// <summary>
    236. /// Write back an existing parameter image
    237. /// </summary>
    238. /// <param name="image">Write back image</param>
    239. /// <param name="originPtr"></param>
    240. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    241. public void GetKernerImg2D(KernelImage image, IntPtr[] originPtr) {
    242. Contract.Requires(originPtr.Length == 3, "stackoverflow in originPtr");
    243. Cl.EnqueueReadImage(ClCompiler.CommandQueue, image.GpuBuffer, Bool.True, originPtr, image.RegionPtr, IntPtr.Zero, IntPtr.Zero, image.Source, 0, null, out _);
    244. }
    245. }
    246. }



    Beispiel:


    OpenCL - Code
    Spoiler anzeigen

    C-Quellcode

    1. __constant sampler_t smp = CLK_NORMALIZED_COORDS_FALSE | //Natural coordinates
    2. CLK_ADDRESS_CLAMP_TO_EDGE | //Clamp to zeros
    3. CLK_FILTER_LINEAR;
    4. __kernel
    5. void run(
    6. __read_only image2d_t src,
    7. __read_write image2d_t dst,
    8. int size
    9. ) {
    10. int x = get_global_id(0);
    11. int y = get_global_id(1);
    12. int2 cord = (int2) (x, y);
    13. float4 locPx = read_imagef(src, smp, cord );
    14. locPx.x = locPx.x * 0.11f; //B
    15. locPx.y = locPx.y * 0.59f; //G
    16. locPx.z = locPx.z * 0.3f; //R
    17. write_imagef(dst, cord, locPx);
    18. }


    C# - Code
    Spoiler anzeigen

    C#-Quellcode

    1. Bitmap bitmap = new Bitmap("image.png");
    2. string sourceCode = Encoding.Default.GetString(Properties.Resources.test);
    3. OpenClBridge openClBridge = ClCompiler.CompileProgramFromSource(sourceCode);
    4. KernelImage image = new KernelImage(0, OpenCL.Net.MemFlags.ReadOnly, bitmap);
    5. KernelImage image2 = new KernelImage(0, OpenCL.Net.MemFlags.WriteOnly, bitmap);
    6. openClBridge.SetKernerArgImg2D(image, ClCompiler.OriginPtr);
    7. openClBridge.SetKernerArgImg2D(image2, ClCompiler.OriginPtr);
    8. openClBridge.SetKernelArg(2, 5); //Size eig. unnötig
    9. openClBridge.Execute(image.WorkGroupSizePtr);
    10. openClBridge.GetKernerImg2D(image2, ClCompiler.OriginPtr);
    11. //image2.Source <- Modifiziertes Bmp (byte[])
    @Facebamm Sorry, das sieht aus wie ein höheres Studio als VS 2017, der will die Sprachversion 7.2, hab ich nich, ich stehe bei 7.0. ;(
    ====
    Das hab ich behoben, readonly einfach weggelassen.
    Dann bleibt es wohl am OpenCL hängen, was ich nicht hab.


    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    ja, das stimmt, ist 7.3 :whistling:

    oh, ja, das ist easy zu fixen ...

    schau mal in deinen System32 ordner nach, dort sollte opencl.dll liegen, die nimmt du per drag and drop in dein Projekt und stellst auf "nur kopiern, wenn neuer"
    @Facebamm Jou.
    Wenn die DLL das tut, ists in Ordnung.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Facebamm :/

    gilt auch für die 64-Bit-Version.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!