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

Reply via email to