memo / ofxMSAOpenCL

C++ openFrameworks addon for very simple to use wrapper for OpenCL. All underlying openCL objects are accessible to allow advanced features too if need be
http://www.memo.tv/ofxmsaopencl/
Other
88 stars 35 forks source link

setupFromOpenGL failure on Windows 10 #23

Open sam-mcelhinney opened 5 years ago

sam-mcelhinney commented 5 years ago

I’m using Windows 10 and Visual Studio 17. The machine has an integrated intel GPU and also an Nvidia GeForce GTX 1050

When compiling and calling setupFromOpenGL I get an error failure (error creating clContext) about 2/3rds of the time. The rest of the time the clContext returns and runs successfully. Looking at the errorcode number it is -1000, which I think translates as 'CL and GL not on the same device’.

This is a new issue - I’ve been compiling the same app fine for about two years up until now. Any suggestions on how to fix? It is kind of frustrating.

tobiasebsen commented 5 years ago

Hi Sam. I've had the same issue. It seems that the order of devices may change from time to time when you run your application. That means that you can't simply initialize the same device id every time. You need the check the name of the device and open the device id associated with that device name.

I made this method to cope with the non-ordered device list:


bool setup(string vendorName, string deviceName) {
int n = opencl.getDeviceInfos();
    for (int i=0; i<n; i++) {
        if ((string((char*)opencl.deviceInfo[i].vendorName).find(vendorName) != string::npos && deviceName == "") ||
            string((char*)opencl.deviceInfo[i].deviceName) == deviceName) {
            ofLog() << "Setting up OpenCL...";
            ofLog() << "Vendor: " << opencl.deviceInfo[i].vendorName;
            ofLog() << "Device: " << opencl.deviceInfo[i].deviceName;
            setupFromOpenGL(i);
            return true;
        }
    }
    return false;
}
sam-mcelhinney commented 5 years ago

Hi Tobias,

Thanks for the quick response. I understand the issue here. But, with your method, do you have to know the vendor and device name before you call the setup function? How would you do this across multiple machines etc?

[edit] I guess another way of putting this would be, is there a method for finding which device is the ‘live’ one for the OpenGL, just before running setup?

sam-mcelhinney commented 5 years ago

Ok, I’ve made a few tweaks

Firstly, in the createQueue function; added an ‘else’ as the function to call isSetup as true. Without this the declaration of being setup was being made in all circumstances where a queue was attempted. So a brute force cycle through all the devices seeing which one sets up correctly couldn’t be done, as later devices don’t even try to set up a context.

void OpenCL::createQueue() { int err = 0; clQueue = clCreateCommandQueue(clContext, clDevice, 0, &err); if(clQueue == NULL || err != CL_SUCCESS ) { ofLog(OF_LOG_ERROR, "Error creating command queue."); } else isSetup = true; currentOpenCL = this; }

I also moved the isSetup bool to public, so I can check it easily at the end of each setup attempt.

Then I did some searching. The function glGetString(GL_RENDERER) sort of returns the device that is being used for the GL context but the end of it usually differs from the CL device name: e.g. AMD Radeon Pro 560 Compute Engine // AMD Radeon Pro 560 OpenGL Engine

So next I wrote the following function to look for a close match between the two before attempting the openCl setup:

` string GL_deviceName = string((char*)glGetString(GL_RENDERER));

int n = opencl.getDeviceInfos();
for (int i=0; i<n; i++){
    string CL_deviceName = string((char*)opencl.deviceInfo[i].deviceName);
    int match = 0;
    for(int j = 0; j<CL_deviceName.size(); j++){
        if(j<GL_deviceName.size()){
            if(CL_deviceName[j] == GL_deviceName[j]) match++;
            else break;
        }}
    if(match>5) opencl.setupFromOpenGL(i);
    if(opencl.isSetup) break;
}`

It is a bit basic as it only tests the first five letters of the device names, but I figured in most cases one will be intel and one will be something else. Hmmm, probably there is a more precise way but it will do for now. Improvements welcome!

Seems to work on my Mac, about to test on PC. S