/*
 * Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
 *
 * SPDX-License-Identifier: MIT
 */

#include "OCLSDI.h"

#include "Timer.h"
#define NUM_TESTS 6

#include <cmath>

typedef struct _threadInfo {
  int threadID_;
  OCLSDI* testObj_;
} ThreadInfo;
const char* kernel_str_ =
    "__kernel void test_kernel(global unsigned int * A) \
			   { \
					int id = get_global_id(0);  \
                    A[id] = id + 2;\
			   } ";
const char* testNames[NUM_TESTS] = {
    "WriteBuffer", "CopyBuffer",      "NDRangeKernel",
    "MapBuffer",   "WriteBufferRect", "CopyImageToBuffer",
};

void* ThreadMain(void* data) {
  if (data == NULL) {
    return 0;
  }
  ThreadInfo* threadData = (ThreadInfo*)data;
  threadData->testObj_->threadEntry(threadData->threadID_);
  return NULL;
}

OCLSDI::OCLSDI() {
  // If there are two different gpus in the system,
  // we have to test each of them as sender and receiver
  _numSubTests = 2 * NUM_TESTS;
}

OCLSDI::~OCLSDI() {}

void OCLSDI::open(unsigned int test, char* units, double& conversion, unsigned int deviceId) {
  cl_uint numPlatforms = 0;
  cl_platform_id platform = NULL;
  cl_uint num_devices = 0;
  _crcword = 0;
  conversion = 1.0f;
  program_ = 0;
  kernel_ = 0;
  srcBuff_ = 0;
  _openTest = test % NUM_TESTS;
  bufSize_ = 0x10000;
  error_ = 0;
  markerValue_ = 0x12345;
  inputArr_ = 0;
  outputArr_ = 0;
  success_ = true;
  extPhysicalBuff_ = 0;
  silentFailure = false;
  busAddressableBuff_ = 0;
  devices_[0] = devices_[1] = 0;
  contexts_[0] = contexts_[1] = 0;
  cmd_queues_[0] = cmd_queues_[1] = 0;
  image_ = 0;

  inputArr_ = (cl_uint*)malloc(bufSize_);
  outputArr_ = (cl_uint*)malloc(bufSize_);
  for (unsigned int i = 0; i < (bufSize_ / sizeof(cl_uint)); ++i) {
    inputArr_[i] = i + 1;
    outputArr_[i] = 0;
  }
  error_ = _wrapper->clGetPlatformIDs(0, NULL, &numPlatforms);
  CHECK_RESULT(numPlatforms == 0, "clGetPlatformIDs failed");
  error_ = _wrapper->clGetPlatformIDs(1, &platform, NULL);
  CHECK_RESULT(error_ != CL_SUCCESS, "clGetPlatformIDs failed");
  error_ = _wrapper->clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &num_devices);
  if (num_devices < 2) {
    printf("\nSilent Failure: Two GPUs are required to run OCLSdi test\n");
    silentFailure = true;
    return;
  }
  error_ = _wrapper->clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 2, devices_, 0);
  CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceIDs failed");
  if (test >= NUM_TESTS) {
    cl_device_id temp = devices_[0];
    devices_[0] = devices_[1];
    devices_[1] = temp;
  }
  size_t param_size = 0;
  char* strExtensions = 0;
  error_ = _wrapper->clGetDeviceInfo(devices_[0], CL_DEVICE_EXTENSIONS, 0, 0, &param_size);
  CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed");
  strExtensions = (char*)malloc(param_size);
  error_ =
      _wrapper->clGetDeviceInfo(devices_[0], CL_DEVICE_EXTENSIONS, param_size, strExtensions, 0);
  CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed");
  if (strstr(strExtensions, "cl_amd_bus_addressable_memory") == 0) {
    printf(
        "\nSilent Failure: cl_amd_bus_addressable_memory extension is not "
        "enabled on GPU 0\n");
    silentFailure = true;
    free(strExtensions);
    return;
  }
  free(strExtensions);
  error_ = _wrapper->clGetDeviceInfo(devices_[1], CL_DEVICE_EXTENSIONS, 0, 0, &param_size);
  CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed");
  strExtensions = (char*)malloc(param_size);
  error_ =
      _wrapper->clGetDeviceInfo(devices_[1], CL_DEVICE_EXTENSIONS, param_size, strExtensions, 0);
  CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed");
  if (strstr(strExtensions, "cl_amd_bus_addressable_memory") == 0) {
    printf(
        "\nSilent Failure: cl_amd_bus_addressable_memory extension is not "
        "enabled on GPU 1\n");
    silentFailure = true;
    free(strExtensions);
    return;
  }
  free(strExtensions);
  deviceNames_ = " [";
  param_size = 0;
  char* strDeviceName = 0;
  error_ = _wrapper->clGetDeviceInfo(devices_[1], CL_DEVICE_NAME, 0, 0, &param_size);
  CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed");
  strDeviceName = (char*)malloc(param_size);
  error_ = _wrapper->clGetDeviceInfo(devices_[1], CL_DEVICE_NAME, param_size, strDeviceName, 0);
  CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed");
  deviceNames_ = deviceNames_ + strDeviceName;
  free(strDeviceName);
  error_ = _wrapper->clGetDeviceInfo(devices_[0], CL_DEVICE_NAME, 0, 0, &param_size);
  CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed");
  strDeviceName = (char*)malloc(param_size);
  error_ = _wrapper->clGetDeviceInfo(devices_[0], CL_DEVICE_NAME, param_size, strDeviceName, 0);
  CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed");
  deviceNames_ = deviceNames_ + "->";
  deviceNames_ = deviceNames_ + strDeviceName;
  free(strDeviceName);
  deviceNames_ = deviceNames_ + "]";
  cl_context_properties props[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0};
  contexts_[0] = _wrapper->clCreateContext(props, 1, &devices_[0], 0, 0, &error_);
  CHECK_RESULT(contexts_[0] == 0, "clCreateContext failed");
  contexts_[1] = _wrapper->clCreateContext(props, 1, &devices_[1], 0, 0, &error_);
  CHECK_RESULT(contexts_[1] == 0, "clCreateContext failed");
  cmd_queues_[0] = _wrapper->clCreateCommandQueue(contexts_[0], devices_[0], 0, NULL);
  CHECK_RESULT(cmd_queues_[0] == 0, "clCreateCommandQueue failed");
  cmd_queues_[1] = _wrapper->clCreateCommandQueue(contexts_[1], devices_[1], 0, NULL);
  CHECK_RESULT(cmd_queues_[1] == 0, "clCreateCommandQueue failed");
  busAddressableBuff_ =
      _wrapper->clCreateBuffer(contexts_[0], CL_MEM_BUS_ADDRESSABLE_AMD, bufSize_, 0, &error_);
  CHECK_RESULT((error_ != CL_SUCCESS), "clCreateBuffer failed");
  error_ = _wrapper->clEnqueueMakeBuffersResidentAMD(cmd_queues_[0], 1, &busAddressableBuff_, true,
                                                     &busAddr_, 0, 0, 0);
  CHECK_RESULT((error_ != CL_SUCCESS), "clEnqueueMakeBuffersResidentAMD failed");
  extPhysicalBuff_ = _wrapper->clCreateBuffer(contexts_[1], CL_MEM_EXTERNAL_PHYSICAL_AMD, bufSize_,
                                              &busAddr_, &error_);
  CHECK_RESULT((error_ != CL_SUCCESS), "clCreateBuffer failed");
  error_ = _wrapper->clEnqueueWriteSignalAMD(cmd_queues_[1], extPhysicalBuff_, 0, 0, 0, 0, 0);
  CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteSignalAMD failed");
  error_ = _wrapper->clFinish(cmd_queues_[1]);
  CHECK_RESULT(error_, "clFinish failed");
  srcBuff_ = _wrapper->clCreateBuffer(contexts_[1], CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
                                      bufSize_, inputArr_, &error_);
  CHECK_RESULT(error_ != CL_SUCCESS, "clCreateBuffer failed");
  error_ = _wrapper->clEnqueueMigrateMemObjects(cmd_queues_[1], 1, &extPhysicalBuff_, 0, 0, 0, 0);
  CHECK_RESULT(error_, "clEnqueueMigrateMemObjects failed");
  error_ = _wrapper->clFinish(cmd_queues_[1]);
  CHECK_RESULT(error_, "clFinish failed");
  error_ = _wrapper->clEnqueueMigrateMemObjects(cmd_queues_[1], 1, &srcBuff_, 0, 0, 0, 0);
  CHECK_RESULT(error_, "clEnqueueMigrateMemObjects failed");
  error_ = _wrapper->clFinish(cmd_queues_[1]);
  CHECK_RESULT(error_, "clFinish failed");
  if (_openTest == 2) {
    program_ = _wrapper->clCreateProgramWithSource(contexts_[1], 1, &kernel_str_, NULL, &error_);
    CHECK_RESULT(error_, "clCreateProgramWithSource failed");
    error_ = _wrapper->clBuildProgram(program_, 1, &devices_[1], NULL, NULL, NULL);
    if (error_ != CL_SUCCESS) {
      char* errorstr;
      size_t size;
      _wrapper->clGetProgramBuildInfo(program_, devices_[1], CL_PROGRAM_BUILD_LOG, 0, NULL, &size);
      errorstr = new char[size];
      _wrapper->clGetProgramBuildInfo(program_, devices_[1], CL_PROGRAM_BUILD_LOG, size, errorstr,
                                      &size);
      printf("\n%s\n", errorstr);
      delete[] errorstr;
    }
    CHECK_RESULT(error_, "clBuildProgram failed");

    kernel_ = _wrapper->clCreateKernel(program_, "test_kernel", &error_);
    CHECK_RESULT(error_, "clCreateKernel failed");
    error_ = _wrapper->clSetKernelArg(kernel_, 0, sizeof(cl_mem), (void*)&extPhysicalBuff_);
    CHECK_RESULT(error_, "clSetKernelArg failed");
  }
  if (_openTest == 5) {
    cl_image_format format = {CL_R, CL_UNSIGNED_INT32};
    cl_image_desc desc;
    desc.image_type = CL_MEM_OBJECT_IMAGE1D;
    desc.image_width = bufSize_ / sizeof(cl_uint);
    desc.image_height = 0;
    desc.image_depth = 0;
    desc.image_array_size = 0;
    desc.image_row_pitch = 0;
    desc.image_slice_pitch = 0;
    desc.num_mip_levels = 0;
    desc.num_samples = 0;
    desc.buffer = (cl_mem)NULL;
    image_ = _wrapper->clCreateImage(contexts_[1], CL_MEM_READ_ONLY, &format, &desc, 0, &error_);
    CHECK_RESULT(error_, "clCreateImage failed");
  }
}

void OCLSDI::run(void) {
  if (silentFailure) {
    return;
  }
  ++markerValue_;
  OCLutil::Thread threads[2];
  ThreadInfo threadInfo[2];
  threadInfo[0].testObj_ = threadInfo[1].testObj_ = this;
  threadInfo[0].threadID_ = 0;
  threadInfo[1].threadID_ = 1;
  threads[0].create(ThreadMain, &threadInfo[0]);
  threads[1].create(ThreadMain, &threadInfo[1]);
  threads[0].join();
  threads[1].join();
  char* descString = (char*)malloc(25 + deviceNames_.size());
  sprintf(descString, "%-20s%s", testNames[_openTest], deviceNames_.c_str());
  testDescString = descString;
  free(descString);
  if (!success_) {
    _errorFlag = true;
    _crcword += 1;
  }
}

void OCLSDI::threadEntry(int threadID) {
  if (silentFailure) {
    return;
  }
  switch (_openTest) {
    case 0:
      testEnqueueWriteBuffer(threadID);
      break;
    case 1:
      testEnqueueCopyBuffer(threadID);
      break;
    case 2:
      testEnqueueNDRangeKernel(threadID);
      break;
    case 3:
      testEnqueueMapBuffer(threadID);
      break;
    case 4:
      testEnqueueWriteBufferRect(threadID);
      break;
    case 5:
      testEnqueueCopyImageToBuffer(threadID);
      break;
  }
}

unsigned int OCLSDI::close(void) {
  if (srcBuff_) {
    error_ = _wrapper->clReleaseMemObject(srcBuff_);
    CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseMemObject failed");
  }
  if (extPhysicalBuff_) {
    error_ = _wrapper->clReleaseMemObject(extPhysicalBuff_);
    CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseMemObject failed");
  }
  if (busAddressableBuff_) {
    error_ = _wrapper->clReleaseMemObject(busAddressableBuff_);
    CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseMemObject failed");
  }
  if (cmd_queues_[0]) {
    error_ = _wrapper->clReleaseCommandQueue(cmd_queues_[0]);
    CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseCommandQueue failed");
  }
  if (cmd_queues_[1]) {
    error_ = _wrapper->clReleaseCommandQueue(cmd_queues_[1]);
    CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseCommandQueue failed");
  }
  if (contexts_[0]) {
    error_ = _wrapper->clReleaseContext(contexts_[0]);
    CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseContext failed");
  }
  if (contexts_[1]) {
    error_ = _wrapper->clReleaseContext(contexts_[1]);
    CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseContext failed");
  }
  if (program_) {
    error_ = _wrapper->clReleaseProgram(program_);
    CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseProgram failed");
  }
  if (kernel_) {
    error_ = _wrapper->clReleaseKernel(kernel_);
    CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseKernel failed");
  }
  if (image_) {
    error_ = _wrapper->clReleaseMemObject(image_);
    CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseMemObject failed");
  }
  if (inputArr_) {
    free(inputArr_);
  }
  if (outputArr_) {
    free(outputArr_);
  }
  return _crcword;
}

void OCLSDI::readAndVerifyResult() {
  memset(outputArr_, 0, bufSize_);
  error_ =
      _wrapper->clEnqueueWaitSignalAMD(cmd_queues_[0], busAddressableBuff_, markerValue_, 0, 0, 0);
  CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWaitSignalAMD failed");
  error_ = _wrapper->clEnqueueReadBuffer(cmd_queues_[0], busAddressableBuff_, CL_TRUE, 0, bufSize_,
                                         outputArr_, 0, 0, NULL);
  CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueReadBuffer failed");
  success_ = (memcmp(inputArr_, outputArr_, bufSize_) == 0);
}

void OCLSDI::testEnqueueCopyImageToBuffer(int threadID) {
  if (threadID == 0) {
    size_t origin[3] = {0, 0, 0};
    size_t region[3] = {bufSize_ / sizeof(cl_uint), 1, 1};
    memset(inputArr_, (_openTest + 1), bufSize_);
    error_ = _wrapper->clEnqueueWriteImage(cmd_queues_[1], image_, CL_TRUE, origin, region, 0, 0,
                                           inputArr_, 0, 0, 0);
    CHECK_RESULT(error_, "clEnqueueWriteImage failed");
    _wrapper->clFinish(cmd_queues_[1]);
    error_ = _wrapper->clEnqueueCopyImageToBuffer(cmd_queues_[1], image_, extPhysicalBuff_, origin,
                                                  region, 0, 0, 0, 0);
    CHECK_RESULT(error_, "clEnqueueCopyImageToBuffer failed");
    _wrapper->clFinish(cmd_queues_[1]);
    error_ = _wrapper->clEnqueueWriteSignalAMD(cmd_queues_[1], extPhysicalBuff_, markerValue_, 0, 0,
                                               0, 0);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteSignalAMD failed");
    error_ = _wrapper->clFinish(cmd_queues_[1]);
    CHECK_RESULT(error_, "clFinish failed");
  } else {
    readAndVerifyResult();
  }
}

void OCLSDI::testEnqueueWriteBufferRect(int threadID) {
  size_t width = (size_t)sqrt((float)bufSize_);
  size_t bufOrigin[3] = {0, 0, 0};
  size_t hostOrigin[3] = {0, 0, 0};
  size_t region[3] = {width, width, 1};
  if (threadID == 0) {
    memset(inputArr_, (_openTest + 1), bufSize_);
    error_ = _wrapper->clEnqueueWriteBufferRect(cmd_queues_[1], extPhysicalBuff_, CL_TRUE,
                                                bufOrigin, hostOrigin, region, width, 0, width, 0,
                                                inputArr_, 0, 0, 0);
    CHECK_RESULT(error_, "clEnqueueWriteBufferRect failed");
    error_ = _wrapper->clEnqueueWriteSignalAMD(cmd_queues_[1], extPhysicalBuff_, markerValue_, 0, 0,
                                               0, 0);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteSignalAMD failed");
    error_ = _wrapper->clFinish(cmd_queues_[1]);
    CHECK_RESULT(error_, "clFinish failed");
  } else {
    memset(outputArr_, 0, bufSize_);
    error_ = _wrapper->clEnqueueWaitSignalAMD(cmd_queues_[0], busAddressableBuff_, markerValue_, 0,
                                              0, 0);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWaitSignalAMD failed");
    error_ = _wrapper->clEnqueueReadBufferRect(cmd_queues_[0], busAddressableBuff_, CL_TRUE,
                                               bufOrigin, hostOrigin, region, width, 0, width, 0,
                                               outputArr_, 0, 0, 0);
    CHECK_RESULT(error_, "clEnqueueReadBufferRect failed");
    success_ = (memcmp(inputArr_, outputArr_, bufSize_) == 0);
  }
}

void OCLSDI::testEnqueueMapBuffer(int threadID) {
  if (threadID == 0) {
    memset(inputArr_, (_openTest + 1), bufSize_);
    error_ = _wrapper->clEnqueueWriteBuffer(cmd_queues_[1], extPhysicalBuff_, CL_TRUE, 0, bufSize_,
                                            inputArr_, 0, 0, NULL);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteBuffer failed");
    error_ = _wrapper->clEnqueueWriteSignalAMD(cmd_queues_[1], extPhysicalBuff_, markerValue_, 0, 0,
                                               0, 0);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteSignalAMD failed");
    error_ = _wrapper->clFinish(cmd_queues_[1]);
    CHECK_RESULT(error_, "clFinish failed");
  } else {
    error_ = _wrapper->clEnqueueWaitSignalAMD(cmd_queues_[0], busAddressableBuff_, markerValue_, 0,
                                              0, 0);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWaitSignalAMD failed");
    void* ptr = _wrapper->clEnqueueMapBuffer(cmd_queues_[0], busAddressableBuff_, CL_TRUE,
                                             CL_MAP_READ, 0, bufSize_, 0, 0, 0, &error_);
    CHECK_RESULT(error_, "clEnqueueMapBuffer failed");
    success_ = (memcmp(inputArr_, ptr, bufSize_) == 0);
    error_ = _wrapper->clEnqueueUnmapMemObject(cmd_queues_[0], busAddressableBuff_, ptr, 0, 0, 0);
    CHECK_RESULT(error_, "clEnqueueUnmapMemObject failed");
    error_ = _wrapper->clFinish(cmd_queues_[0]);
    CHECK_RESULT(error_, "clFinish failed");
  }
}

void OCLSDI::testEnqueueNDRangeKernel(int threadID) {
  if (threadID == 0) {
    size_t global_work_size = bufSize_ / sizeof(cl_uint);
    error_ = _wrapper->clEnqueueNDRangeKernel(cmd_queues_[1], kernel_, 1, NULL, &global_work_size,
                                              NULL, 0, NULL, NULL);
    CHECK_RESULT(error_, "clEnqueueNDRangeKernel failed");
    error_ = _wrapper->clFinish(cmd_queues_[1]);
    CHECK_RESULT(error_, "clFinish failed");
    error_ = _wrapper->clEnqueueWriteSignalAMD(cmd_queues_[1], extPhysicalBuff_, markerValue_, 0, 0,
                                               0, 0);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteSignalAMD failed");
    error_ = _wrapper->clFinish(cmd_queues_[1]);
    CHECK_RESULT(error_, "clFinish failed");
  } else {
    memset(outputArr_, 0, bufSize_);
    error_ = _wrapper->clEnqueueWaitSignalAMD(cmd_queues_[0], busAddressableBuff_, markerValue_, 0,
                                              0, 0);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWaitSignalAMD failed");
    error_ = _wrapper->clEnqueueReadBuffer(cmd_queues_[0], busAddressableBuff_, CL_TRUE, 0,
                                           bufSize_, outputArr_, 0, 0, NULL);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteBuffer failed");
    success_ = true;
    for (cl_uint i = 0; i < bufSize_ / sizeof(cl_uint); ++i) {
      success_ &= (outputArr_[i] == i + 2);
    }
  }
}

void OCLSDI::testEnqueueCopyBuffer(int threadID) {
  if (threadID == 0) {
    memset(inputArr_, (_openTest + 1), bufSize_);
    error_ = _wrapper->clEnqueueWriteBuffer(cmd_queues_[1], srcBuff_, CL_TRUE, 0, bufSize_,
                                            inputArr_, 0, 0, NULL);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteBuffer failed");
    error_ = _wrapper->clEnqueueCopyBuffer(cmd_queues_[1], srcBuff_, extPhysicalBuff_, 0, 0,
                                           bufSize_, 0, NULL, NULL);
    CHECK_RESULT(error_, "clEnqueueCopyBuffer failed");
    error_ = _wrapper->clEnqueueWriteSignalAMD(cmd_queues_[1], extPhysicalBuff_, markerValue_, 0, 0,
                                               0, 0);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteSignalAMD failed");
    error_ = _wrapper->clFinish(cmd_queues_[1]);
    CHECK_RESULT(error_, "clFinish failed");
  } else {
    readAndVerifyResult();
  }
}

void OCLSDI::testEnqueueWriteBuffer(int threadID) {
  if (threadID == 0) {
    memset(inputArr_, (_openTest + 1), bufSize_);
    error_ = _wrapper->clEnqueueWriteBuffer(cmd_queues_[1], extPhysicalBuff_, CL_TRUE, 0, bufSize_,
                                            inputArr_, 0, 0, NULL);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteBuffer failed");
    error_ = _wrapper->clEnqueueWriteSignalAMD(cmd_queues_[1], extPhysicalBuff_, markerValue_, 0, 0,
                                               0, 0);
    CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteSignalAMD failed");
    error_ = _wrapper->clFinish(cmd_queues_[1]);
    CHECK_RESULT(error_, "clFinish failed");
  } else {
    readAndVerifyResult();
  }
}
