
#include "common.h"

// 'g' <-> global, 'd' <-> device
// global variable storing the current 3x3 filter into device constant memory
// you must use cudaMemcpyToSymbol() to copy the values into that variable
__constant__ float gd_filter[3][3];


// kernel applying a 3x3 filter to an image
__global__ void apply_3x3filter_kernel( /* TODO */)
{
  // Here, you can use gd_filter[i][j] to access to the coefficient of the filter
  /* TODO */
}


__host__ void apply_3x3filter_cuda(FloatImageGray& img, float filter[3][3], int n)
{
  // copy of the 3x3 filter values into constant device memory
  CUDA_SAFE_CALL( cudaMemcpyToSymbol(gd_filter, filter, sizeof(float)*9) );

  // Step 1 - Allocate the buffers on the device using cudaMalloc
  /* TODO */


  // Step 2 - Copy the values from the host memory to the device memory using cudaMemcpy
  /* TODO */


  // This is a timer to measure the running time.
  Timer t;
  startTimer(t);

  // Step 3 - Call the kernel using iogs_launch_kernel_2D
  // The syntax is:
  // iogs_launch_kernel_2D(name_of_the_kernel_function, nx, ny)(arg0, arg1, arg2, ...);
  /* TODO */


  // Wait until the device finished all its jobs
  stopTimer(t);

  std::cout << "CUDA time to convolution " << img.width() * img.height() << " values: " << t << "s\n";


  // Step 4 - Read back the values from the device using cudaMemcpy
  /* TODO */


  // Step 5 - Free device memory
  /* TODO */

}
