c# - CUDAfy.Net / OpenCL, struct containing byte array results in non-blittable exception -
c# - CUDAfy.Net / OpenCL, struct containing byte array results in non-blittable exception -
ok, i'm using cudafy.net, , have next 3 structs:
[cudafy] public struct collider { public int index; public int type; public sphere sphere; public plane plane; public material material; } [cudafy] public struct material { public color color; public texture texture; public float shininess; } [cudafy] public struct texture { public int width, height; public byte[ ] data; }
now, send on array of collider objects gpu, using
copytodevice<gpu.collider>( colliderarray );
i next error:
an unhandled exception of type 'system.argumentexception' occurred in mscorlib.dll additional information: object contains non-primitive or non-blittable data.
does experience either cudafy.net, or opencl ( since compiles downwards opencl ), have thought how accomplish this? whole problem lies in byte array of texture, since worked fine when didn't have texture struct , array non-blittable part far know. had found several questions regarding same problem, , fixed using fixed-size arrays. however, unable these textures, can have varying sizes.
edit: right now, i'm doing next on cpu:
public unsafe static gpu.texture creategputexture( cudafy.host.gpgpu _gpu, system.drawing.bitmap image ) { gpu.texture t = new gpu.texture( ); t.width = image.width; t.height = image.height; byte[ ] info = new byte[ image.width * image.height * 3 ]; ( int x = 0; x < image.width; x++ ) ( int y = 0; y < image.height; y++ ) { system.drawing.color c = image.getpixel( x, y ); int id = ( x + y * image.width ) * 3; data[ id ] = c.r; data[ id + 1 ] = c.g; data[ id + 2 ] = c.b; } byte[ ] _data = _gpu.copytodevice<byte>( info ); intptr pointer = _gpu.getdevicememory( _data ).pointer; t.data = ( byte* )pointer.topointer( ); homecoming t; }
i attach texture struct colliders, , send them gpu. goes without errors. however, seek utilize texture on gpu, this:
[cudafy] public static color gettexturecolor( int x, int y, texture tex ) { int id = ( x + y * tex.width ) * 3; unsafe { byte r = tex.data[ id ]; byte g = tex.data[ id + 1 ]; byte b = tex.data[ id + 2 ]; homecoming createcolor( ( float )r / 255f, ( float )g / 255f, ( float )b / 255f ); } }
i next error:
an unhandled exception of type 'cloo.invalidcommandqueuecomputeexception' occurred in cudafy.net.dll additional information: opencl error code detected: invalidcommandqueue.
the texture struct looks this, way:
[cudafy] public unsafe struct texture { public int width, height; public byte* data; }
i'm @ loss again..
cudafy not back upwards arrays yet. can't utilize "public byte[] data" neither in structures nor kernels itself. seek less object oriented. mean seek remove info array structre , re-create them separately. e.g. copytodevice("texture properties") , re-create appropriate info array copytodevice("texture data")
edit: ok found solution not pretty code.
as pointer of info stored in gpu mem. cast him in integer value pointer.toint64(); , store value in construction object long value(not long pointer). can utilize gthread.insertcode() method insert straight code kernel without compiling. can not utilize pointer straight in kernel code becase not blittable info type. stop talking here illustration of working code
class programme { [cudafy] public struct teststruct { public double value; public long datapointer; // info pointer adress } [cudafy] public static void kerneltest(gthread thread, teststruct[] structure, int[] intarray) { // gthread.insertcode("int* pointer = (int*)structure[0].datapointer;"); gthread.insertcode("structure[0].value = pointer[1];"); // here can acces info using pointer pointer[0], pointer[1] , on } private unsafe static void main(string[] args) { gpgpu gpucuda = cudafyhost.getdevice(egputype.cuda, 0); cudafymodule km = cudafytranslator.cudafy(); gpucuda.loadmodule(km); teststruct[] host_array = new teststruct[1]; host_array[0] = new teststruct(); int[] host_intarray = new[] {1, 8, 3}; int[] dev_intarray = gpucuda.copytodevice(host_intarray); deviceptrex p = gpucuda.getdevicememory(dev_intarray); intptr pointer = p.pointer; host_array[0].datapointer = pointer.toint64(); teststruct[] dev_array = gpucuda.allocate(host_array); gpucuda.copytodevice(host_array, dev_array); gpucuda.launch().kerneltest(dev_array, dev_intarray); gpucuda.copyfromdevice(dev_array, host_array); console.writeline(host_array[0].value); console.readkey(); } }
the "magic" in insertcode() cast long datapointer value int pointer adress... disadvantage of approache must write parts of code string.
or can separate info , structures e.g.
[cudafy] public struct texture { public int width, height; } [cudafy] public static void kerneltest(gthread thread, texture[] texstructure, byte[] data) {....}
and re-create
dev_data = gpu.copytodevice(host_data); dev_texture = gpu.copytodevice(host_texture); gpu.launch().kerneltest(dev_texture, dev_data);
edit two: forget code :d
check https://cudafy.codeplex.com/discussions/538310 , solution problem https://cudafy.codeplex.com/discussions/283527
c# arrays struct opencl cudafy.net
Comments
Post a Comment