1 module dcl.context; 2 3 import dcl.base; 4 import dcl.device; 5 import dcl.platform; 6 import dcl.program; 7 import dcl.commandqueue; 8 9 /// 10 class CLContext : CLObject 11 { 12 protected: 13 /// 14 static synchronized class NotifyBuffer 15 { 16 /// 17 protected Notify[] list; 18 19 /// 20 void push( Notify n ) { list ~= n; } 21 22 /// 23 Notify[] getAll() const 24 { 25 auto ret = new Notify[]( list.length ); 26 foreach( i, n; list ) ret[i] = n; 27 return ret; 28 } 29 30 /// 31 void drop() { list.length = 0; } 32 } 33 34 /// 35 shared NotifyBuffer notify_buffer; 36 37 static CLContext[cl_context] used; 38 39 this( cl_context id ) 40 { 41 enforce( id !is null, new CLException( "can't create context with null id" ) ); 42 enforce( id !in used, new CLException( "can't create existing context" ) ); 43 this.id = id; 44 used[id] = this; 45 checkCall!clRetainContext(id); 46 47 notify_buffer = new shared NotifyBuffer; 48 updateDevices(); 49 } 50 51 CLDevice[] _devices; 52 53 void updateDevices() 54 { 55 import std.stdio; 56 uint ndev; 57 checkCall!clGetContextInfo( id, CL_CONTEXT_NUM_DEVICES, 58 uint.sizeof, &ndev, null ); 59 60 auto dev_ids = new cl_device_id[](ndev); 61 size_t dev_ids_bytes; 62 63 checkCall!clGetContextInfo( id, CL_CONTEXT_DEVICES, 64 ndev * cl_device_id.sizeof, 65 dev_ids.ptr, &dev_ids_bytes ); 66 67 _devices = dev_ids.map!(a=>CLDevice.getFromID(a)).array; 68 } 69 70 package: 71 /// 72 cl_context id; 73 74 public: 75 76 static CLContext getFromID( cl_context id ) 77 { 78 if( id is null ) return null; 79 if( id in used ) return used[id]; 80 return new CLContext(id); 81 } 82 83 /// 84 static struct Notify 85 { 86 /// 87 string errinfo; 88 /// 89 immutable(void)[] bininfo; 90 } 91 92 /// 93 this( CLDevice[] devs ) 94 in{ assert(devs.length); } body 95 { 96 enforce( devs.all!(a=>a.platform is devs[0].platform) ); 97 98 auto prop = getProperties(devs[0].platform); 99 100 this( checkCode!clCreateContext( prop.ptr, 101 cast(uint)_devices.length, 102 getIDsPtr(_devices), 103 &pfn_notify, 104 cast(void*)notify_buffer ) ); 105 } 106 107 /// 108 this( CLPlatform pl, CLDevice.Type type=CLDevice.Type.ALL ) 109 { 110 auto prop = getProperties(pl); 111 112 this( checkCode!clCreateContextFromType( prop.ptr, type, 113 &pfn_notify, 114 cast(void*)notify_buffer ) ); 115 } 116 117 /// 118 CLPlatform platform() @property { return _devices[0].platform; } 119 120 /// 121 CLDevice[] devices() @property { return _devices; } 122 123 /// 124 Notify[] notifies() const { return notify_buffer.getAll(); } 125 /// 126 void dropNotifies() { return notify_buffer.drop(); } 127 128 /// 129 CLProgram buildProgram( string src, CLBuildOption[] opt=[] ) 130 { 131 auto prog = regChild( CLProgram.createWithSource( this, src ) ); 132 prog.build( devices, opt ); 133 return prog; 134 } 135 136 /// 137 CLCommandQueue createQueue( CLCommandQueue.Properties[] prop, size_t devNo=0 ) 138 in{ assert( devNo < devices.length ); } body 139 { return newChild!CLCommandQueue( this, devNo, prop ); } 140 141 static private enum info_list = 142 [ 143 "uint reference_count:refcount", 144 "cl_context_properties[] properties" 145 ]; 146 147 mixin( infoMixin( "context", info_list ) ); 148 149 protected: 150 151 override void selfDestroy() 152 { 153 used.remove(id); 154 checkCall!clReleaseContext(id); 155 } 156 157 cl_context_properties[] getProperties( CLPlatform p ) 158 { 159 return [ CL_CONTEXT_PLATFORM, cast(cl_context_properties)(p.id), 0 ]; 160 } 161 } 162 163 private 164 { 165 version(Windows) 166 { 167 extern(Windows) void pfn_notify( const char* errinfo, const void* private_info, size_t cb, void* user_data ) 168 { 169 auto nb = (cast(shared CLContext.NotifyBuffer)user_data); 170 nb.push( CLContext.Notify( errinfo.fromStringz.idup, 171 (cast(ubyte*)private_info)[0..cb].idup ) ); 172 } 173 } 174 else 175 { 176 extern(C) void pfn_notify( const char* errinfo, const void* private_info, size_t cb, void* user_data ) 177 { 178 auto nb = (cast(shared CLContext.NotifyBuffer)user_data); 179 nb.push( CLContext.Notify( errinfo.fromStringz.idup, 180 (cast(ubyte*)private_info)[0..cb].idup ) ); 181 } 182 } 183 }