I am experimenting with adding image support to Mesa and am encountering 
something I don't understand with the mapping routines implemented in 
transfer.cpp, within the soft_copy_op function.

We are working on 10.1 branch of Mesa which has some tweaks to let Mesa run 
OpenCL kernels build from the AMD OpenCL driver, so my issues may very well be 
an artifact of that environment.

In any case, here is what I am seeing:

I have a simple program which generates an image of a given size, and sets each 
pixel to a value from a given starting point with a given increment value.
For example, the command "imageTest 32 32 0 1" would create a 32x32 image, in 
which pixel (0,0) would be set to 0, (0,1)=1 ... (0,31)=31, (1,0)=32 and so 
on...
The kernel takes the x,y coordinates as parameters and returns the value at 
that location.

It appears that the default soft_copy_op destination mapping does not provide a 
compatible setup for images.

Given a 32x32 image of format CL_R8, INT32, the validate_object() routines in 
clEnqueueWriteImage() calculate a destination pitch of {4,128,4096}
This results in a size of 4096 being passed to the mapping get 
(dst_pitch[2]*region[2]) this generates a staging texture of 4096x1x1 pixels.

With this, I can retrieve the values from the first row of the image, but none 
of the subsequent rows return valid values.

After some experimentation (with a 64x4 image) I discovered that there appears 
to be a minimum row pitch of 256bytes, so the 128 being passed in for the 32x32 
image didn't work properly.

I changed the clEnqueueWrite routine to adjust the destination pitches as 
follows:
dst_pitch[1]= MAX2(256,dst_pitch[1]); // row pitch
dst_pitch[2]=dst_pitch[1]*region[1];  // slice pitch

That seemed to work at first, but once I started moving to different image 
sizes, things did not work right at all...
With a 64x64 image, the subsequent rows no longer mapped properly.

After more experimentation, I seem to have found a method that will work 
reliably, with testing of images up to 2048x2048. (I can't seem to go higher 
than that, due to a memory leak I have not found yet...)

What I did, was add a different mapping get template for images:

template<>
struct _map<clover::image*> {
   static mapping
   get(command_queue &q, clover::image *img, cl_map_flags flags, size_t offset, 
size_t size) {
      return { q, img->resource(q), flags, true, {{offset}}, {{size, size, 1}} 
};
   }
}

Then, in the soft_copy_op routine, instead of passing in the slice pitch size, 
I pass in MAX2(region[0],region[1]).
I'd rather pass in the entire vector for the region, but I didn't want to 
rework the other mapping get routines in the template quite yet...

This works, as long as my images are square... but once I move to different 
dimensions (ie 32x64, 64x128) my second row of data is off again...
I'm assuming this is because of passing the largest dimension in for the 
mapping get routine, rather than the width and height....

I feel like I'm misunderstanding how these mapping routines are supposed to be 
working.
I'm also concerned that as the image sizes grow, that the use of the 'memcpy' 
will be very inefficient (as opposed to a DMA copy)

I'm hoping someone might be able to explain a bit about these mapping routines, 
and perhaps shed some light on the OpenGL image transfer routines and how they 
might be accessible from the OpenCL side.

Thanks for reading my rambling message! :)

Al Dorrington
Software Engineer Sr
Lockheed Martin, Mission Systems and Training

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to