   int32_t c1, c2, c3;
   float plane_a,plane_b,plane_c,plane_d;
 
-
-  // CUDA copy over needed memory information
-  // disparity_grid, I1_desc,I2_desc,P,D
-  int32_t* d_disparity_grid, *d_grid_dims;
-  int32_t* d_P;
-  float* d_D;
-  uint8_t* d_I1, *d_I2;
-  //Allocate on global memory
-  cudaMalloc((void**) &d_disparity_grid, grid_dims[0]*grid_dims[1]*grid_dims[2]*sizeof(int32_t));
-  cudaMalloc((void**) &d_P, disp_num*sizeof(int32_t));
-  cudaMalloc((void**) &d_D, width*height*sizeof(float));
-  cudaMalloc((void**) &d_I1, 16*width*height*sizeof(uint8_t)); //Device descriptors
-  cudaMalloc((void**) &d_I2, 16*width*height*sizeof(uint8_t)); //Device descriptors
-  cudaMalloc((void**) &d_grid_dims, 3*sizeof(int32_t)); 
-
-  //Now copy over data
-  cudaMemcpy(d_disparity_grid, disparity_grid, grid_dims[0]*grid_dims[1]*grid_dims[2]*sizeof(int32_t), cudaMemcpyHostToDevice);
-  cudaMemcpy(d_P, P, disp_num*sizeof(int32_t), cudaMemcpyHostToDevice);
-  cudaMemcpy(d_D, D, width*height*sizeof(float), cudaMemcpyHostToDevice);
-  cudaMemcpy(d_I1, I1_desc, 16*width*height*sizeof(uint8_t), cudaMemcpyHostToDevice);
-  cudaMemcpy(d_I2, I2_desc, 16*width*height*sizeof(uint8_t), cudaMemcpyHostToDevice);
-  cudaMemcpy(d_grid_dims, grid_dims, 3*sizeof(int32_t), cudaMemcpyHostToDevice); 
+  // Size variables
+  int32_t size_total = 0;
+  int32_t size_tri = tri.size();
+
+  // Master objects that will need to be created
+  // These will be passed to the CUDA kernel
+  float* planes = new float[4*size_tri];
+  int32_t* size_uv = new int32_t[size_tri];
+  int32_t** vals_u = new *int32_t[size_tri];
+  int32_t** vals_v = new *int32_t[size_tri];
+
 
   // for all triangles do
   for (uint32_t i=0; i<tri.size(); i++) {

  uint32_t idx = blockDim.x*blockIdx.x + threadIdx.x;

  // Check that we are in range
  if(idx >= size_vals)
    return;

  // Else get our value
  uint32_t u = u_vals[idx];
  uint32_t v = v_vals[idx];

  // address of disparity we want to compute
  uint32_t d_addr;

          int32_t v_2 = (uint32_t)(BC_a*(float)u+BC_b);
          for (int32_t v=min(v_1,v_2); v<max(v_1,v_2); v++)
            if (!param.subsampling || v%2==0) {
              temp_val_u.push_back(u);
              temp_val_v.push_back(v);
            }
        }
      }
    }

    // Append our planes to our vector
    planes[4*i + 0] = plane_a;
    planes[4*i + 1] = plane_b;
    planes[4*i + 2] = plane_c;
    planes[4*i + 3] = plane_d;

    // Update our total and local size variable
    size_uv[i] = temp_val_u.size();
    size_total += temp_val_u.size();

    int32_t* t_vals_u = new int32_t[temp_val_u.size()];
    int32_t* t_vals_v = new int32_t[temp_val_u.size()];

    // Append to our master u,v vector
    for(size_t j=0; j<temp_val_u.size(); j++) {
      vals_u[j] = temp_val_u.at(j)
      vals_v[j] = temp_val_v.at(j)
    }

    // Set pointer in main array
    vals_u[i] = &t_vals_u;
    vals_v[i] = &t_vals_v;

  }

  // Calculate size of kernel
  int block_size = 32;
  int grid_size = 0;

  //Calculate grid_size (add 1 if not evenly divided)
  if(to_calc.size()%block_size == 0) {
      grid_size = ceil(size_total/block_size);
  } else {
      grid_size = ceil(size_total/block_size) + 1;
  }

  dim3 DimGrid(grid_size,1,1);
  dim3 DimBlock(block_size,1,1);


  // Allocate pointer array
  int32_t** d_u_vals, **d_v_vals;
  cudaMalloc(d_u_vals, size_tri*sizeof(int32_t*));
  cudaMalloc(d_v_vals, size_tri*sizeof(int32_t*));

  // Copy over pointer array
  cudaMemcpy(d_u_vals, vals_u, size_tri * sizeof(int32_t*), cudaMemcpyHostToDevice);
  cudaMemcpy(d_v_vals, vals_v, size_tri * sizeof(int32_t*), cudaMemcpyHostToDevice);


  // Allocate device arrays
  for(int i = 0; i < size_tri; i++){
    cudaMalloc(&vals_u[i], size_uv[i]*sizeof(int32_t));
    cudaMalloc(&vals_v[i], size_uv[i]*sizeof(int32_t));
  }

  // Copy over arrays
  for(int i = 0; i < size_tri; i++){
    cudaMemcpy(d_u_vals[i], vals_u[i], size_uv[i] * sizeof(int32_t), cudaMemcpyHostToDevice);
    cudaMemcpy(d_v_vals[i], vals_v[i], size_uv[i] * sizeof(int32_t), cudaMemcpyHostToDevice);
  }

  // Create array that maps our u,v cords to a triangle
  int32_t* tri_idx = new int32_t[size_total];
  int count = 0;
  for(int i = 0; i < size_tri; i++) {
    for(int j=0; j<size_uv[i]; j++) {
      tri_idx[count] = i;
      count++;
    }
  }  

  // Allocate and copy over our triangle array
  int32_t* d_tri_idx;
  cudaMalloc(d_tri_idx, size_total*sizeof(int32_t));
  cudaMemcpy(d_tri_idx, tri_idx, num_arrays * sizeof(float*), cudaMemcpyHostToDevice);

  // Copy over the plane values
  float* d_planes;
  cudaMalloc(d_planes, 4*size_tri*sizeof(float));
  cudaMemcpy(d_planes, planes, 4*size_tri*sizeof(float), cudaMemcpyHostToDevice);
  
  // Copy over size values
  int32_t* d_size_uv;
  cudaMalloc(d_size_uv, size_tri*sizeof(int32_t));
  cudaMemcpy(d_size_uv, size_uv, size_tri*sizeof(int32_t), cudaMemcpyHostToDevice);

  // CUDA copy over needed memory information
  // disparity_grid, I1_desc,I2_desc,P,D
  int32_t* d_disparity_grid, *d_grid_dims;
  int32_t* d_P;
  float* d_D;
  uint8_t* d_I1, *d_I2;

  // Allocate on global memory
  cudaMalloc((void**) &d_disparity_grid, grid_dims[0]*grid_dims[1]*grid_dims[2]*sizeof(int32_t));
  cudaMalloc((void**) &d_P, disp_num*sizeof(int32_t));
  cudaMalloc((void**) &d_D, width*height*sizeof(float));
  cudaMalloc((void**) &d_I1, 16*width*height*sizeof(uint8_t)); //Device descriptors
  cudaMalloc((void**) &d_I2, 16*width*height*sizeof(uint8_t)); //Device descriptors
  cudaMalloc((void**) &d_grid_dims, 3*sizeof(int32_t)); 

  // Now copy over data
  cudaMemcpy(d_disparity_grid, disparity_grid, grid_dims[0]*grid_dims[1]*grid_dims[2]*sizeof(int32_t), cudaMemcpyHostToDevice);
  cudaMemcpy(d_P, P, disp_num*sizeof(int32_t), cudaMemcpyHostToDevice);
  cudaMemcpy(d_D, D, width*height*sizeof(float), cudaMemcpyHostToDevice);
  cudaMemcpy(d_I1, I1_desc, 16*width*height*sizeof(uint8_t), cudaMemcpyHostToDevice);
  cudaMemcpy(d_I2, I2_desc, 16*width*height*sizeof(uint8_t), cudaMemcpyHostToDevice);
  cudaMemcpy(d_grid_dims, grid_dims, 3*sizeof(int32_t), cudaMemcpyHostToDevice);

  // Launch the kernel
  findMatch_GPU<<<DimGrid, DimBlock>>>(d_tri_idx, d_u_vals,d_v_vals,d_size_uv, d_planes, d_disparity_grid, d_grid_dims,
                                        d_I1,d_I2,d_P,plane_radius,width,height,valid,right_image,d_D);
    
  // Sync after the kernel is launched
  cudaDeviceSynchronize();

  // Copy the final disparity values back over
  cudaMemcpy(disparity_grid, d_disparity_grid, grid_dims[0]*grid_dims[1]*grid_dims[2]*sizeof(int32_t), cudaMemcpyDeviceToHost);
  cudaMemcpy(D, d_D, width*height*sizeof(float), cudaMemcpyDeviceToHost);
  
  // Free local memory
  delete[] P;

  // Free cuda memory
  cudaFree(d_disparity_grid);
