cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

Marco13
Journeyman III

Arguments for clEnqueueReadBufferRect

Setup for copying a region from a 2D int buffer

Hello,

I'm wondering about the right setup for the clEnqueueReadBufferRect function. I tried to boil it down to a minimum test case: In the attached example, a buffer of 4x4 ints is created. Then the clEnqueueReadBufferRect should be used to copy a region with origin (0,0) and a size of 3x3 ints. However, it keeps saying "CL_INVALID_VALUE". (With a region of size 2x2 it works, but I assume that it copies only garbage then)

Can anyone give me a hint or an example how this function may be used, or tell me what's wrong with the function arguments in the example?

 

 

 

#include <cstdio> #include <cstdlib> #include <iostream> #include <CL/cl.hpp> int main() { // --->--- Initialization stuff cl_platform_id platform; clGetPlatformIDs(1, &platform, NULL); cl_context_properties contextProperties[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0 }; cl_context context = clCreateContextFromType( contextProperties, CL_DEVICE_TYPE_CPU, NULL, NULL, NULL); cl_device_id device; clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(cl_device_id), &device, NULL); cl_command_queue commandQueue = clCreateCommandQueue(context, device, 0, NULL); // ---<--- Initialization stuff // Create a buffer of 4*4 ints int sizeX = 4; int sizeY = 4; int n = sizeX * sizeY; cl_mem mem = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(int)*n, NULL, NULL); size_t bufferOffset[] = { 0, 0, 0 }; size_t hostOffset[] = { 0, 0, 0 }; // Copy a region of 3x3 int values from the buffer int regionSizeX = 3; int regionSizeY = 3; // The region size must be given in bytes size_t region[] = { regionSizeX * sizeof(int), regionSizeY * sizeof(int), 1 }; // These values are computed automatically when they are 0 size_t bufferRowPitch = 0; size_t bufferSlicePitch = 0; size_t hostRowPitch = 0; size_t hostSlicePitch = 0; int *regionData = new int[regionSizeX*regionSizeY]; int result = clEnqueueReadBufferRect( commandQueue, mem, true, bufferOffset, hostOffset, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, regionData, 0, NULL, NULL); if (result == CL_SUCCESS) { printf("Passed\n"); } else { printf("Failed\n"); } return 0; }

0 Likes
4 Replies
genaganna
Journeyman III

Originally posted by: Marco13 Hello,

 

I'm wondering about the right setup for the clEnqueueReadBufferRect function. I tried to boil it down to a minimum test case: In the attached example, a buffer of 4x4 ints is created. Then the clEnqueueReadBufferRect should be used to copy a region with origin (0,0) and a size of 3x3 ints. However, it keeps saying "CL_INVALID_VALUE". (With a region of size 2x2 it works, but I assume that it copies only garbage then)

 

Can anyone give me a hint or an example how this function may be used, or tell me what's wrong with the function arguments in the example?

 

 

bufferRowPitch and hostRowPitch are wrong and should be as follows

size_t bufferRowPitch = sizeZ * sizeof(int);

size_t hostRowPitch = regionSizeX * sizeof(int);

 

0 Likes

Hello genaganna,

Thank you for your response. Initially I tried to set these values similar to what you described

size_t bufferRowPitch = sizeX * sizeof(int); // using sizeX here

size_t hostRowPitch = regionSizeX * sizeof(int);

which should be correct to my understanding of the specification. Initially, I used an offset of (1,1,0) and a size of (2,2,1), but then I noticed that I might be tricky to get the multiplication with sizeof(int) right - excerpt from the spec:

buffer_origin: [...] The offset in bytes is computed as buffer_origin[2] * buffer_slice_pitch + buffer_origin[1] * buffer_row_pitch

So as far as I understand, the factor sizeof(int) should /either/ be applied to the buffer_origin[1], /or/ to the buffer_row_pitch, but not to both, and care has to be taken not to multiply with sizeof(int) once too often.

However, to avoid issues like this and to simplify things for the first test, I set the origin to (0,0,0), and referred to the behavior that is described in the specification, which says: When the bufferHostPitch or hostRowPitch are 0, they are computed as 'region[0]' - so I don't see what's wrong with the given code. Or did I overlook something in the release notes, stating that this behavior (computing the pitches automatically) is not supported yet?

Otherwise, I'll try to do some "black box analysis" of the function, to see if I can guess the right parameters, but would appreciate any hints that might point me in the right direction...

bye


 

0 Likes

Originally posted by: Marco13 Hello genaganna,

 

Thank you for your response. Initially I tried to set these values similar to what you described

 

size_t bufferRowPitch = sizeX * sizeof(int); // using sizeX here

 

size_t hostRowPitch = regionSizeX * sizeof(int);

 

which should be correct to my understanding of the specification. Initially, I used an offset of (1,1,0) and a size of (2,2,1), but then I noticed that I might be tricky to get the multiplication with sizeof(int) right - excerpt from the spec:

 

buffer_origin: [...] The offset in bytes is computed as buffer_origin[2] * buffer_slice_pitch + buffer_origin[1] * buffer_row_pitch
So as far as I understand, the factor sizeof(int) should /either/ be applied to the buffer_origin[1], /or/ to the buffer_row_pitch, but not to both, and care has to be taken not to multiply with sizeof(int) once too often.
However, to avoid issues like this and to simplify things for the first test, I set the origin to (0,0,0), and referred to the behavior that is described in the specification, which says: When the bufferHostPitch or hostRowPitch are 0, they are computed as 'region[0]' - so I don't see what's wrong with the given code. Or did I overlook something in the release notes, stating that this behavior (computing the pitches automatically) is not supported yet?
Otherwise, I'll try to do some "black box analysis" of the function, to see if I can guess the right parameters, but would appreciate any hints that might point me in the right direction...
bye

 

buffer_row_pitch is zero means region must be 1D.

Just replace following code with size_t region[] statement. Your code works without any problem.

size_t region[] = { regionSizeX * sizeof(int), 1, 1 };

I hope it clarifies your all doughts.

0 Likes

Hello,

Setting the region size to

size_t region[] = { regionSizeX * sizeof(int), 1, 1 };

obviously copied only the first row, but this hint (together with some more trial and error and painting of little boxes) lead me into the right direction: 'int' entries are 4 bytes wide, but only 1 byte high... (Now this seems sooo embarassing to me - it's obviously time for the weekend )

Thanks for your support!

 

 

0 Likes