What do rowpitch and slicepitch mean?

Help
Jeff Adams
2010-05-03
2012-12-21
  • Jeff Adams

    Jeff Adams - 2010-05-03

    I want to write data from an array of ints (or floats) to a ComputeImage2D, but I'm not certain what all the parameters are expecting.

    Can you give me a simple example:

    public WriteToImage(ComputeCommandQueue queue, int fromHere, ComputeImage2D toHere, int imageStartX, int imageStartY, int fromOffset, int numIntsToCopy) {
        queue.Write(something, something, something, something);
    }

     
  • nythrix

    nythrix - 2010-05-03

    They have the same meaning as in here: http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateImage3D.html
    The same explanation, albeit shorter, should pop up in IntelliSense.

    Posting the example. Copy paste it in an editor and it should be clear what it does:

            public void WriteToImage(ComputeCommandQueue queue, int fromHere, ComputeImage2D toHere, int imageStartX, int imageStartY, int fromOffset, int numIntsToCopy)
            {
                unsafe
                {
                    GCHandle gch = GCHandle.Alloc(fromHere, GCHandleType.Pinned);
                    IntPtr fromHerePtr = Marshal.UnsafeAddrOfPinnedArrayElement(fromHere, fromOffset);
                    // need to specify written image area (sizeX and sizeY) instead of numIntsToCopy argument
                    long sizeXYZ = new long{ sizeX, sizeY, 1};
                    queue.Write(toHere, true, new long { imageStartX, imageStartY, 0 }, sizeXYZ, fromHerePtr, null);
                    gch.Free();
                }
            }

    Cloo 0.8.x will bring more comfy overloads that help with code like this. Right after my exams that is :)

     
  • Jeff Adams

    Jeff Adams - 2010-05-04

    So if I understand correctly, the rowpitch is how wide the original image was, and slicepitch is how (wide * tall) it is?

    So if my original image is this:

    BBBBBBBB
    BBBBBBBB
    BBAAAABB
    BBAAAABB
    BBAAAABB
    BBAAAABB
    BBBBBBBB
    BBBBBBBB

    And I'm writing the A's, I would call:

    queue.Write(toHere, true, new long { 2, 2, 0 }, new long { 4, 4, 1 }, 8, 64, fromHerePtr, null);

    Rowpitch would be 8 (width of the original row) and slicepitch would be 64 (2-dimensional size of the image).  That's in bytes according to the API so assume this is a byte array in the example ;-).

    I'm using the Write signature that takes the rowpitch and slicepitch.

    Does Write require 3 longs for start and size even for Image2Ds?  Or can I pass just two?

     
  • Jeff Adams

    Jeff Adams - 2010-05-04

    Good luck on your exams by the way :-).  Are you located anywhere near Philadelphia?

     
  • Jeff Adams

    Jeff Adams - 2010-05-04

    OK I think I'm still confused.

    I want to create a 10x10 ComputeImage2D.  So I'm calling:

    new ComputeImage2D(
    _context,
    ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.AllocateHostPointer, // I'm letting OpenCL allocate the memory.
    new ComputeImageFormat(ComputeImageChannelOrder.R, ComputeImageChannelType.Float), // Only using a single channel.
    10, // width
    10, // height
    10 * Marshal.SizeOf(typeof(float)), // rowpitch

    IntPtr.Zero) // Pass zero when using AllocateHostPointer

    But it's throwing

    Cloo.InvalidImageSizeComputeException: Error in the application.
    at Cloo.ComputeException.ThrowOnError(ComputeErrorCode error)
    at Cloo.ComputeImage2D..ctor(ComputeContext context, ComputeMemoryFlags flags, ComputeImageFormat format, Int32 width, Int32 height, Int64 rowPitch, IntPtr data)
    at my code

    What am I doing wrong?

     
  • nythrix

    nythrix - 2010-05-04

    Thing is you have to specify rowPitch = 0 if you're not passing in any data (last argument is IntPtr.Zero) as in your case(*). I found out that leaving rowPitch and slicePitch be (=0) is the safest bet. Setting them to 0 will have OpenCL compute them for you. Otherwise you might be surprised. Like for example, I bet you wouldn't expect ComputeImage2D has SlicePitch = 0…
    Row/slice pitch is usually used when the image is carrying additional non-renderable data. Setting these values to a larger value than the row/slice size tells OpenCL to jump over "tails":
    DDDDDDD
    PPPPPDD
    PPPPPDD
    PPPPPDD
    PPPPPDD
    P - pixel, D - other stuff

    Does Write require 3 longs for start and size even for Image2Ds? Or can I pass just two?
    Regardless of the image type, three values are requested.

    Good luck on your exams by the way :-). Are you located anywhere near Philadelphia?
    Thanks. I'll need that :)
    No thats a bit out of my range. I'm a lucky participant in this byrocratic mashup we call the EU…

     
  • nythrix

    nythrix - 2010-05-04

    (*) Note to self: The API docs don't contain this and probably other vital facts. FIX IT!

     
  • Jeff Adams

    Jeff Adams - 2010-05-04

    (*) Even better in addition to updating the API docs, would be having the method throw an exception that says that. "Hey doofus you passed IntPtr.Zero, so you have to pass zero for rowslice also".  Or just internally ignoring rowslice and not passing it on to the OpenCL call in that case.

    Ah well I guess we won't be going out for a beer after your exams :-).

    Hrmph, now it's giving me an InvalidMemoryObjectComputeException, when calling SetMemoryArgument.

     
  • nythrix

    nythrix - 2010-05-04

    Of course! Now I see what you meant by enhancing those exception messages. I reopened your feature request with additional info. It's a rather large amount of work but it can be done. Also I have to check the OpenCL Specification license since this will require redistributing the majority of its text with Cloo.

    Some of these errors won't help much though. For example:
    CL_INVALID_MEM_ OBJECT (= InvalidMemoryObjectComputeException): an argument declared to be a memory object when the specified argument is not a valid memory object.

     
  • Jeff Adams

    Jeff Adams - 2010-05-04

    Any idea why it wouldn't be valid?  I'm creating it as above (except with 0 for the rowslice), which then if I look at it right before this call everything seems correct about it (rowslice is calculated as 40, which sounds correct).

     
  • nythrix

    nythrix - 2010-05-04

    I can't reproduce it. I tried setting this very same image type as a kernel arg and it worked. Check your kernel signature.

    I got an InvalidArgumentIndex by simply forgetting a "read_only" specifier. In this case verbose messages will point you the wrong way. Unfortunately, this is out of my reach :/

     
  • Jeff Adams

    Jeff Adams - 2010-05-05

    Yeah it was my kernel.  I have two kernels to do the same operation, one with normal buffers (arrays) and one with image types, to see what the difference is performance-wise.  I was calling the array kernel with image params… cut-n-paste mistake.

    However now the "Write" call gives me an InvalidValueComputeException!  I'm on a mission to find out every single possible step where I can do something wrong.  Time to take a close look at those parameters…

     
  • Jeff Adams

    Jeff Adams - 2010-05-05

    Victory!

    Well, I mean, it produces wrong results, but I'm reading and writing image2d_ts :-).

    I was passing a real value for slicepitch when writing (and also reading), but as you commented back on comment 6: "I bet you wouldn't expect ComputeImage2D has SlicePitch = 0…"

    Changing to 0 made read and write work.  That's another place where a better exception message ("You passed a non-zero slicepitch with a ComputeImage2D!") would be handy.

    Now to go make it actually produce correct results.

     

Log in to post a comment.