Hi Andrew,
You conclusion is not the best way to do that, because you loose the
functionality of the GPUArray.
I wrote a wrapper class GPUPitchedImage which allocates an 2D array as a
GPUArray, but adaptes the shape to be correct for tex2D access later on .
Best solution would be to integrate a pitched allocation inside the GPUarray
class itself for that.
--code
class GPUPitchedImage:
#...@profile
def __init__(self,shape,pitch=None,dtype=None):
if isinstance(shape,numpy.ndarray):
im = shape;
shape = im.shape
if pitch == None:
pitch = divUp(shape[1],8)*8
if dtype == None:
dtype = im.dtype
else:
assert dtype == im.dtype
#print "generate an gpuImage based on numpy" , shape, pitch
self.shape = shape
self.pitch = pitch
if self.pitch == None:
self.pitch = divUp(self.shape[1],8)*8
self.dtype = dtype
self.gpushape= (shape[0],self.pitch)
#pitch larger than image !
assert self.shape[1] <= self.pitch
self.gpuArray = GPUArray( self.gpushape ,self.dtype )
if 'im' in locals():
self.set(im)
#get,set to be compatible with the GPUArray style
def get(self):
im = self.gpuArray.get()
return im[:,0:self.shape[1]]
def set(self,im):
""" sets the image with a numpyArray """
#generate a pitched sized ndArray
im_ = numpy.empty( self.gpushape, self.dtype )
im_[:,0:self.shape[1]] = im
self.gpuArray.set(im_)
#bind to a 2D texture -> so you can axcess with tex2D in your kernels
def bind_to_texture(self,tex):
assert (self.pitch%8) == 0 #for float types
descr = pycuda.driver.ArrayDescriptor()
descr.format = pycuda.driver.array_format.FLOAT
descr.height = self.shape[0]
descr.width = self.shape[1]
descr.num_channels = 1
tex.set_address_2d(self.gpuArray.gpudata,descr,self.pitch*4)
------------ code
Up to now only tested for float32 image types.
cu
Andrew Byrd wrote:
> On 07 Nov 2009, at 20:12, Andrew Byrd wrote:
>
>>>> Is the binding of a GPUArray to a Texture not supported, Or did I
>>>> miss something ??
>>
>> I was having the same problem, trying to pass GPUArrays' gpudata
>> into my kernels to do other processing. I think I've figured out
>> what's going on.
>>
>
> After some further experimentation, I've found out more details.
>
> You can indeed bind GPUArrays to textures, and read them with tex2D.
> The current bind_to_texref_ext() does a 1D binding, but there is a 2D
> function available. Borrowing from that original code, I was able to
> make a GPUArray.bind_to_texref_ext_2D() using an ArrayDescriptor and
> TextureReference.set_address_2d() .
>
> There are some problems in practical use. First, you have to reverse
> the order of the indices when you call tex2D. I think this is because
> GPUArrays use C ordering and CUDA uses Fortran ordering. Second, there
> are alignment restrictions on texture memory (256 bytes usually) so
> your rows need to be a multiple of 256 bytes long. You could pad the
> rows, but GPUArrays are set up to be contiguous. Third, it looks like
> you still don't get hardware interpolation/filtering.
>
> My conclusion is that in general it's better to just copy the data to
> a CUDA Array ( as is done in matrix_to_texref() ) or address it as a
> 1D array using tex1Dfetch() in device code, calculating your own
> 'flat' addresses.
>
> Thanks,
> Andrew
>
> _______________________________________________
> PyCUDA mailing list
> [email protected]
> http://tiker.net/mailman/listinfo/pycuda_tiker.net
_______________________________________________
PyCUDA mailing list
[email protected]
http://tiker.net/mailman/listinfo/pycuda_tiker.net