dolphin/Source/Core/Common/Src/OpenCL.cpp
Orphis 094c73a080 OpenCL: Moved the OpenCL code from the compiled source to a separate file TextureDecoder.cl and added a .rules files to copy the updated version to the build directory.
Fixed RGB5A3 decoding with alpha
New CMPR decoding, blocks with no alpha are great, still have to figure the problems with transparent blocks. Disabled for now.
Added a better error reporting to the base OpenCL functions

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4439 8ced0084-cf51-0410-be5f-012b33b47a6e
2009-10-20 00:55:07 +00:00

196 lines
5.8 KiB
C++

// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program 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 General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// TODO: Make a more centralized version of this (for now every plugin that will use it will create its own context, which is weird). An object maybe?
#include "OpenCL.h"
#include "Common.h"
namespace OpenCL {
#if defined(HAVE_OPENCL) && HAVE_OPENCL
cl_device_id device_id = NULL;
cl_context g_context = NULL;
cl_command_queue g_cmdq = NULL;
#endif
bool g_bInitialized = false;
bool Initialize() {
if(g_bInitialized)
return true;
#if defined(HAVE_OPENCL) && HAVE_OPENCL
if(g_context)
return false;
int err; // error code returned from api calls
// Connect to a compute device
//
int gpu = 1; // I think we should use CL_DEVICE_TYPE_ALL
err = clGetDeviceIDs(NULL, gpu ? CL_DEVICE_TYPE_GPU : CL_DEVICE_TYPE_CPU, 1, &device_id, NULL);
if (err != CL_SUCCESS)
{
HandleCLError(err, "Failed to create a device group!");
return false;
}
// Create a compute context
//
g_context = clCreateContext(0, 1, &device_id, NULL, NULL, &err);
if (!g_context)
{
HandleCLError(err, "Failed to create a compute context!");
return false;
}
// Create a command commands
//
g_cmdq = clCreateCommandQueue(g_context, device_id, 0, &err);
if (!g_cmdq)
{
HandleCLError(err, "Failed to create a command commands!");
return false;
}
//PanicAlert("Initialized OpenCL fine!");
g_bInitialized = true;
return true;
#else
return false;
#endif
}
#if defined(HAVE_OPENCL) && HAVE_OPENCL
cl_context GetContext() {
return g_context;
}
cl_command_queue GetCommandQueue() {
return g_cmdq;
}
cl_program CompileProgram(const char *Kernel) {
int err;
cl_program program;
program = clCreateProgramWithSource(OpenCL::g_context, 1, (const char **) & Kernel, NULL, &err);
if (!program)
{
HandleCLError(err, "Error: Failed to create compute program!");
return NULL;
}
// Build the program executable
//
err = clBuildProgram(program , 0, NULL, NULL, NULL, NULL);
if(err != CL_SUCCESS) {
char *errors[16384] = {0};
err = clGetProgramBuildInfo(program, OpenCL::device_id, CL_PROGRAM_BUILD_LOG, sizeof(errors),
errors, NULL);
PanicAlert("Error log:\n%s\n", errors);
return NULL;
}
return program;
}
cl_kernel CompileKernel(cl_program program, const char *Function)
{
int err;
// Create the compute kernel in the program we wish to run
//
cl_kernel kernel = clCreateKernel(program, Function, &err);
if (!kernel || err != CL_SUCCESS)
{
HandleCLError(err, "Failed to create compute kernel!");
return NULL;
}
return kernel;
}
#endif
void Destroy() {
#if defined(HAVE_OPENCL) && HAVE_OPENCL
if(!g_context)
return;
clReleaseCommandQueue(g_cmdq);
clReleaseContext(g_context);
#endif
}
void HandleCLError(cl_int error, char* str)
{
char* name;
switch(error)
{
#define CL_ERROR(x) case (x): name = #x; break
CL_ERROR(CL_SUCCESS);
CL_ERROR(CL_DEVICE_NOT_FOUND);
CL_ERROR(CL_DEVICE_NOT_AVAILABLE);
CL_ERROR(CL_COMPILER_NOT_AVAILABLE);
CL_ERROR(CL_MEM_OBJECT_ALLOCATION_FAILURE);
CL_ERROR(CL_OUT_OF_RESOURCES);
CL_ERROR(CL_OUT_OF_HOST_MEMORY);
CL_ERROR(CL_PROFILING_INFO_NOT_AVAILABLE);
CL_ERROR(CL_MEM_COPY_OVERLAP);
CL_ERROR(CL_IMAGE_FORMAT_MISMATCH);
CL_ERROR(CL_IMAGE_FORMAT_NOT_SUPPORTED);
CL_ERROR(CL_BUILD_PROGRAM_FAILURE);
CL_ERROR(CL_MAP_FAILURE);
CL_ERROR(CL_INVALID_VALUE);
CL_ERROR(CL_INVALID_DEVICE_TYPE);
CL_ERROR(CL_INVALID_PLATFORM);
CL_ERROR(CL_INVALID_DEVICE);
CL_ERROR(CL_INVALID_CONTEXT);
CL_ERROR(CL_INVALID_QUEUE_PROPERTIES);
CL_ERROR(CL_INVALID_COMMAND_QUEUE);
CL_ERROR(CL_INVALID_HOST_PTR);
CL_ERROR(CL_INVALID_MEM_OBJECT);
CL_ERROR(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
CL_ERROR(CL_INVALID_IMAGE_SIZE);
CL_ERROR(CL_INVALID_SAMPLER);
CL_ERROR(CL_INVALID_BINARY);
CL_ERROR(CL_INVALID_BUILD_OPTIONS);
CL_ERROR(CL_INVALID_PROGRAM);
CL_ERROR(CL_INVALID_PROGRAM_EXECUTABLE);
CL_ERROR(CL_INVALID_KERNEL_NAME);
CL_ERROR(CL_INVALID_KERNEL_DEFINITION);
CL_ERROR(CL_INVALID_KERNEL);
CL_ERROR(CL_INVALID_ARG_INDEX);
CL_ERROR(CL_INVALID_ARG_VALUE);
CL_ERROR(CL_INVALID_ARG_SIZE);
CL_ERROR(CL_INVALID_KERNEL_ARGS);
CL_ERROR(CL_INVALID_WORK_DIMENSION);
CL_ERROR(CL_INVALID_WORK_GROUP_SIZE);
CL_ERROR(CL_INVALID_WORK_ITEM_SIZE);
CL_ERROR(CL_INVALID_GLOBAL_OFFSET);
CL_ERROR(CL_INVALID_EVENT_WAIT_LIST);
CL_ERROR(CL_INVALID_EVENT);
CL_ERROR(CL_INVALID_OPERATION);
CL_ERROR(CL_INVALID_GL_OBJECT);
CL_ERROR(CL_INVALID_BUFFER_SIZE);
CL_ERROR(CL_INVALID_MIP_LEVEL);
#undef CL_ERROR
default:
name = "Unknown error code";
}
if(!str)
str = "";
PanicAlert("OpenCL error: %s %s (%d)", str, name, error);
}
};