Prefer Your Language

Search This Blog

cudaChannelFormatDesc () in CUDA | How to use cudaChannelFormatDesc in CUDA | CUDA Channels


cudaChannelFormatDesc () in CUDA | How to use cudaChannelFormatDesc in CUDA

In this article we learn how to use cudaChannelFormatDesc () in-build function in CUDA. Background of this function is very interesting [ (I can’t open that secret here ;) ].
So, if you are planning to use CUDA Array’s, then you have to be understand what is 
cudaChannelFormatDesc() function in CUDA.

So, Today I going to teach you, how to use
cudaChannelFormatDesc() function in CUDA, related to CUDA Array’s. For sake of advice, I advise you please go through this article for sake of understanding.
Let’s start our discussion;

cudaChannelFormatDesc ( )

channelDesc describes the format of the value that is returned when fetching the texture;
The cudaChannelFormatDesc describes the format of a texture element.


struct cudaChannelFormatDesc {
                                                                   int x, y, z, w;
                                                                   enum cudaChannelFormatKind  f;
                                                         }


Where,
 x, y, z, w :                      are set to the number of bits for each component, and
 f:                                       is one of the
cudaChannelFormatKindSigned (if these components are of signed integer type)
cudaChannelFormatKindUnsigned (if they are of unsigned integer type)
cudaChannelFormatKindFloat (if they are of floating point type )
Example
For float texels we could create a channel with;
              cudaCreateChannelDesc( 32, 0, 0, 0, cudaChannelFormatKindFloat );
While for short4 texels this would be
             cudaCreateChannelDesc( 16, 16, 16, 16, cudaChannelFormatKindSigned );





Before a kernel can use a texture reference to read from texture memory, the texture reference must be bound to a texture using cudaBindTexture() or cudaBindTexture2D() for linear memory, or cudaBindTextureToArray() for CUDA arrays. cudaUnbindTexture() is used to unbind a texture reference. It is recommended to allocate two-dimensional textures in linear memory using cudaMallocPitch() and use the pitch returned by cudaMallocPitch() as input parameter to cudaBindTexture2D().

The following code samples bind a texture reference to aCUDA Array’s cuArray:

Using the low-level API:

texture <float, cudaTextureType2D, cudaReadModeElementType> texRef;

textureReference* texRefPtr;

cudaGetTextureReference(&texRefPtr, "texRef");

cudaChannelFormatDesc channelDesc;

cudaGetChannelDesc(&channelDesc, cuArray);

cudaBindTextureToArray(texRef, cuArray, &channelDesc);

Using the high-level API:


texture<float, cudaTextureType2D, cudaReadModeElementType> texRef;

cudaBindTextureToArray(texRef, cuArray);

The format specified when binding a texture to a texture reference must match the parameters specified when declaring the texture reference; otherwise, the results of texture fetches are undefined.

Complete Example of CUDA Array and cudaChannelFormatDesc () 


#include "HEADER.h"
#include "ERROR.h"

// 2D float texture
texture<float, cudaTextureType2D, cudaReadModeElementType> texRef;


// Simple transformation kernel
__global__ void transformKernel(float* output, int width, int height, float theta)
{
      // Calculate normalized texture coordinates
      unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
     
      unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
     
      float u = x / (float)width;
     
      float v = y / (float)height;
     
      // Transform coordinates
      u -= 0.5f;
     
      v -= 0.5f; 
     
      float tu = u * cosf(theta) - v * sinf(theta) + 0.5f ;
     
      float tv = v * cosf(theta) + u * sinf(theta) + 0.5f ;
     
      // Read from texture and write to global memory
      output[y * width + x] = tex2D(texRef, tu, tv);
}

// Host code
int main()
{
      int width = 3 , height = 3 ;

      float h_data[3][3] ;
      for ( int i =0 ; i<3 ; i++ )
                  for ( int j = 0 ; j<3; j++ )
                              h_data [i][j] = i*j ;

      int size = width*height*sizeof(float) ;
     
      // Allocate CUDA array in device memory
      cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(32, 0, 0, 0,
                                             cudaChannelFormatKindFloat );
     
      cudaArray* cuArray;
     
      cudaMallocArray(&cuArray, &channelDesc, width, height);
     
      // Copy to device memory some data located at address h_data
      // in host memory
      cudaMemcpyToArray(cuArray, 0, 0, h_data, size, cudaMemcpyHostToDevice);
     
      // Set texture parameters
      texRef.addressMode[0] = cudaAddressModeWrap;
      texRef.addressMode[1] = cudaAddressModeWrap;
      texRef.filterMode = cudaFilterModeLinear;
      texRef.normalized = true;
     
      // Bind the array to the texture reference
      cudaBindTextureToArray(texRef, cuArray, channelDesc);
     
      // Allocate result of transformation in device memory
      float* output;
     
      cudaMalloc(&output, size );
     
      // Invoke kernel
      dim3 dimBlock(16, 16);
      dim3 dimGrid( (width + dimBlock.x - 1) / dimBlock.x,
                       (height + dimBlock.y - 1) / dimBlock.y );
     
      transformKernel<<<dimGrid, dimBlock>>>(output, width, height, 90 );
     
      printf ("\n Original array \n");
      for ( int i =0 ; i<3 ; i++ )
      {
            for ( int j = 0 ; j<3; j++ )
                              printf ("%f ", h_data [i][j] );
           
            printf ("\n");
      }

      CUDA_CALL ( cudaMemcpy (h_data , output, size, cudaMemcpyDeviceToHost ) );

      printf ("\n After operation \n ");
      for ( int i =0 ; i<3 ; i++ )
      {
            for ( int j = 0 ; j<3; j++ )
                              printf ("%f ", h_data [i][j] );
           
            printf ("\n");
      }

      system ("pause");
      // Free device memory
      cudaFreeArray(cuArray);
      cudaFree(output);
      return 0;
}


Sample output

Fig.


I hope you must like this article and have learned cudaChannelFormatDesc ( ) and how to use cudaChannelFormatDesc ( ) in CUDA.

If you want to know about Texture memory; click here

Got Questions?
Feel free to ask me any question because I'd be happy to walk you through step by step! 
Want to Contact us? Click here


4 comments:

  1. Your blog provided us with valuable information to work with. Each & every tips of your post are awesome. Thanks a lot for sharing.
    안전놀이터

    ReplyDelete
  2. We are really grateful for your blog post. You will find a lot of approaches after visiting your post. Great work!
    성인웹툰

    ReplyDelete

Help us to improve our quality and become contributor to our blog

Become a contributor to this blog. Click on contact us tab
Blogger Template by Clairvo