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

Comparing OpenCL/OpenCL.pm (file contents):
Revision 1.61 by root, Sat Apr 28 13:31:40 2012 UTC vs.
Revision 1.67 by root, Tue May 1 22:04:56 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
1003=cut 1037=cut
1004 1038
1005sub OpenCL::Context::build_program { 1039sub OpenCL::Context::build_program {
1006 my ($self, $prog, $options) = @_; 1040 my ($self, $prog, $options) = @_;
1007 1041
1008 require Carp;
1009
1010 $prog = $self->program_with_source ($prog) 1042 $prog = $self->program_with_source ($prog)
1011 unless ref $prog; 1043 unless ref $prog;
1012 1044
1013 eval { $prog->build (undef, $options); 1 } 1045 eval { $prog->build (undef, $options); 1 }
1014 or errno == BUILD_PROGRAM_FAILURE 1046 or errno == BUILD_PROGRAM_FAILURE
1047 or errno == INVALID_BINARY # workaround nvidia bug
1015 or Carp::croak "OpenCL::Context->build_program: " . err2str; 1048 or Carp::croak "OpenCL::Context->build_program: " . err2str;
1016 1049
1017 # we check status for all devices 1050 # we check status for all devices
1018 for my $dev ($self->devices) { 1051 for my $dev ($self->devices) {
1019 $prog->build_status ($dev) == BUILD_SUCCESS 1052 $prog->build_status ($dev) == BUILD_SUCCESS
1020 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"
1021 . $prog->build_log ($dev)); 1054 . $prog->build_log ($dev);
1022 } 1055 }
1023 1056
1024 $prog 1057 $prog
1025} 1058}
1026 1059
1204 1237
1205=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...)
1206 1239
1207http://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
1208 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
1209=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...)
1210 1247
1211L<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
1212 1249module uses the image width (and height) to supply default values.
1213=item $ev = $queue->copy_buffer_to_image ($src_buffer, $dst_image, $src_offset, $dst_x, $dst_y, $dst_z, $width, $height, $depth, $wait_events...)
1214 1250
1215L<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>
1216 1252
1217=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...)
1218 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.
1219L<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>
1220 1258
1221=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...)
1222 1260
1223L<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>
1330 1368
1331=for gengetinfo end command_queue 1369=for gengetinfo end command_queue
1332 1370
1333=back 1371=back
1334 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
1335=head2 THE OpenCL::Memory CLASS 1417=head2 THE OpenCL::Memory CLASS
1336 1418
1337This the superclass of all memory objects - OpenCL::Buffer, OpenCL::Image, 1419This the superclass of all memory objects - OpenCL::Buffer, OpenCL::Image,
1338OpenCL::Image2D and OpenCL::Image3D. 1420OpenCL::Image2D and OpenCL::Image3D.
1339 1421
1529If 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
1530finished. Note that many OpenCL implementations block your program while 1612finished. Note that many OpenCL implementations block your program while
1531compiling 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
1532want to make sure the build is done in the background. 1614want to make sure the build is done in the background.
1533 1615
1534Note 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
1535callback in some error cases (but call it in others). This implementation 1617callback in some error cases (but call it in others). This implementation
1536assumes 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
1537not 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.
1538 1623
1539L<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>
1540 1625
1541=item $program->build_async (\@devices = undef, $options = "", $cb->($program) = undef) 1626=item $program->build_async (\@devices = undef, $options = "", $cb->($program) = undef)
1542 1627
1877 1962
1878L<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>
1879 1964
1880=back 1965=back
1881 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 - same as C<$mapped+0>.
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 but slower than direct manipulation of
2031C<$$mapped> with substr.
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#TODO: really?
2042
2043=cut
2044
2045sub get {
2046 substr ${$_[0]}, $_[1], $_[2]
2047}
2048
2049=back
2050
2051=head2 THE OpenCL::MappedBuffer CLASS
2052
2053This is a subclass of OpenCL::Mapped, representing mapped buffers.
2054
2055=head2 THE OpenCL::MappedImage CLASS
2056
2057This is a subclass of OpenCL::Mapped, representing mapped images.
2058
2059=over 4
2060
2061=item $bytes = $mapped->row_pitch
2062
2063=item $bytes = $mapped->slice_pitch
2064
2065Return the row or slice pitch of the image that has been mapped.
2066
2067=back
2068
2069
1882=cut 2070=cut
1883 2071
18841; 20721;
1885 2073
1886=head1 AUTHOR 2074=head1 AUTHOR

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines