ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/OpenCL/OpenCL.pm
(Generate patch)

Comparing OpenCL/OpenCL.pm (file contents):
Revision 1.60 by root, Wed Apr 25 21:48:44 2012 UTC vs.
Revision 1.68 by root, Tue May 1 22:25:13 2012 UTC

212 $ev->wait; 212 $ev->wait;
213 213
214=head2 Use the OpenGL module to share a texture between OpenCL and OpenGL and draw some julia 214=head2 Use the OpenGL module to share a texture between OpenCL and OpenGL and draw some julia
215set tunnel effect. 215set tunnel effect.
216 216
217This is quite a long example to get you going. 217This is quite a long example to get you going - you can download it from
218L<http://cvs.schmorp.de/OpenCL/examples/juliaflight>.
218 219
219 use OpenGL ":all"; 220 use OpenGL ":all";
220 use OpenCL; 221 use OpenCL;
221 222
223 my $S = $ARGV[0] || 256; # window/texture size, smaller is faster
224
222 # open a window and create a gl texture 225 # open a window and create a gl texture
223 OpenGL::glpOpenWindow width => 256, height => 256; 226 OpenGL::glpOpenWindow width => $S, height => $S;
224 my $texid = glGenTextures_p 1; 227 my $texid = glGenTextures_p 1;
225 glBindTexture GL_TEXTURE_2D, $texid; 228 glBindTexture GL_TEXTURE_2D, $texid;
226 glTexImage2D_c GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0; 229 glTexImage2D_c GL_TEXTURE_2D, 0, GL_RGBA8, $S, $S, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0;
227 230
228 # find and use the first opencl device that let's us get a shared opengl context 231 # find and use the first opencl device that let's us get a shared opengl context
229 my $platform; 232 my $platform;
230 my $dev; 233 my $dev;
231 my $ctx; 234 my $ctx;
250 # now the boring opencl code 253 # now the boring opencl code
251 my $src = <<EOF; 254 my $src = <<EOF;
252 kernel void 255 kernel void
253 juliatunnel (write_only image2d_t img, float time) 256 juliatunnel (write_only image2d_t img, float time)
254 { 257 {
255 float2 p = (float2)(get_global_id (0), get_global_id (1)) / 256.f * 2.f - 1.f; 258 int2 xy = (int2)(get_global_id (0), get_global_id (1));
259 float2 p = convert_float2 (xy) / $S.f * 2.f - 1.f;
256 260
257 float2 m = (float2)(1.f, p.y) / fabs (p.x); 261 float2 m = (float2)(1.f, p.y) / fabs (p.x); // tunnel
258 m.x = fabs (fmod (m.x + time * 0.05f, 4.f)) - 2.f; 262 m.x = fabs (fmod (m.x + time * 0.05f, 4.f) - 2.f);
259 263
260 float2 z = m; 264 float2 z = m;
261 float2 c = (float2)(sin (time * 0.05005), cos (time * 0.06001)); 265 float2 c = (float2)(sin (time * 0.01133f), cos (time * 0.02521f));
262 266
263 for (int i = 0; i < 25 && dot (z, z) < 4.f; ++i) 267 for (int i = 0; i < 25 && dot (z, z) < 4.f; ++i) // standard julia
264 z = (float2)(z.x * z.x - z.y * z.y, 2.f * z.x * z.y) + c; 268 z = (float2)(z.x * z.x - z.y * z.y, 2.f * z.x * z.y) + c;
265 269
266 float3 colour = (float3)(z.x, z.y, z.x * z.y); 270 float3 colour = (float3)(z.x, z.y, atan2 (z.y, z.x));
267 write_imagef (img, (int2)(get_global_id (0), get_global_id (1)), (float4)(colour * p.x * p.x, 1.)); 271 write_imagef (img, xy, (float4)(colour * p.x * p.x, 1.));
268 } 272 }
269 EOF 273 EOF
270 274
271 my $prog = $ctx->build_program ($src); 275 my $prog = $ctx->build_program ($src);
272 my $kernel = $prog->kernel ("juliatunnel"); 276 my $kernel = $prog->kernel ("juliatunnel");
276 for (my $time; ; ++$time) { 280 for (my $time; ; ++$time) {
277 # acquire objects from opengl 281 # acquire objects from opengl
278 $queue->acquire_gl_objects ([$tex]); 282 $queue->acquire_gl_objects ([$tex]);
279 283
280 # configure and run our kernel 284 # configure and run our kernel
281 $kernel->set_image2d (0, $tex); 285 $kernel->setf ("mf", $tex, $time*2); # mf = memory object, float
282 $kernel->set_float (1, $time);
283 $queue->nd_range_kernel ($kernel, undef, [256, 256], undef); 286 $queue->nd_range_kernel ($kernel, undef, [$S, $S], undef);
284 287
285 # release objects to opengl again 288 # release objects to opengl again
286 $queue->release_gl_objects ([$tex]); 289 $queue->release_gl_objects ([$tex]);
287 290
288 # wait 291 # wait
301 304
302 glXSwapBuffers; 305 glXSwapBuffers;
303 306
304 select undef, undef, undef, 1/60; 307 select undef, undef, undef, 1/60;
305 } 308 }
309
310=head2 How to modify the previous example to not rely on GL sharing.
311
312For those poor souls with only a sucky CPU OpenCL implementation, you
313currently have to read the image into some perl scalar, and then modify a
314texture or use glDrawPixels or so).
315
316First, when you don't need gl sharing, you can create the context much simpler:
317
318 $ctx = $platform->context (undef, [$dev])
319
320To use a texture, you would modify the above example by creating an
321OpenCL::Image manually instead of deriving it from a texture:
322
323 my $tex = $ctx->image2d (OpenCL::MEM_WRITE_ONLY, OpenCL::RGBA, OpenCL::UNORM_INT8, $S, $S);
324
325And in the darw loop, intead of acquire_gl_objects/release_gl_objects, you
326would read the image2d after the kernel has written it:
327
328 $queue->read_image ($tex, 0, 0, 0, 0, $S, $S, 1, 0, 0, my $data);
329
330And then you would upload the pixel data to the texture (or use glDrawPixels):
331
332 glTexSubImage2D_s GL_TEXTURE_2D, 0, 0, 0, $S, $S, GL_RGBA, GL_UNSIGNED_BYTE, $data;
333
334The fully modified example can be found at
335L<http://cvs.schmorp.de/OpenCL/examples/juliaflight-nosharing>.
306 336
307=head1 DOCUMENTATION 337=head1 DOCUMENTATION
308 338
309=head2 BASIC CONVENTIONS 339=head2 BASIC CONVENTIONS
310 340
493=cut 523=cut
494 524
495package OpenCL; 525package OpenCL;
496 526
497use common::sense; 527use common::sense;
528use Carp ();
498use Async::Interrupt (); 529use Async::Interrupt ();
499 530
500our $POLL_FUNC; # set by XS 531our $POLL_FUNC; # set by XS
501 532
502BEGIN { 533BEGIN {
503 our $VERSION = '0.97'; 534 our $VERSION = '0.98';
504 535
505 require XSLoader; 536 require XSLoader;
506 XSLoader::load (__PACKAGE__, $VERSION); 537 XSLoader::load (__PACKAGE__, $VERSION);
507 538
508 @OpenCL::Platform::ISA = 539 @OpenCL::Platform::ISA =
526 @OpenCL::Image1D::ISA = 557 @OpenCL::Image1D::ISA =
527 @OpenCL::Image1DArray::ISA = 558 @OpenCL::Image1DArray::ISA =
528 @OpenCL::Image1DBuffer::ISA = OpenCL::Image::; 559 @OpenCL::Image1DBuffer::ISA = OpenCL::Image::;
529 560
530 @OpenCL::UserEvent::ISA = OpenCL::Event::; 561 @OpenCL::UserEvent::ISA = OpenCL::Event::;
562
563 @OpenCL::MappedBuffer::ISA =
564 @OpenCL::MappedImage::ISA = OpenCL::Mapped::;
531} 565}
532 566
533=head2 THE OpenCL PACKAGE 567=head2 THE OpenCL PACKAGE
534 568
535=over 4 569=over 4
537=item $int = OpenCL::errno 571=item $int = OpenCL::errno
538 572
539The last error returned by a function - it's only valid after an error occured 573The last error returned by a function - it's only valid after an error occured
540and before calling another OpenCL function. 574and before calling another OpenCL function.
541 575
542=item $str = OpenCL::err2str $errval 576=item $str = OpenCL::err2str [$errval]
543 577
544Comverts an error value into a human readable string. 578Converts an error value into a human readable string. IF no error value is
579given, then the last error will be used (as returned by OpenCL::errno).
545 580
546=item $str = OpenCL::enum2str $enum 581=item $str = OpenCL::enum2str $enum
547 582
548Converts most enum values (of parameter names, image format constants, 583Converts most enum values (of parameter names, image format constants,
549object types, addressing and filter modes, command types etc.) into a 584object types, addressing and filter modes, command types etc.) into a
1002=cut 1037=cut
1003 1038
1004sub OpenCL::Context::build_program { 1039sub OpenCL::Context::build_program {
1005 my ($self, $prog, $options) = @_; 1040 my ($self, $prog, $options) = @_;
1006 1041
1007 require Carp;
1008
1009 $prog = $self->program_with_source ($prog) 1042 $prog = $self->program_with_source ($prog)
1010 unless ref $prog; 1043 unless ref $prog;
1011 1044
1012 # we build separately per device so we instantly know which one failed 1045 eval { $prog->build (undef, $options); 1 }
1046 or errno == BUILD_PROGRAM_FAILURE
1047 or errno == INVALID_BINARY # workaround nvidia bug
1048 or Carp::croak "OpenCL::Context->build_program: " . err2str;
1049
1050 # we check status for all devices
1013 for my $dev ($self->devices) { 1051 for my $dev ($self->devices) {
1014 eval { $prog->build ([$dev], $options); 1 } 1052 $prog->build_status ($dev) == BUILD_SUCCESS
1015 or Carp::croak ("Building OpenCL program for device '" . $dev->name . "' failed:\n" 1053 or Carp::croak "Building OpenCL program for device '" . $dev->name . "' failed:\n"
1016 . $prog->build_log ($dev)); 1054 . $prog->build_log ($dev);
1017 } 1055 }
1018 1056
1019 $prog 1057 $prog
1020} 1058}
1021 1059
1199 1237
1200=item $ev = $queue->write_buffer_rect (OpenCL::Memory buf, cl_bool blocking, $buf_x, $buf_y, $buf_z, $host_x, $host_y, $host_z, $width, $height, $depth, $buf_row_pitch, $buf_slice_pitch, $host_row_pitch, $host_slice_pitch, $data, $wait_events...) 1238=item $ev = $queue->write_buffer_rect (OpenCL::Memory buf, cl_bool blocking, $buf_x, $buf_y, $buf_z, $host_x, $host_y, $host_z, $width, $height, $depth, $buf_row_pitch, $buf_slice_pitch, $host_row_pitch, $host_slice_pitch, $data, $wait_events...)
1201 1239
1202http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueWriteBufferRect.html 1240http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueWriteBufferRect.html
1203 1241
1242=item $ev = $queue->copy_buffer_to_image ($src_buffer, $dst_image, $src_offset, $dst_x, $dst_y, $dst_z, $width, $height, $depth, $wait_events...)
1243
1244L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueCopyBufferToImage.html>
1245
1204=item $ev = $queue->read_image ($src, $blocking, $x, $y, $z, $width, $height, $depth, $row_pitch, $slice_pitch, $data, $wait_events...) 1246=item $ev = $queue->read_image ($src, $blocking, $x, $y, $z, $width, $height, $depth, $row_pitch, $slice_pitch, $data, $wait_events...)
1205 1247
1206L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueCopyBufferRect.html> 1248C<$row_pitch> (and C<$slice_pitch>) can be C<0>, in which case the OpenCL
1207 1249module uses the image width (and height) to supply default values.
1208=item $ev = $queue->copy_buffer_to_image ($src_buffer, $dst_image, $src_offset, $dst_x, $dst_y, $dst_z, $width, $height, $depth, $wait_events...)
1209 1250
1210L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueReadImage.html> 1251L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueReadImage.html>
1211 1252
1212=item $ev = $queue->write_image ($src, $blocking, $x, $y, $z, $width, $height, $depth, $row_pitch, $slice_pitch, $data, $wait_events...) 1253=item $ev = $queue->write_image ($src, $blocking, $x, $y, $z, $width, $height, $depth, $row_pitch, $slice_pitch, $data, $wait_events...)
1213 1254
1255C<$row_pitch> (and C<$slice_pitch>) can be C<0>, in which case the OpenCL
1256module uses the image width (and height) to supply default values.
1214L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueWriteImage.html> 1257L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueWriteImage.html>
1215 1258
1216=item $ev = $queue->copy_image ($src_image, $dst_image, $src_x, $src_y, $src_z, $dst_x, $dst_y, $dst_z, $width, $height, $depth, $wait_events...) 1259=item $ev = $queue->copy_image ($src_image, $dst_image, $src_x, $src_y, $src_z, $dst_x, $dst_y, $dst_z, $width, $height, $depth, $wait_events...)
1217 1260
1218L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueCopyImage.html> 1261L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueCopyImage.html>
1325 1368
1326=for gengetinfo end command_queue 1369=for gengetinfo end command_queue
1327 1370
1328=back 1371=back
1329 1372
1373=head3 MEMORY MAPPED BUFFERS
1374
1375OpenCL allows you to map buffers and images to host memory (read: perl
1376scalars). This is done much like reading or copying a buffer, by enqueuing
1377a map or unmap operation on the command queue.
1378
1379The map operations return a C<OpenCL::Mapped> object - see L<THE
1380OpenCL::Mapped CLASS> section for details on what to do with these
1381objects.
1382
1383The object will be unmapped automatically when the mapped object is
1384destroyed (you can use a barrier to make sure the unmap has finished,
1385before using the buffer in a kernel), but you can also enqueue an unmap
1386operation manually.
1387
1388=over 4
1389
1390=item $mapped_buffer = $queue->map_buffer ($buf, $data, $blocking=1, $map_flags=OpenCL::MAP_READ|OpenCL::MAP_WRITE, $offset=0, $size=0, $wait_events...)
1391
1392Maps the given buffer into host memory and returns a C<OpenCL::MappedBuffer> object.
1393
1394L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueMapBuffer.html>
1395
1396=item $mapped_image = $queue->map_image ($img, $data, $blocking=1, $map_flags=OpenCL::MAP_READ|OpenCL::MAP_WRITE, $x=0, $y=0, $z=0, $width=0, $height=0, $depth=0, $wait_events...)
1397
1398Maps the given image area into host memory and return a
1399C<OpenCL::MappedImage> object. Although there are default values for most
1400arguments, you currently have to specify all arguments, otherwise the call
1401will fail.
1402
1403L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clEnqueueMapImage.html>
1404
1405=item $ev = $queue->unmap ($mapped, $wait_events...)
1406
1407Unmaps the data from host memory. You must not call any methods that
1408modify the data, or modify the data scalar directly, after calling this
1409method.
1410
1411The mapped event object will always be passed as part of the
1412$wait_events. The mapped event object will be replaced by the new event
1413object that this request creates.
1414
1415=back
1416
1330=head2 THE OpenCL::Memory CLASS 1417=head2 THE OpenCL::Memory CLASS
1331 1418
1332This the superclass of all memory objects - OpenCL::Buffer, OpenCL::Image, 1419This the superclass of all memory objects - OpenCL::Buffer, OpenCL::Image,
1333OpenCL::Image2D and OpenCL::Image3D. 1420OpenCL::Image2D and OpenCL::Image3D.
1334 1421
1524If a callback is specified, then it will be called when compilation is 1611If a callback is specified, then it will be called when compilation is
1525finished. Note that many OpenCL implementations block your program while 1612finished. Note that many OpenCL implementations block your program while
1526compiling whether you use a callback or not. See C<build_async> if you 1613compiling whether you use a callback or not. See C<build_async> if you
1527want to make sure the build is done in the background. 1614want to make sure the build is done in the background.
1528 1615
1529Note that some OpenCL implementations atc up badly, and don't call the 1616Note that some OpenCL implementations act up badly, and don't call the
1530callback in some error cases (but call it in others). This implementation 1617callback in some error cases (but call it in others). This implementation
1531assumes the callback will always be called, and leaks memory if this is 1618assumes the callback will always be called, and leaks memory if this is
1532not so. So best make sure you don't pass in invalid values. 1619not so. So best make sure you don't pass in invalid values.
1620
1621Some implementations fail with C<OpenCL::INVALID_BINARY> when the
1622compilation state is successful but some later stage fails.
1533 1623
1534L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clBuildProgram.html> 1624L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clBuildProgram.html>
1535 1625
1536=item $program->build_async (\@devices = undef, $options = "", $cb->($program) = undef) 1626=item $program->build_async (\@devices = undef, $options = "", $cb->($program) = undef)
1537 1627
1872 1962
1873L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clSetUserEventStatus.html> 1963L<http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clSetUserEventStatus.html>
1874 1964
1875=back 1965=back
1876 1966
1967=head2 THE OpenCL::Mapped CLASS
1968
1969This class represents objects mapped into host memory. They are
1970represented by a blessed string scalar. The string data is the mapped
1971memory area, that is, if you read or write it, then the mapped object is
1972accessed directly.
1973
1974You must only ever use operations that modify the string in-place - for
1975example, a C<substr> that doesn't change the length, or maybe a regex that
1976doesn't change the length. Any other operation might cause the data to be
1977copied.
1978
1979When the object is destroyed it will enqueue an implicit unmap operation
1980on the queue that was used to create it.
1981
1982Keep in mind that you I<need> to unmap (or destroy) mapped objects before
1983OpenCL sees the changes, even if some implementations don't need this
1984sometimes.
1985
1986Example, replace the first two floats in the mapped buffer by 1 and 2.
1987
1988 my $mapped = $queue->map_buffer ($buf, ...
1989 $mapped->event->wait; # make sure it's there
1990
1991 # now replace first 8 bytes by new data, which is exactly 8 bytes long
1992 # we blindly assume device endianness to equal host endianness
1993 # (and of course, we assume iee 754 single precision floats :)
1994 substr $$mapped, 0, 8, pack "f*", 1, 2;
1995
1996=over 4
1997
1998=item $ev = $mapped->unmap ($wait_events...)
1999
2000Unmaps the mapped memory object, using the queue originally used to create
2001it, quite similarly to C<< $queue->unmap ($mapped, ...) >>.
2002
2003=item $bool = $mapped->mapped
2004
2005Returns whether the object is still mapped - true before an C<unmap> is
2006enqueued, false afterwards.
2007
2008=item $ev = $mapped->event
2009
2010Return the event object associated with the mapped object. Initially, this
2011will be the event object created when mapping the object, and after an
2012unmap, this will be the event object that the unmap operation created.
2013
2014=item $mapped->wait
2015
2016Same as C<< $mapped->event->wait >> - makes sure no operations on this
2017mapped object are outstanding.
2018
2019=item $bytes = $mapped->size
2020
2021Returns the size of the mapped area, in bytes. Same as C<length $$mapped>.
2022
2023=item $ptr = $mapped->ptr
2024
2025Returns the raw memory address of the mapped area.
2026
2027=item $mapped->set ($offset, $data)
2028
2029Replaces the data at the given C<$offset> in the memory area by the new
2030C<$data>. This method is safer than direct manipulation of C<$mapped>
2031because it does bounds-checking, but also slower.
2032
2033=item $data = $mapped->get ($offset, $length)
2034
2035Returns (without copying) a scalar representing the data at the given
2036C<$offset> and C<$length> in the mapped memory area. This is the same as
2037the following substr, except much slower;
2038
2039 $data = substr $$mapped, $offset, $length
2040
2041=cut
2042
2043sub OpenCL::Mapped::get {
2044 substr ${$_[0]}, $_[1], $_[2]
2045}
2046
2047=back
2048
2049=head2 THE OpenCL::MappedBuffer CLASS
2050
2051This is a subclass of OpenCL::Mapped, representing mapped buffers.
2052
2053=head2 THE OpenCL::MappedImage CLASS
2054
2055This is a subclass of OpenCL::Mapped, representing mapped images.
2056
2057=over 4
2058
2059=item $bytes = $mapped->row_pitch
2060
2061=item $bytes = $mapped->slice_pitch
2062
2063Return the row or slice pitch of the image that has been mapped.
2064
2065=back
2066
2067
1877=cut 2068=cut
1878 2069
18791; 20701;
1880 2071
1881=head1 AUTHOR 2072=head1 AUTHOR

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines