Search Unity

Has anyone done OpenCL + Unity on Mac?

Discussion in 'Scripting' started by Molt, Mar 12, 2013.

  1. Molt

    Molt

    Joined:
    Sep 6, 2011
    Posts:
    103
    I've been playing with OpenCL in Unity on Windows recently, using both the OpenCL.Net bindings and the Cloo ones, and so far everything' has gone well up to the point where I'm generating textures and moving them into Unity via SetPixel32(). It was just a case of dragging the .dll into my Assets directory and I was good to go.

    The problem is that now I've now copied the projects to my Macbook and have found that neither binding is finding any OpenCL platforms and so I can't do anything. The libraries are both linking fine, they're just reporting zero platforms, and I know I do have OpenCL-hardware as OpenCL code in C is finding both my CPU and GPU and running OpenCL demos fine.

    Both machines are running Unity 4 Pro, and the projects are identical on the two machines.

    Before I resort to digging through the code of the bindings to see if I can find what the problem is I thought I"d check if anyone'd seen this before and if so had a quick solution, or at least any suggestions to point me in the right direction.
     
  2. Jaymz

    Jaymz

    Joined:
    Jan 28, 2013
    Posts:
    7
    can you give some details about how are you trying this? I have the latest Macbook Pro which only has the NVIDIA card working with OpenCL because Intel HD 4000 does not have OpenCL compatible drivers yet for Mac OSX :(
     
  3. Molt

    Molt

    Joined:
    Sep 6, 2011
    Posts:
    103
    Okay, I added Cloo.dll from http://sourceforge.net/projects/cloo/ into my Assets folder which gives me access to the OpenCL library with nicer .Net bindings, and should be compatible with OpenCL on Windows, Mac or Linux. I have also tried the OpenCL.net bindings, which are a simpler low-level binding, with the same result).

    Given those bindings the following Unity Component should just list the compute platforms and devices available to the debug console, it doesn't try and do anything with them, it's pretty much a minimal "Is OpenCL available and working?" script:

    Code (csharp):
    1. using System;
    2. using UnityEngine;
    3. using Cloo;
    4.  
    5. public class ListDevices : MonoBehaviour {
    6.  
    7.     // Use this for initialization
    8.     void Start () {
    9.         int platformCount = ComputePlatform.Platforms.Count;
    10.         Debug.Log("Found "+platformCount+ " platforms");
    11.  
    12.         for (var platformIndex = 0; platformIndex < platformCount; platformIndex++) {
    13.             var platform = ComputePlatform.Platforms[platformIndex] as ComputePlatform;
    14.             if (platform == null) {
    15.                 throw new Exception("Somehow got a ComputePlatform which isn't a ComputePlatform, aborting");
    16.             }
    17.             Debug.Log("Found platform: " + platform.Name);
    18.            
    19.             foreach (var device in platform.Devices)
    20.             {
    21.                 Debug.Log("  Device: "+device.Name);
    22.             }
    23.         }
    24.     }
    25.    
    26.     // Update is called once per frame
    27.     void Update () {
    28.    
    29.     }
    30. }
    On my Windows desktop I get:
    ..but on my Macbook Retina, which is using the nVidia GPU (Confirmed via gfxCardStatus program), I get:
    I have tried some OpenCL demonstration programs on the Macbook which don't use .Net bindings and they're finding both the nVidia GPU and the i7 CPU as two separate OpenCL platforms so they are at least available and properly configured at some level, I just can't see them in Unity/Cloo or Unity/OpenCL.net.

    When I have time I'm going to see what happens if I use the Cloo bindings outside of Unity on the Mac, find out if it's a problem with them or something in the Unity runtime which is stopping this from working. I admit so far I've just been having too much fun playing about which this on the Windows side of things, which is working really nicely, rather than taking the time to find out why things are broken on the OS X side.
     
    Last edited: Mar 14, 2013
  4. Molt

    Molt

    Joined:
    Sep 6, 2011
    Posts:
    103
    Okay, seems the same thing's happening in Monodevelop outside of Unity. Shall investigate more, and ask the Cloo folks too, and when it's all working shall put a quick guide somewhere in the forums here in case anyone else hits similar problems.
     
  5. phidri

    phidri

    Joined:
    Dec 1, 2012
    Posts:
    2
    It is a library binding and finding issue I guess. Like the one on this thread:
    http://answers.unity3d.com/questions/359991/how-to-use-mono-dllnamedllconfig-with-unity.html

    I have the same problem with cloo and already tried to fix it with dllmap config settings (even going into the build .app package content and fix the mono/etc/config), but without success...

    If someone knows how to integrate platform-independent OpenCL, especially Cloo, properly in Unity3D, I'd be very happy to know about that, too :)
     
  6. Molt

    Molt

    Joined:
    Sep 6, 2011
    Posts:
    103
    Thanks phidri, I'd not seen that before- it at least gives me another line of investigation. I'll try and have a go with that later in the week just in case I find something, I do have Unity Pro here so if (as they suspected..) it needed Pro then I should be able to do something, and if not I may see if I can somehow hack it together by rebuilding Cloo using that type of config in (non-Unity) Mono and use the resultant DLL in Unity.

    Did ask on the Cloo forum but haven't had any replies yet, going to dig out my OpenCL.net version and ask there too.
     
  7. Molt

    Molt

    Joined:
    Sep 6, 2011
    Posts:
    103
    Okay- thanks to phidri's comment, corintho's initial investigation, and some random searching and experimentation I now appear to have Cloo working with Unity on the Mac. So far I've only had it adding a series of numbers together but if that works I see no reason the rest shouldn't work too.

    The key does lie with the DllMap but it's not solved by adding a Cloo.dll.config it's solved by (*gulp*) editing Unity's own configuration files. Without starting Unity use a text editor to open the file
    Code (csharp):
    1. /Applications/Unity/Unity.app/Contents/Frameworks/Mono/etc/mono/config
    and add the following two lines to the DllMap lines already in it:

    Code (csharp):
    1.  
    2. <dllmap os="linux" dll="OpenCL.dll" target="libOpenCL.so"/>
    3. <dllmap os="osx" dll="OpenCL.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
    4.  
    Now when you restart Unity, and add the Cloo.dll into your Assets, you should have access to OpenCL from within Unity.
     
  8. corintho

    corintho

    Joined:
    Oct 14, 2011
    Posts:
    10
    Molt,

    Good to see some progress, I came to the same conclusion as you. I needed to change Unity's internal dllmap to make it work, I don't think that's an optimal solution, but it works on Indie version as well. I am currently working towards a Unity extension to make noise using OpenCL, and for that I would need everyone who gets it, to be willing to edit their Unity configuration files.
    For now, I have hacked a Cloo.dll that is internally bound against "/System/Library/Frameworks/OpenCL.framework/OpenCL", I have a script that determines if the editor is windows or mac and updates the libraries as necessary. Its a bit hacky, but at least I don't have to edit Unity internal configuration files (and remember to do that after every update).
    I think the best way would have Unity developers to officially add those two lines to the file, that would make a whole bunch of possibilities open without any troubles for them.

    Good to see more people tackling OpenCL in Unity.
     
  9. phidri

    phidri

    Joined:
    Dec 1, 2012
    Posts:
    2
    Molt, corintho,

    thanks for the final hints - it works as far as I tested it now - despite still being hacky. You have to modify the dllmap in the built osx app package, too. OpenCL is such a convenient thing for future computing tasks - especially for multi-platform solutions.

    Best wishes for your works!
     
  10. Foam

    Foam

    Joined:
    Jun 13, 2012
    Posts:
    322
    I hate to necrobump something but I've found this thread to be a great use for a very unused and little documented feature.

    In sum, copy the Cloo.DLL to your project, then add the lines above to /Unity/Unity.app/Contents/Frameworks/Mono/etc/mono/config and then you're good to go, whether it's Cloo or not, as the DLLs are provided by OSX (obviously, since the CL libs are provided by OSX, you can just as easily add, for example, Lumial instead of Cloo).

    Keep in mind that printf is not part of OpenCL, it's a host convenience function. So if you want to test things out use something like this:

    Code (csharp):
    1. class ClooTest (MonoBehaviour):
    2.     kernel_code as string
    3.     def Awake():
    4.         kernel_code = """
    5.         kernel void VectorAdd(global read_only float* a, global read_only float* b, global write_only float* c) {
    6.            int index = get_global_id(0);
    7.            c[index] = a[index] + b[index];
    8.         }
    9.         """
    10.    
    11.     def Start():
    12.         Debug.Log("BEGIN CLOO")
    13.         platform_info()
    14.         vector_addition()
    15.  
    16.     def platform_info():
    17.         platform_count = ComputePlatform.Platforms.Count
    18.         Debug.Log("Found $platform_count platforms")
    19.         for p as ComputePlatform in ComputePlatform.Platforms:
    20.             Debug.Log("Found platform: $(p.Name)")
    21.             for device in p.Devices:
    22.                 Debug.Log("   Device: $(device.Name)")
    23.  
    24.     def vector_addition():
    25.         count = 10
    26.         array_a = array(single, count)
    27.         array_b = array(single, count)
    28.         array_c = array(single, count)
    29.         rand = System.Random()
    30.         for i in range(count):
    31.             array_a[i] = rand.NextDouble() * 100
    32.             array_b[i] = rand.NextDouble() * 100
    33.  
    34.         platform as ComputePlatform = ComputePlatform.Platforms[0]
    35.         context as ComputeContext = ComputeContext(ComputeDeviceTypes.Gpu, ComputeContextPropertyList(platform), null, IntPtr.Zero)
    36.         a as ComputeBuffer[of single] = ComputeBuffer[of single](context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, array_a)
    37.         b as ComputeBuffer[of single] = ComputeBuffer[of single](context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, array_b)
    38.         c as ComputeBuffer[of single] = ComputeBuffer[of single](context, ComputeMemoryFlags.WriteOnly, array_c.Length)
    39.  
    40.         program = ComputeProgram(context, kernel_code)
    41.         program.Build(null, null, null, IntPtr.Zero)
    42.  
    43.         kernel = program.CreateKernel("VectorAdd")
    44.         kernel.SetMemoryArgument(0, a)
    45.         kernel.SetMemoryArgument(1, b)
    46.         kernel.SetMemoryArgument(2, c)
    47.  
    48.         event_list = ComputeEventList()
    49.         commands = ComputeCommandQueue(context, context.Devices[0], ComputeCommandQueueFlags.None)
    50.         # j as (long) = (count cast long)
    51.         j = array(long, 1)
    52.         j[0] = count
    53.         commands.Execute(kernel, null, j, null, event_list)
    54.         commands.ReadFromBuffer(c, array_c, false, event_list)
    55.         commands.Finish()
    56.  
    57.         i = count - 1
    58.         Debug.Log("$(array_a[i]) + $(array_b[i]) = $(array_c[i])")
    59.  
    It's all QUITE manual, but, it does work. Pretty easily, really.
     
    Last edited: Dec 21, 2013
    jason-fisher likes this.
  11. mnop14000

    mnop14000

    Joined:
    Mar 27, 2015
    Posts:
    1