Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

Use custom struct

Help
VVS0205
2011-05-16
2012-12-21
  • VVS0205
    VVS0205
    2011-05-16

    Big thanks for your project, it is the best project for Net and OpenCl.
    My problem:
    I'm try use custom struct, but I did not get work solution.
    Kernel

    typedef struct 
    {
        int X;
        int * Mass;
    } TestStruct;
    kernel void StructTest(
        global  TestStruct* a,
        global  int* b )
    {
        for (int i = 0; i < 100; i++)
        {
            b[i] = a[index].Mass[i];            
        }
    }
    

    Host:

    var properties = new ComputeContextPropertyList(ComputePlatform.Platforms[0]);
                var context = new ComputeContext(ComputeDeviceTypes.Gpu, properties, null, IntPtr.Zero);
                var quene = new ComputeCommandQueue(context, context.Devices[0], ComputeCommandQueueFlags.None);
                var prog = new ComputeProgram(context, Kernel);
                prog.Build(context.Devices, "", null, IntPtr.Zero);
                var testKernel = prog.CreateKernel("StructTest");
                var ints = new int[100];
                for (int index = 0; index < ints.Length; index++)
                {
                    ints[index] = 100;
                }
                var ints1 = new int[100];
                var triangleMesh = new TestStruct();
                fixed (int * intsPoint = ints)
                {
                    triangleMesh.Mass = intsPoint;
                    triangleMesh.X = 888;
                    IntPtr pntToStruct = Marshal.AllocHGlobal(Marshal.SizeOf(triangleMesh));
                    Marshal.StructureToPtr(triangleMesh, pntToStruct, false);
                    ComputeErrorCode errorCode;
                    CLMemoryHandle triangleMeshDev = CL10.CreateBuffer(context.Handle,
                                                               ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.CopyHostPointer,
                                                               new IntPtr(Marshal.SizeOf(triangleMesh)), pntToStruct,
                                                               out errorCode);
                    var b = new ComputeBuffer<int>(context, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.CopyHostPointer,
                                                   ints1);
                    ComputeErrorCode computeErrorCode = CL10.SetKernelArg(testKernel.Handle, 0, new IntPtr(sizeof(IntPtr)),
                                                                          triangleMeshDev.Value);
                    testKernel.SetMemoryArgument(1, b);
                    quene.Execute(testKernel, null, new long[] { 1 }, null, null);
                    quene.ReadFromBuffer(b, ref ints1, true, null);
                }
    

    This is not working.
    How to pass struct?
    P.S. Sorry for my english. I hope for your help.
    Thanks.

     
  • VVS0205
    VVS0205
    2011-05-16

    Sorry, forgot to add in the kernel

    int index = get_global_id(0);
    
     
  • VVS0205
    VVS0205
    2011-05-17

    I'm find this http://www.opentk.com/node/1496?page=1 in the example of people say that everything works, but I do not.

     
  • VVS0205
    VVS0205
    2011-05-17

    Sorry did not read to the end, bad that it is impossible to convey structure.

     
  • VVS0205
    VVS0205
    2011-05-17

    Off-topic:
    I do not know the bug is or how it should be, but if you initialize an array of bool as follows:

    var bitsDev = new ComputeBuffer<bool>(_compressKernel.Context,
                                                              ComputeMemoryFlags.ReadOnly |
                                                              ComputeMemoryFlags.UseHostPointer, new bool[1000000] );
    

    then the large size of the array, the kernel crashes. But if you do so:

    fixed (bool* resRef = new bool[1000000])
                    {
                        var bitsDev = new ComputeBuffer<bool>(_compressKernel.Context,
                                                              ComputeMemoryFlags.ReadOnly |
                                                              ComputeMemoryFlags.UseHostPointer, bits.Count/4,
                                                              new IntPtr(resRef));
                    }
    

    Everything works fine. I hope something can be done.
    Thanks.

     
  • nythrix
    nythrix
    2011-05-22

    Do not use ComputeMemoryFlags.UseHostPointer or AllocHostPointer, unless you're COMPLETELY sure about what they do. Replace with CopyHostPointer.
    Both pieces of code you provided contain a bug regarding the garbage collector deleting the array while the OpenCL is using them. The first one is more obvious but the second one is bad as well. Because it WILL crash sometime later.