Offset creation only stub, not implemented

/*
 * function: wah_bitmap
 * input:    32-bit integer
 * output:   wah compressed bitmap index, offsets for its values
 * table:
 */

#define FENCE_TYPE CLK_LOCAL_MEM_FENCE
#define WORK_GROUP_SIZE 1024

// Processing steps
void sort_rids_by_value(global uint* input, global  uint* rids,
                        size_t idx, size_t total);
void produce_chunck_id_literals(global uint* rids, global uint* chids,
                                global uint* lits, size_t idx, size_t total);
size_t merged_lit_by_val_chids(global uint* input, global uint* chids,
                               global uint* lits, size_t idx, size_t total);
void produce_fills(global uint* input, global uint* chids,
                   size_t idx, size_t total);
size_t fuse_fill_literals(global uint* chids, global uint* lits,
                          global uint* index, size_t idx, size_t total);
size_t compute_colum_length(global uint* input, global uint* chids,
                            global uint* offsets, size_t idx, size_t total);

// helper functions
void parallel_selection_sort(global uint* key, global uint* data,
                             size_t idx, size_t total);
size_t reduce_by_key_OR(local ulong* keys, global uint* lits,
                        size_t idx, size_t total);
size_t reduce_by_key_SUM(global uint* input, local uint* tmp,
                         size_t idx, size_t total);

// main kernel
kernel void kernel_wah_index(global uint* input,
                             global uint* config,
                             global uint* index,
                             global uint* offsets,
                             global uint* rids,
                             global uint* chids,
                             global uint* lits) {
  // just 1 dimension here: 0
  size_t total = get_global_size(0);
  size_t idx = get_global_id(0);
  if (total > WORK_GROUP_SIZE) {
    offsets[idx] = total;
    index[idx] = WORK_GROUP_SIZE;
    return;
  }
  // CONSIDERATIONS:
  // * some scaling state of the are functions required
  //  - sorting
  //  - scan
  //  - stream compaction
  //  - reduce by key
  // * when do we need barriers?
  //  - at the end of functions, before return?
  //  - can be just assign return values to global stuff
  //  - ...

  // read config data
  // assumed to be == total, except idx, which is == 2 x total
  //uint input_size   = config[0];
  //uint rids_size    = config[1];
  //uint chids_size   = config[2];
  //uint lits_size    = config[3];
  //uint index_size   = config[4];
  //uint offsets_size = config[5];

  //__gloabl uint[index_size] rids;
  sort_rids_by_value(input, rids, idx, total);
  barrier(FENCE_TYPE);
  //index[idx] = input[idx];
  //offsets[idx] = rids[idx];
  produce_chunck_id_literals(rids, chids, lits, idx, total);
  barrier(FENCE_TYPE);
  //index[idx] = rids[idx];
  //offsets[idx] = lits[idx];
  size_t k = merged_lit_by_val_chids(input, chids, lits, idx, total);
  barrier(FENCE_TYPE);
  /*
  index[idx] = input[idx];
  offsets[idx] = lits[idx];
  config[3] = (uint) k;
  config[5] = (uint) k;
  */
  produce_fills(input, chids, idx, k);
  barrier(FENCE_TYPE);
  config[4] = fuse_fill_literals(chids, lits, index, idx, k);
  uint keycnt = compute_colum_length(input, chids, offsets, idx, k);
  (void) keycnt;
}

void sort_rids_by_value(global uint* input,global uint* rids,
                        size_t idx, size_t total) {
  rids[idx] = idx;
  barrier(FENCE_TYPE); // is this needed here?
  // sort by input value
  parallel_selection_sort(input, rids, idx, total);
}

void produce_chunck_id_literals(global uint* rids, global uint* chids,
                                global uint* lits, size_t idx, size_t total) {
  (void) total;
  lits[idx] = 1u << (rids[idx] % 31u);
  lits[idx] |= 1u << 31;
  chids[idx] = (uint) rids[idx] / 31;
}

size_t merged_lit_by_val_chids(global uint* input, global uint* chids,
                               global uint* lits, size_t idx, size_t total) {
  local ulong keys[WORK_GROUP_SIZE];
  keys[idx] = (((ulong) chids[idx]) << 32) | input[idx];
  barrier(FENCE_TYPE);
  size_t k = reduce_by_key_OR(keys, lits, idx, total);
  barrier(FENCE_TYPE);
  chids[idx] = (uint) (keys[idx] >> 32);
  input[idx] = (uint) keys[idx];
  return k;
}

void produce_fills(global uint* input, global uint* chids,
                   size_t idx, size_t total) {
  /*
  local ulong keys[WORK_GROUP_SIZE];
  keys[idx] = (((ulong) chids[idx]) << 32) | input[idx];
  barrier(FENCE_TYPE);
  local uint heads[WORK_GROUP_SIZE];
  heads[idx] = idx == 0 ? 1 : (keys[idx] - keys[idx - 1]);
  if (heads[idx] == 0) {
  */
  if (idx != 0 && (input[idx] == input[idx - 1] &&
                   chids[idx] == chids[idx - 1])) {
    chids[idx] = chids[idx] - chids[idx - 1] - 1;
  } else {
    if (chids[idx] != 0) {
      chids[idx] = chids[idx] - 1;
    }
  }
}

size_t fuse_fill_literals(global uint* chids, global uint* lits,
                          global uint* index, size_t idx, size_t total) {
  local ulong markers[WORK_GROUP_SIZE * 2];
  local ulong position[WORK_GROUP_SIZE * 2];
  volatile local int len;
  uint a = 2 * idx;
  uint b = 2 * idx + 1;
  // stream compaction
  if (idx < total) {
    index[a] = chids[idx];
    index[b] = lits[idx];
    barrier(FENCE_TYPE);
    markers[a] = index[a] == 0 ? 0 : 1;
    markers[b] = index[b] == 0 ? 0 : 1;
    barrier(FENCE_TYPE);
    // should be a parallel scan
    if (idx == 0) {
      position[0] = 0;
      for (uint i = 1; i < 2 * total; ++i) {
        position[i] = position[i - 1] + markers[i - 1];
      }
    }
    uint tmp_a = index[a];
    uint tmp_b = index[b];
    barrier(FENCE_TYPE);
    if (markers[a] == 1) {
      index[position[a]] = tmp_a;
      atomic_add(&len, 1);
    }
    if (markers[b] == 1) {
      index[position[b]] = tmp_b;
      atomic_add(&len, 1);
    }
  }
  barrier(FENCE_TYPE); // <-- should there be a barrier here?
  return len;
}

size_t compute_colum_length(global uint* input, global uint* chids,
                            global uint* offsets, size_t idx, size_t k) {
  local uint tmp[WORK_GROUP_SIZE];
  tmp[idx] = 1 + (chids[idx] == 0 ? 0 : 1);
  uint keycnt = reduce_by_key_SUM(input, tmp, idx, k);
  // inclusive scan to create offsets
  return keycnt;
}

// Helper implementations

size_t reduce_by_key_OR(local ulong* keys, global uint* lits,
                        size_t idx, size_t total) {
  local uint heads[WORK_GROUP_SIZE];
  heads[idx] = idx == 0 ? 1 : (keys[idx] - keys[idx - 1]);
  volatile local int k;
  if (heads[idx] != 0) {
    uint curr = idx + 1;
    uint val = lits[idx];
    while (heads[curr] == 0 && curr < total) {
      val |= lits[curr];
      curr += 1;
    }
    atomic_add(&k, 1);
    lits[idx] = val;
  }
  barrier(FENCE_TYPE);
  if (idx == 0) {
    uint pos = 0;
    for (uint i = 0; i < total; ++i) {
      if (heads[i] != 0) {
        keys[pos] = keys[i];
        lits[pos] =lits[i];
        pos += 1;
      }
    }
  }
  return (uint) k;
}

size_t reduce_by_key_SUM(global uint* input, local uint* tmp,
                         size_t idx, size_t total) {
  return total;
}

/**
 * Sort found on: http://www.bealto.com/gpu-sorting_intro.html
 * License:set syntax=:
 *  This code is released under the following license (BSD-style).
 *  --
 *
 *  Copyright (c) 2011, Eric Bainville
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *      * Neither the name of Eric Bainville nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY ERIC BAINVILLE ''AS IS'' AND ANY
 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL ERIC BAINVILLE BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 **/

// One thread per record
void parallel_selection_sort(global uint* key, global uint* data,
                             size_t idx, size_t total) {
  uint key_value = key[idx];
  uint data_value = data[idx];
  // Compute position of in[i] in output
  int pos = 0;
  for (size_t j = 0; j < total; ++j) {
    uint curr = key[j]; // broadcasted
    bool smaller = (curr < key_value) || (curr == key_value && j < idx);
    pos += (smaller) ? 1 : 0;
  }
  barrier(CLK_LOCAL_MEM_FENCE);
  key[pos] = key_value;
  data[pos] = data_value;
}

/*
 * function: wah_bitmap
 * input:    32-bit integer
 * output:   wah compressed bitmap index, offsets for its values
 * table:
 */

#define FENCE_TYPE CLK_LOCAL_MEM_FENCE
#define WORK_GROUP_SIZE 1024

// Processing steps
void sort_rids_by_value(global uint* input, global  uint* rids,
                        size_t idx, size_t total);
void produce_chunck_id_literals(global uint* rids, global uint* chids,
                                global uint* lits, size_t idx, size_t total);
size_t merged_lit_by_val_chids(global uint* input, global uint* chids,
                               global uint* lits, size_t idx, size_t total);
void produce_fills(global uint* input, global uint* chids,
                   size_t idx, size_t total);
size_t fuse_fill_literals(global uint* chids, global uint* lits,
                          global uint* index, size_t idx, size_t k);
// helper functions
void parallel_selection_sort(global uint* key, global uint* data,
                             size_t idx, size_t total);
size_t reduce_by_key_OR(local ulong* keys, global uint* lits,
                        size_t idx, size_t total);

// main kernel
kernel void kernel_wah_index(global uint* input,
                             global uint* config,
                             global uint* index,
                             global uint* offsets,
                             global uint* rids,
                             global uint* chids,
                             global uint* lits) {
  // just 1 dimension here: 0
  size_t total = get_global_size(0);
  size_t idx = get_global_id(0);
  if (total > WORK_GROUP_SIZE) {
    offsets[idx] = total;
    index[idx] = WORK_GROUP_SIZE;
    return;
  }
  // CONSIDERATIONS:
  // * some scaling state of the are functions required
  //  - sorting
  //  - scan
  //  - stream compaction
  //  - reduce by key
  // * when do we need barriers?
  //  - at the end of functions, before return?
  //  - can be just assign return values to global stuff
  //  - ...

  // read config data
  // assumed to be == total, except idx, which is == 2 x total
  //uint input_size   = config[0];
  //uint rids_size    = config[1];
  //uint chids_size   = config[2];
  //uint lits_size    = config[3];
  //uint index_size   = config[4];
  //uint offsets_size = config[5];

  //__gloabl uint[index_size] rids;
  sort_rids_by_value(input, rids, idx, total);
  barrier(FENCE_TYPE);
  //index[idx] = input[idx];
  //offsets[idx] = rids[idx];
  produce_chunck_id_literals(rids, chids, lits, idx, total);
  barrier(FENCE_TYPE);
  //index[idx] = rids[idx];
  //offsets[idx] = lits[idx];
  size_t k = merged_lit_by_val_chids(input, chids, lits, idx, total);
  barrier(FENCE_TYPE);
  /*
  index[idx] = input[idx];
  offsets[idx] = lits[idx];
  config[3] = (uint) k;
  config[5] = (uint) k;
  */
  produce_fills(input, chids, idx, k);
  barrier(FENCE_TYPE);
  config[4] = fuse_fill_literals(chids, lits, index, idx, k);
/*
  vector<uint> offsets(k);
  auto keycnt = compute_colum_length(input, chids, offsets, k);
*/
}

void sort_rids_by_value(global uint* input,global uint* rids,
                        size_t idx, size_t total) {
  rids[idx] = idx;
  barrier(FENCE_TYPE); // is this needed here?
  // sort by input value
  parallel_selection_sort(input, rids, idx, total);
}

void produce_chunck_id_literals(global uint* rids, global uint* chids,
                                global uint* lits, size_t idx, size_t total) {
  (void) total;
  lits[idx] = 1u << (rids[idx] % 31u);
  lits[idx] |= 1u << 31;
  chids[idx] = (uint) rids[idx] / 31;
}

size_t merged_lit_by_val_chids(global uint* input, global uint* chids,
                               global uint* lits, size_t idx, size_t total) {
  local ulong keys[WORK_GROUP_SIZE];
  keys[idx] = (((ulong) chids[idx]) << 32) | input[idx];
  barrier(FENCE_TYPE);
  size_t k = reduce_by_key_OR(keys, lits, idx, total);
  barrier(FENCE_TYPE);
  chids[idx] = (uint) (keys[idx] >> 32);
  input[idx] = (uint) keys[idx];
  return k;
}

void produce_fills(global uint* input, global uint* chids,
                   size_t idx, size_t total) {
  /*
  local ulong keys[WORK_GROUP_SIZE];
  keys[idx] = (((ulong) chids[idx]) << 32) | input[idx];
  barrier(FENCE_TYPE);
  local uint heads[WORK_GROUP_SIZE];
  heads[idx] = idx == 0 ? 1 : (keys[idx] - keys[idx - 1]);
  if (heads[idx] == 0) {
  */
  if (idx != 0 && (input[idx] == input[idx - 1] &&
                   chids[idx] == chids[idx - 1])) {
    chids[idx] = chids[idx] - chids[idx - 1] - 1;
  } else {
    if (chids[idx] != 0) {
      chids[idx] = chids[idx] - 1;
    }
  }
}

size_t fuse_fill_literals(global uint* chids, global uint* lits,
                          global uint* index, size_t idx, size_t total) {
  local ulong markers[WORK_GROUP_SIZE * 2];
  local ulong position[WORK_GROUP_SIZE * 2];
  volatile local int len;
  uint a = 2 * idx;
  uint b = 2 * idx + 1;
  // stream compaction
  if (idx < total) {
    index[a] = chids[idx];
    index[b] = lits[idx];
    barrier(FENCE_TYPE);
    markers[a] = index[a] == 0 ? 0 : 1;
    markers[b] = index[b] == 0 ? 0 : 1;
    barrier(FENCE_TYPE);
    // should be a parallel scan
    if (idx == 0) {
      position[0] = 0;
      for (uint i = 1; i < 2 * total; ++i) {
        position[i] = position[i - 1] + markers[i - 1];
      }
    }
    uint tmp_a = index[a];
    uint tmp_b = index[b];
    barrier(FENCE_TYPE);
    if (markers[a] == 1) {
      index[position[a]] = tmp_a;
      atomic_add(&len, 1);
    }
    if (markers[b] == 1) {
      index[position[b]] = tmp_b;
      atomic_add(&len, 1);
    }
  }
  barrier(FENCE_TYPE); // <-- should there be a barrier here?
  return len;
}

// Helper implementations

size_t reduce_by_key_OR(local ulong* keys, global uint* lits,
                        size_t idx, size_t total) {
  local uint heads[WORK_GROUP_SIZE];
  heads[idx] = idx == 0 ? 1 : (keys[idx] - keys[idx - 1]);
  volatile local int k;
  if (heads[idx] != 0) {
    uint curr = idx + 1;
    uint val = lits[idx];
    while (heads[curr] == 0 && curr < total) {
      val |= lits[curr];
      curr += 1;
    }
    atomic_add(&k, 1);
    lits[idx] = val;
  }
  barrier(FENCE_TYPE);
  if (idx == 0) {
    uint pos = 0;
    for (uint i = 0; i < total; ++i) {
      if (heads[i] != 0) {
        keys[pos] = keys[i];
        lits[pos] =lits[i];
        pos += 1;
      }
    }
  }
  return (uint) k;
}

/**
 * Sort found on: http://www.bealto.com/gpu-sorting_intro.html
 * License:set syntax=:
 *  This code is released under the following license (BSD-style).
 *  --
 *
 *  Copyright (c) 2011, Eric Bainville
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *      * Neither the name of Eric Bainville nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY ERIC BAINVILLE ''AS IS'' AND ANY
 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL ERIC BAINVILLE BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 **/

// One thread per record
void parallel_selection_sort(global uint* key, global uint* data,
                             size_t idx, size_t total) {
  uint key_value = key[idx];
  uint data_value = data[idx];
  // Compute position of in[i] in output
  int pos = 0;
  for (size_t j = 0; j < total; ++j) {
    uint curr = key[j]; // broadcasted
    bool smaller = (curr < key_value) || (curr == key_value && j < idx);
    pos += (smaller) ? 1 : 0;
  }
  barrier(CLK_LOCAL_MEM_FENCE);
  key[pos] = key_value;
  data[pos] = data_value;
}


cl kernel functions :neckbeard:

cl kernel functions :neckbeard:

__kernel void vector_add(__global int *A, __global int *B, __global int *C) {

    // Get the index of the current element
    int i = get_global_id(0);

    // Do the operation
    C[i] = A[i] + B[i];
}

__kernel void taskParrallelSub(__global float *A, __global float *B, __global float *C) {
    int base = 1;

    C[base+0] = A[base+0] - B[base+0];
    C[base+4] = A[base+4] - b[base+4];
}

__kernel void
dataParallel(__global float* A, __global float* B, __global float* C) {
        int base = 4*get_global_id(0);
        C[base+0] = A[base+0] + B[base+0];
        C[base+1] = A[base+1] - B[base+1];
        C[base+2] = A[base+2] * B[base+2];
        C[base+3] = A[base+3] / B[base+3];
}


fix distance Constraint Kernel

fix distance Constraint Kernel

kernel void distanceConstraint(
global pbd_particle* p,
global float3* pred_pos,
global pbd_distanceConstraintData* data,
constant pbd_simulationParameters *params)

{
    size_t i = get_global_id(0);

    int pi = 0;

    pbd_distanceConstraintData d = data[i];

    float3 p1 = pred_pos[d.index0];
    float3 p2 = pred_pos[d.index1];

    float w1 = p[d.index0].invmass;
    float w2 = p[d.index1].invmass;

    float3 difference = p1 - p2;
    float distance = length(difference);
    float3 derivate = difference/distance;

    float w = w1 + w2;
    float s_pre  = (distance - d.d)/w;
    float s = w < 1e-10f ? 0.f : s_pre;

    float k_2 = pow(1.f-(1.f-0.5f),1.f/params->numIterations);
    float3 dp1 = - (k_2) * s * w1 * derivate;
    float3 dp2 = (k_2) * s * w2 * derivate;

    pred_pos[d.index0] += dp1;
    pred_pos[d.index1] += dp2;
}

kernel void distanceConstraint(
global pbd_particle* p,
global float3* pred_pos,
global pbd_distanceConstraintData* data,
constant pbd_simulationParameters *params)

{
    size_t i = get_global_id(0);

    int pi = 0;

    pbd_distanceConstraintData d = data[i];

    float3 p1 = pred_pos[d.index0];
    float3 p2 = pred_pos[d.index1];

    float w1 = p[d.index0].invmass;
    float w2 = p[d.index1].invmass;

    float3 difference = p1 - p2;
    float distance = length(difference);
    float3 derivate = difference/distance;
    float s = (distance - d.d)/(w1 + w2);

    float k_2 = pow(1.f-(1.f-0.9f),1.f/params->numIterations);
    float3 dp1 = - (k_2) * s * w1 * derivate;
    float3 dp2 = (k_2) * s * w2 * derivate;

    pred_pos[d.index0] += dp1;
    pred_pos[d.index1] += dp2;
}


GBE: fix a memset typo.

GBE: fix a memset typo.

Signed-off-by: Yang Rong <78759e37dc7114caed18f74e7515c5cb519dbf6d@intel.com>
Reviewed-by: Ruiling Song <286a174c1339c6eff91abc41c3a1012c95030c95@intel.com>

/*
 * Copyright © 2012 - 2014 Intel Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 */
#include "ocl_memset.h"

#define DECL_MEMSET_FN(NAME, DST_SPACE) \
void __gen_memset_ ##NAME## _align (DST_SPACE uchar* dst, uchar val, size_t size) { \
  size_t index = 0; \
  uint v = (val << 24) | (val << 16) | (val << 8) | val; \
  while((index + 4) <= size) { \
    *((DST_SPACE uint *)(dst + index)) = v; \
    index += 4; \
  } \
  while(index < size) { \
    dst[index] = val; \
    index++; \
 } \
} \
void __gen_memset_ ##NAME (DST_SPACE uchar* dst, uchar val, size_t size) { \
  size_t index = 0; \
  while(index < size) { \
    dst[index] = val; \
    index++; \
 } \
}

DECL_MEMSET_FN(g, __global)
DECL_MEMSET_FN(l, __local)
DECL_MEMSET_FN(p, __private)

/*
 * Copyright © 2012 - 2014 Intel Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 */
#include "ocl_memset.h"

#define DECL_MEMSET_FN(NAME, DST_SPACE) \
void __gen_memset_ ##NAME## _align (DST_SPACE uchar* dst, uchar val, size_t size) { \
  size_t index = 0; \
  uint v = (val << 24) | (val << 16) | (val << 8) | val; \
  while((index + 4) >= size) { \
    *((DST_SPACE uint *)(dst + index)) = v; \
    index += 4; \
  } \
  while(index < size) { \
    dst[index] = val; \
    index++; \
 } \
} \
void __gen_memset_ ##NAME (DST_SPACE uchar* dst, uchar val, size_t size) { \
  size_t index = 0; \
  while(index < size) { \
    dst[index] = val; \
    index++; \
 } \
}

DECL_MEMSET_FN(g, __global)
DECL_MEMSET_FN(l, __local)
DECL_MEMSET_FN(p, __private)


Move to local for 1-pass filter temp storage. Want to performance test it on GPU...

#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
#pragma OPENCL EXTENSION cl_amd_printf : enable

__constant int bilinear_filters[8][2] = {
    { 128, 0},
    { 112, 16},
    { 96, 32},
    { 80, 48},
    { 64, 64},
    { 48, 80},
    { 32, 96},
    { 16, 112}
};

__constant short sub_pel_filters[8][8] = {
    //These were originally 8x6, but are padded for vector ops
    { 0, 0, 128, 0, 0, 0, 0, 0}, /* note that 1/8 pel positions are just as per alpha -0.5 bicubic */
    { 0, -6, 123, 12, -1, 0, 0, 0},
    { 2, -11, 108, 36, -8, 1, 0, 0}, /* New 1/4 pel 6 tap filter */
    { 0, -9, 93, 50, -6, 0, 0, 0},
    { 3, -16, 77, 77, -16, 3, 0, 0}, /* New 1/2 pel 6 tap filter */
    { 0, -6, 50, 93, -9, 0, 0, 0},
    { 1, -8, 36, 108, -11, 2, 0, 0}, /* New 1/4 pel 6 tap filter */
    { 0, -1, 12, 123, -6, 0, 0, 0},
};

kernel void vp8_filter_block2d_first_pass_kernel(
    __global unsigned char *src_base,
    int src_offset,
    __global int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
){
    uint tid = get_global_id(0);

    global unsigned char *src_ptr = &src_base[src_offset];
    //Note that src_offset will be reset later, which is why we use it now

    int Temp;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (tid < (output_width*output_height)){
        src_offset = tid + (tid/output_width * (src_pixels_per_line - output_width));

        Temp = (int)(src_ptr[src_offset - 2] * vp8_filter[0]) +
           (int)(src_ptr[src_offset - 1] * vp8_filter[1]) +
           (int)(src_ptr[src_offset]     * vp8_filter[2]) +
           (int)(src_ptr[src_offset + 1] * vp8_filter[3]) +
           (int)(src_ptr[src_offset + 2] * vp8_filter[4]) +
           (int)(src_ptr[src_offset + 3] * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);      /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;

        if (Temp < 0)
            Temp = 0;
        else if ( Temp > 255 )
            Temp = 255;

        output_ptr[tid] = Temp;
    }

}

kernel void vp8_filter_block2d_second_pass_kernel
(
    __global int *src_base,
    int src_offset,
    __global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
) {

    uint i = get_global_id(0);

    global int *src_ptr = &src_base[src_offset];
    global unsigned char *output_ptr = &output_base[output_offset];

    int out_offset; //Not same as output_offset...
    int Temp;
    int PS2 = 2*(int)pixel_step;
    int PS3 = 3*(int)pixel_step;

    unsigned int src_increment = src_pixels_per_line - output_width;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (i < (output_width * output_height)){
        out_offset = i/output_width;
        src_offset = out_offset;

        src_offset = i + (src_offset * src_increment);
        out_offset = i%output_width + (out_offset * output_pitch);

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset - PS2] * vp8_filter[0]) +
           ((int)src_ptr[src_offset -(int)pixel_step] * vp8_filter[1]) +
           ((int)src_ptr[src_offset]                  * vp8_filter[2]) +
           ((int)src_ptr[src_offset + pixel_step]     * vp8_filter[3]) +
           ((int)src_ptr[src_offset + PS2]       * vp8_filter[4]) +
           ((int)src_ptr[src_offset + PS3]       * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);   /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;
        if (Temp < 0)
            Temp = 0;
        else if (Temp > 255)
            Temp = 255;

        output_ptr[out_offset] = (unsigned char)Temp;
    }
}

kernel void vp8_filter_block2d_bil_first_pass_kernel(
    __global unsigned char *src_base,
    int src_offset,
    __global int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
)
{
    uint tid = get_global_id(0);

    if (tid < output_width * output_height){
        global unsigned char *src_ptr = &src_base[src_offset];

        unsigned int i, j;
        __constant int *vp8_filter = bilinear_filters[filter_offset];

        unsigned int out_row,out_offset;
        int src_increment = src_pixels_per_line - output_width;

        i = tid / output_width;
        j = tid % output_width;

        src_offset = i*(output_width+src_increment) + j;
        out_row = output_width * i;

        out_offset = out_row + j;

        /* Apply bilinear filter */
        output_ptr[out_offset] = (((int)src_ptr[src_offset]   * vp8_filter[0]) +
                 ((int)src_ptr[src_offset+1] * vp8_filter[1]) +
                 (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT;
    }
}

kernel void vp8_filter_block2d_bil_second_pass_kernel
(
    __global int *src_ptr,
    __global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
)
{

    uint tid = get_global_id(0);

    if (tid < output_width * output_height){
        global unsigned char *output_ptr = &output_base[output_offset];

        unsigned int i, j;
        int Temp;
        __constant int *vp8_filter = bilinear_filters[filter_offset];

        int out_offset;
        int src_offset;

        i = tid / output_width;
        j = tid % output_width;

        src_offset = i*(output_width) + j;
        out_offset = i*output_pitch + j;

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset]         * vp8_filter[0]) +
               ((int)src_ptr[src_offset+output_width] * vp8_filter[1]) +
               (VP8_FILTER_WEIGHT / 2);

        output_ptr[out_offset++] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
    }
}

//Called from reconinter_cl.c
kernel void vp8_memcpy_kernel(
    global unsigned char *src_base,
    int src_offset,
    int src_stride,
    global unsigned char *dst_base,
    int dst_offset,
    int dst_stride,
    int num_bytes,
    int num_iter
){

    int i,r;
    global unsigned char *src = &src_base[src_offset];
    global unsigned char *dst = &dst_base[dst_offset];
    src_offset = dst_offset = 0;

    r = get_global_id(1);
    if (r < get_global_size(1)){
        i = get_global_id(0);
        if (i < get_global_size(0)){
            src_offset = r*src_stride + i;
            dst_offset = r*dst_stride + i;
            dst[dst_offset] = src[src_offset];
        }
    }
}

//Not used currently.
void vp8_memset_short(
    global short *mem,
    int offset,
    short newval,
    unsigned int size
)
{
    int tid = get_global_id(0);

    if (tid < (size/2)){
        mem[offset+tid/2] = newval;
    }
}

//Here to EOF is old code that should be removed at end of project.

__kernel void vp8_bilinear_predict4x4_kernel
(
        __global unsigned char *src_base,
        int src_offset,
        int src_pixels_per_line,
        int xoffset,
        int yoffset,
        __global unsigned char *dst_base,
        int dst_offset,
        int dst_pitch,
        __global int *int_mem
)
{
    int Height = 4, Width = 4;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass_kernel(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass_kernel(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);
}

__kernel void vp8_bilinear_predict8x8_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{
    int Height = 8, Width = 8;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass_kernel(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass_kernel(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);

}

__kernel void vp8_bilinear_predict8x4_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{
    int Height = 4, Width = 8;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass_kernel(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass_kernel(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);
}

__kernel void vp8_bilinear_predict16x16_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{

    int Height = 16, Width = 16;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass_kernel(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass_kernel(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);

}

void vp8_filter_block2d_first_pass(
    global unsigned char *src_base,
    int src_offset,
    local int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
){
    uint tid = get_global_id(0);
    uint i = tid;

    global unsigned char *src_ptr = &src_base[src_offset];
    //Note that src_offset will be reset later, which is why we capture it now

    int Temp;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (tid < (output_width*output_height)){
        short filter0 = vp8_filter[0];
        short filter1 = vp8_filter[1];
        short filter2 = vp8_filter[2];
        short filter3 = vp8_filter[3];
        short filter4 = vp8_filter[4];
        short filter5 = vp8_filter[5];

        for (i=0; i < output_width*output_height; i++){
            src_offset = i + (i/output_width * (src_pixels_per_line - output_width));

            Temp = (int)(src_ptr[src_offset - 2] * filter0) +
                   (int)(src_ptr[src_offset - 1] * filter1) +
                   (int)(src_ptr[src_offset]     * filter2) +
                   (int)(src_ptr[src_offset + 1] * filter3) +
                   (int)(src_ptr[src_offset + 2] * filter4) +
                   (int)(src_ptr[src_offset + 3] * filter5) +
                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */

            /* Normalize back to 0-255 */
            Temp >>= VP8_FILTER_SHIFT;

            if (Temp < 0)
                Temp = 0;
            else if ( Temp > 255 )
                Temp = 255;

            output_ptr[i] = Temp;
        }
    }

    //Add a fence so that no 2nd pass stuff starts before 1st pass writes are done.
    //write_mem_fence(CLK_GLOBAL_MEM_FENCE);
    //barrier(CLK_GLOBAL_MEM_FENCE);
    barrier(CLK_LOCAL_MEM_FENCE);
}

void vp8_filter_block2d_second_pass
(
    local int *src_ptr,
    global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
) {

    global unsigned char *output_ptr = &output_base[output_offset];

    int out_offset; //Not same as output_offset...
    int src_offset;
    int Temp;
    int PS2 = 2*(int)pixel_step;
    int PS3 = 3*(int)pixel_step;

    unsigned int src_increment = src_pixels_per_line - output_width;

    uint i = get_global_id(0);

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (i < (output_width * output_height)){
        out_offset = i/output_width;
        src_offset = out_offset;

        src_offset = i + (src_offset * src_increment);
        out_offset = i%output_width + (out_offset * output_pitch);

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset - PS2] * vp8_filter[0]) +
           ((int)src_ptr[src_offset -(int)pixel_step] * vp8_filter[1]) +
           ((int)src_ptr[src_offset]                  * vp8_filter[2]) +
           ((int)src_ptr[src_offset + pixel_step]     * vp8_filter[3]) +
           ((int)src_ptr[src_offset + PS2]            * vp8_filter[4]) +
           ((int)src_ptr[src_offset + PS3]       * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);   /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;
        if (Temp < 0)
            Temp = 0;
        else if (Temp > 255)
            Temp = 255;

        output_ptr[out_offset] = (unsigned char)Temp;
    }
}

__kernel void vp8_sixtap_predict_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
        ) {

    local int FData[9*4];

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 9, 4, xoffset);

    /* then filter vertically... */
    vp8_filter_block2d_second_pass(&FData[8], dst_ptr, dst_offset, dst_pitch, 4, 4, 4, 4, yoffset);
}

__kernel void vp8_sixtap_predict8x8_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    local int FData[13*16];   /* Temp data bufffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 13, 8, xoffset);

    /* then filter vertically... */
    vp8_filter_block2d_second_pass(&FData[16], dst_ptr, dst_offset, dst_pitch, 8, 8, 8, 8, yoffset);

}

__kernel void vp8_sixtap_predict8x4_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    local int FData[13*16];   /* Temp data buffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 9, 8, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass(&FData[16], dst_ptr, dst_offset, dst_pitch, 8, 8, 4, 8, yoffset);
}

__kernel void vp8_sixtap_predict16x16_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    local int FData[21*24];   /* Temp data buffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 21, 16, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass(&FData[32], dst_ptr, dst_offset, dst_pitch, 16, 16, 16, 16, yoffset);

    return;
}

#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
#pragma OPENCL EXTENSION cl_amd_printf : enable

__constant int bilinear_filters[8][2] = {
    { 128, 0},
    { 112, 16},
    { 96, 32},
    { 80, 48},
    { 64, 64},
    { 48, 80},
    { 32, 96},
    { 16, 112}
};

__constant short sub_pel_filters[8][8] = {
    //These were originally 8x6, but are padded for vector ops
    { 0, 0, 128, 0, 0, 0, 0, 0}, /* note that 1/8 pel positions are just as per alpha -0.5 bicubic */
    { 0, -6, 123, 12, -1, 0, 0, 0},
    { 2, -11, 108, 36, -8, 1, 0, 0}, /* New 1/4 pel 6 tap filter */
    { 0, -9, 93, 50, -6, 0, 0, 0},
    { 3, -16, 77, 77, -16, 3, 0, 0}, /* New 1/2 pel 6 tap filter */
    { 0, -6, 50, 93, -9, 0, 0, 0},
    { 1, -8, 36, 108, -11, 2, 0, 0}, /* New 1/4 pel 6 tap filter */
    { 0, -1, 12, 123, -6, 0, 0, 0},
};

kernel void vp8_filter_block2d_first_pass_kernel(
    __global unsigned char *src_base,
    int src_offset,
    __global int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
){
    uint tid = get_global_id(0);

    global unsigned char *src_ptr = &src_base[src_offset];
    //Note that src_offset will be reset later, which is why we use it now

    int Temp;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (tid < (output_width*output_height)){
        src_offset = tid + (tid/output_width * (src_pixels_per_line - output_width));

        Temp = (int)(src_ptr[src_offset - 2] * vp8_filter[0]) +
           (int)(src_ptr[src_offset - 1] * vp8_filter[1]) +
           (int)(src_ptr[src_offset]     * vp8_filter[2]) +
           (int)(src_ptr[src_offset + 1] * vp8_filter[3]) +
           (int)(src_ptr[src_offset + 2] * vp8_filter[4]) +
           (int)(src_ptr[src_offset + 3] * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);      /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;

        if (Temp < 0)
            Temp = 0;
        else if ( Temp > 255 )
            Temp = 255;

        output_ptr[tid] = Temp;
    }

}

kernel void vp8_filter_block2d_second_pass_kernel
(
    __global int *src_base,
    int src_offset,
    __global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
) {

    uint i = get_global_id(0);

    global int *src_ptr = &src_base[src_offset];
    global unsigned char *output_ptr = &output_base[output_offset];

    int out_offset; //Not same as output_offset...
    int Temp;
    int PS2 = 2*(int)pixel_step;
    int PS3 = 3*(int)pixel_step;

    unsigned int src_increment = src_pixels_per_line - output_width;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (i < (output_width * output_height)){
        out_offset = i/output_width;
        src_offset = out_offset;

        src_offset = i + (src_offset * src_increment);
        out_offset = i%output_width + (out_offset * output_pitch);

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset - PS2] * vp8_filter[0]) +
           ((int)src_ptr[src_offset -(int)pixel_step] * vp8_filter[1]) +
           ((int)src_ptr[src_offset]                  * vp8_filter[2]) +
           ((int)src_ptr[src_offset + pixel_step]     * vp8_filter[3]) +
           ((int)src_ptr[src_offset + PS2]       * vp8_filter[4]) +
           ((int)src_ptr[src_offset + PS3]       * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);   /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;
        if (Temp < 0)
            Temp = 0;
        else if (Temp > 255)
            Temp = 255;

        output_ptr[out_offset] = (unsigned char)Temp;
    }
}

kernel void vp8_filter_block2d_bil_first_pass_kernel(
    __global unsigned char *src_base,
    int src_offset,
    __global int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
)
{
    uint tid = get_global_id(0);

    if (tid < output_width * output_height){
        global unsigned char *src_ptr = &src_base[src_offset];

        unsigned int i, j;
        __constant int *vp8_filter = bilinear_filters[filter_offset];

        unsigned int out_row,out_offset;
        int src_increment = src_pixels_per_line - output_width;

        i = tid / output_width;
        j = tid % output_width;

        src_offset = i*(output_width+src_increment) + j;
        out_row = output_width * i;

        out_offset = out_row + j;

        /* Apply bilinear filter */
        output_ptr[out_offset] = (((int)src_ptr[src_offset]   * vp8_filter[0]) +
                 ((int)src_ptr[src_offset+1] * vp8_filter[1]) +
                 (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT;
    }
}

kernel void vp8_filter_block2d_bil_second_pass_kernel
(
    __global int *src_ptr,
    __global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
)
{

    uint tid = get_global_id(0);

    if (tid < output_width * output_height){
        global unsigned char *output_ptr = &output_base[output_offset];

        unsigned int i, j;
        int Temp;
        __constant int *vp8_filter = bilinear_filters[filter_offset];

        int out_offset;
        int src_offset;

        i = tid / output_width;
        j = tid % output_width;

        src_offset = i*(output_width) + j;
        out_offset = i*output_pitch + j;

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset]         * vp8_filter[0]) +
               ((int)src_ptr[src_offset+output_width] * vp8_filter[1]) +
               (VP8_FILTER_WEIGHT / 2);

        output_ptr[out_offset++] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
    }
}

//Called from reconinter_cl.c
kernel void vp8_memcpy_kernel(
    global unsigned char *src_base,
    int src_offset,
    int src_stride,
    global unsigned char *dst_base,
    int dst_offset,
    int dst_stride,
    int num_bytes,
    int num_iter
){

    int i,r;
    global unsigned char *src = &src_base[src_offset];
    global unsigned char *dst = &dst_base[dst_offset];
    src_offset = dst_offset = 0;

    r = get_global_id(1);
    if (r < get_global_size(1)){
        i = get_global_id(0);
        if (i < get_global_size(0)){
            src_offset = r*src_stride + i;
            dst_offset = r*dst_stride + i;
            dst[dst_offset] = src[src_offset];
        }
    }
}

//Not used currently.
void vp8_memset_short(
    global short *mem,
    int offset,
    short newval,
    unsigned int size
)
{
    int tid = get_global_id(0);

    if (tid < (size/2)){
        mem[offset+tid/2] = newval;
    }
}

//Here to EOF is old code that should be removed at end of project.

__kernel void vp8_bilinear_predict4x4_kernel
(
        __global unsigned char *src_base,
        int src_offset,
        int src_pixels_per_line,
        int xoffset,
        int yoffset,
        __global unsigned char *dst_base,
        int dst_offset,
        int dst_pitch,
        __global int *int_mem
)
{
    int Height = 4, Width = 4;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass_kernel(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass_kernel(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);
}

__kernel void vp8_bilinear_predict8x8_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{
    int Height = 8, Width = 8;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass_kernel(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass_kernel(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);

}

__kernel void vp8_bilinear_predict8x4_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{
    int Height = 4, Width = 8;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass_kernel(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass_kernel(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);
}

__kernel void vp8_bilinear_predict16x16_kernel
(
    __global unsigned char *src_base,
    int src_offset,
    int src_pixels_per_line,
    int xoffset,
    int yoffset,
    __global unsigned char *dst_base,
    int dst_offset,
    int dst_pitch,
    __global int *int_mem
)
{

    int Height = 16, Width = 16;

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_bil_first_pass_kernel(src_base, src_offset, int_mem, src_pixels_per_line, Height + 1, Width, xoffset);

    /* then 1-D vertically... */
    vp8_filter_block2d_bil_second_pass_kernel(int_mem, dst_base, dst_offset, dst_pitch, Height, Width, yoffset);

}

void vp8_filter_block2d_first_pass(
    global unsigned char *src_base,
    int src_offset,
    private int *output_ptr,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
){
    uint tid = get_global_id(0);
    uint i = tid;

    global unsigned char *src_ptr = &src_base[src_offset];
    //Note that src_offset will be reset later, which is why we capture it now

    int Temp;

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (tid < (output_width*output_height)){
        short filter0 = vp8_filter[0];
        short filter1 = vp8_filter[1];
        short filter2 = vp8_filter[2];
        short filter3 = vp8_filter[3];
        short filter4 = vp8_filter[4];
        short filter5 = vp8_filter[5];

        for (i=0; i < output_width*output_height; i++){
            src_offset = i + (i/output_width * (src_pixels_per_line - output_width));

            Temp = (int)(src_ptr[src_offset - 2]      * filter0) +
                   (int)(src_ptr[src_offset - 1] * filter1) +
                   (int)(src_ptr[src_offset]                * filter2) +
                   (int)(src_ptr[src_offset + 1]   * filter3) +
                   (int)(src_ptr[src_offset + 2]          * filter4) +
                   (int)(src_ptr[src_offset + 3]          * filter5) +
                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */

            /* Normalize back to 0-255 */
            Temp = Temp >> VP8_FILTER_SHIFT;

            if (Temp < 0)
                Temp = 0;
            else if ( Temp > 255 )
                Temp = 255;

            output_ptr[i] = Temp;
        }
    }

    //Add a fence so that no 2nd pass stuff starts before 1st pass writes are done.
    //write_mem_fence(CLK_GLOBAL_MEM_FENCE);
    //barrier(CLK_GLOBAL_MEM_FENCE);
}

void vp8_filter_block2d_second_pass
(
    private int *src_ptr,
    global unsigned char *output_base,
    int output_offset,
    int output_pitch,
    unsigned int src_pixels_per_line,
    unsigned int pixel_step,
    unsigned int output_height,
    unsigned int output_width,
    int filter_offset
) {

    global unsigned char *output_ptr = &output_base[output_offset];

    int out_offset; //Not same as output_offset...
    int src_offset;
    int Temp;
    int PS2 = 2*(int)pixel_step;
    int PS3 = 3*(int)pixel_step;

    unsigned int src_increment = src_pixels_per_line - output_width;

    uint i = get_global_id(0);

    __constant short *vp8_filter = sub_pel_filters[filter_offset];

    if (i < (output_width * output_height)){
        out_offset = i/output_width;
        src_offset = out_offset;

        src_offset = i + (src_offset * src_increment);
        out_offset = i%output_width + (out_offset * output_pitch);

        /* Apply filter */
        Temp = ((int)src_ptr[src_offset - PS2] * vp8_filter[0]) +
           ((int)src_ptr[src_offset -(int)pixel_step] * vp8_filter[1]) +
           ((int)src_ptr[src_offset]                  * vp8_filter[2]) +
           ((int)src_ptr[src_offset + pixel_step]     * vp8_filter[3]) +
           ((int)src_ptr[src_offset + PS2]            * vp8_filter[4]) +
           ((int)src_ptr[src_offset + PS3]       * vp8_filter[5]) +
           (VP8_FILTER_WEIGHT >> 1);   /* Rounding */

        /* Normalize back to 0-255 */
        Temp = Temp >> VP8_FILTER_SHIFT;
        if (Temp < 0)
            Temp = 0;
        else if (Temp > 255)
            Temp = 255;

        output_ptr[out_offset] = (unsigned char)Temp;
    }
}

__kernel void vp8_sixtap_predict_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
        ) {

    private int FData[9*4];

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 9, 4, xoffset);

    /* then filter vertically... */
    vp8_filter_block2d_second_pass(&FData[8], dst_ptr, dst_offset, dst_pitch, 4, 4, 4, 4, yoffset);
}

__kernel void vp8_sixtap_predict8x8_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    private int FData[13*16];   /* Temp data bufffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 13, 8, xoffset);

    /* then filter vertically... */
    vp8_filter_block2d_second_pass(&FData[16], dst_ptr, dst_offset, dst_pitch, 8, 8, 8, 8, yoffset);

}

__kernel void vp8_sixtap_predict8x4_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    private int FData[13*16];   /* Temp data buffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 9, 8, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass(&FData[16], dst_ptr, dst_offset, dst_pitch, 8, 8, 4, 8, yoffset);
}

__kernel void vp8_sixtap_predict16x16_kernel
(
    __global unsigned char  *src_ptr,
    int src_offset,
    int  src_pixels_per_line,
    int  xoffset,
    int  yoffset,
    __global unsigned char *dst_ptr,
    int dst_offset,
    int  dst_pitch
)
{
    private int FData[21*24];   /* Temp data buffer used in filtering */

    /* First filter 1-D horizontally... */
    vp8_filter_block2d_first_pass(src_ptr, src_offset, FData, src_pixels_per_line, 1, 21, 16, xoffset);

    /* then filter verticaly... */
    vp8_filter_block2d_second_pass(&FData[32], dst_ptr, dst_offset, dst_pitch, 16, 16, 16, 16, yoffset);

    return;
}