我正在制作一个Android应用来测试OpenCL和RenderScript之间的差异。现在我正在尝试优化OpenCL的视频处理代码,但我只能处理第一帧而其他所有代码都是黑色的。
我的所有功能都适用于图像,当我在每个视频帧之前回想起初始化然后边缘检测功能时,一切顺利。但是,每当它被激活(当它是相同的内核)时,我需要重建OpenCL程序似乎不是逻辑。
我有一个包含所有OpenCL对象的结构:
struct OpenCLObjects
{
// Regular OpenCL objects:
cl_platform_id platform;
cl_device_id device;
cl_context context;
cl_command_queue queue;
cl_program program;
cl_kernel kernel;
// Objects that are specific for this sample.
bool isInputBufferInitialized;
cl_mem inputBuffer;
cl_mem outputBuffer;
};
// Hold all OpenCL objects.
static OpenCLObjects openCLObjects;
然后我有这个初始化函数:
void initOpenCL
(
JNIEnv* env,
jobject thisObject,
jstring kernelName,
cl_device_type required_device_type,
OpenCLObjects& openCLObjects
)
{
using namespace std;
openCLObjects.isInputBufferInitialized = false;
cl_int err = CL_SUCCESS;
cl_platform_id platform;
err = clGetPlatformIDs(1, &platform, NULL);
SAMPLE_CHECK_ERRORS(err);
cl_uint i = 0;
size_t platform_name_length = 0;
err = clGetPlatformInfo(
platform,
CL_PLATFORM_NAME,
0,
0,
&platform_name_length
);
SAMPLE_CHECK_ERRORS(err);
openCLObjects.platform = platform;
cl_context_properties context_props[] = {
CL_CONTEXT_PLATFORM,
cl_context_properties(openCLObjects.platform),
0
};
openCLObjects.context =
clCreateContextFromType
(
context_props,
required_device_type,
0,
0,
&err
);
SAMPLE_CHECK_ERRORS(err);
err = clGetContextInfo
(
openCLObjects.context,
CL_CONTEXT_DEVICES,
sizeof(openCLObjects.device),
&openCLObjects.device,
0
);
SAMPLE_CHECK_ERRORS(err);
const char* fileName = env->GetStringUTFChars(kernelName, 0);
std::string fileDir;
fileDir.append("/data/data/com.denayer.ovsr/app_execdir/");
fileDir.append(fileName);
fileDir.append(".cl");
std::string kernelSource = loadProgram(fileDir);
const char* kernelSourceChar = kernelSource.c_str();
openCLObjects.program =
clCreateProgramWithSource
(
openCLObjects.context,
1,
&kernelSourceChar,
0,
&err
);
SAMPLE_CHECK_ERRORS(err);
err = clBuildProgram(openCLObjects.program, 0, 0, "-cl-fast-relaxed-math", 0, 0);
SAMPLE_CHECK_ERRORS(err);
/* -----------------------------------------------------------------------
* Step 6: Extract kernel from the built program.
*/
fileName = env->GetStringUTFChars(kernelName, 0);
char result[100]; // array to hold the result.
std::strcpy(result,fileName); // copy string one into the result.
std::strcat(result,"Kernel"); // append string two to the result.
openCLObjects.kernel = clCreateKernel(openCLObjects.program, result, &err);
SAMPLE_CHECK_ERRORS(err);
/* -----------------------------------------------------------------------
* Step 7: Create command queue.
*/
openCLObjects.queue =
clCreateCommandQueue
(
openCLObjects.context,
openCLObjects.device,
0,
&err
);
SAMPLE_CHECK_ERRORS(err);
}
extern "C" void Java_com_denayer_ovsr_OpenCL_initOpenCL
(
JNIEnv* env,
jobject thisObject,
jstring kernelName
)
{
initOpenCL
(
env,
thisObject,
kernelName,
CL_DEVICE_TYPE_GPU,
openCLObjects
);
}
这是调用边缘检测内核的函数:
void nativeImage2DOpenCL
(
JNIEnv* env,
jobject thisObject,
OpenCLObjects& openCLObjects,
jobject inputBitmap,
jobject outputBitmap
)
{
using namespace std;
AndroidBitmapInfo bitmapInfo;
AndroidBitmap_getInfo(env, inputBitmap, &bitmapInfo);
size_t bufferSize = bitmapInfo.height * bitmapInfo.stride;
cl_uint rowPitch = bitmapInfo.stride / 4;
cl_int err = CL_SUCCESS;
if(openCLObjects.isInputBufferInitialized)
{
err = clReleaseMemObject(openCLObjects.inputBuffer);
SAMPLE_CHECK_ERRORS(err);
}
void* inputPixels = 0;
AndroidBitmap_lockPixels(env, inputBitmap, &inputPixels);
cl_image_format image_format;
image_format.image_channel_data_type=CL_UNORM_INT8;
image_format.image_channel_order=CL_RGBA;
openCLObjects.inputBuffer =
clCreateImage2D(openCLObjects.context,
CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
&image_format,
bitmapInfo.width,
bitmapInfo.height,
0,
inputPixels,
&err);
SAMPLE_CHECK_ERRORS(err);
openCLObjects.isInputBufferInitialized = true;
AndroidBitmap_unlockPixels(env, inputBitmap);
void* outputPixels = 0;
AndroidBitmap_lockPixels(env, outputBitmap, &outputPixels);
cl_mem outputBuffer =
clCreateImage2D(openCLObjects.context,
CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
&image_format,
bitmapInfo.width,
bitmapInfo.height,
0,
outputPixels,
&err);
SAMPLE_CHECK_ERRORS(err);
err = clSetKernelArg(openCLObjects.kernel, 0, sizeof(openCLObjects.inputBuffer), &openCLObjects.inputBuffer);
SAMPLE_CHECK_ERRORS(err);
err = clSetKernelArg(openCLObjects.kernel, 1, sizeof(outputBuffer), &outputBuffer);
SAMPLE_CHECK_ERRORS(err);
size_t globalSize[2] = { bitmapInfo.width, bitmapInfo.height };
err = clEnqueueNDRangeKernel
(
openCLObjects.queue,
openCLObjects.kernel,
2,
0,
globalSize,
0,
0, 0, 0
);
SAMPLE_CHECK_ERRORS(err);
err = clFinish(openCLObjects.queue);
SAMPLE_CHECK_ERRORS(err);
const size_t origin[3] = {0, 0, 0};
const size_t region[3] = {bitmapInfo.width, bitmapInfo.height, 1};
err = clEnqueueReadImage(
openCLObjects.queue,
outputBuffer,
true,
origin,
region,
0,
0,
outputPixels,
0,
0,
0);
SAMPLE_CHECK_ERRORS(err);
err = clFinish(openCLObjects.queue);
SAMPLE_CHECK_ERRORS(err);
err = clReleaseMemObject(outputBuffer);
SAMPLE_CHECK_ERRORS(err);
AndroidBitmap_unlockPixels(env, outputBitmap);
}
extern "C" void Java_com_denayer_ovsr_OpenCL_nativeImage2DOpenCL
(
JNIEnv* env,
jobject thisObject,
jobject inputBitmap,
jobject outputBitmap
)
{
nativeImage2DOpenCL
(
env,
thisObject,
openCLObjects,
inputBitmap,
outputBitmap
);
}