context.cpp 4.39 KB
Newer Older
schultezub's avatar
schultezub committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// ================================================================================================
// 
// This file is part of the KissCL, an OpenCL C++ wrapper following the KISS principle.
// 
// Copyright (C) 2012, all rights reserved,
//      Christian Schulte zu Berge (software@cszb.net)
// 
// This library is free software; you can redistribute it and/or modify it under the terms of the 
// GNU Lesser General Public License version 3 as published by the Free Software Foundation.
// 
// 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 in the file 
// "LICENSE.txt" along with this library. If not, see <http://www.gnu.org/licenses/>.
// 
// ================================================================================================

20
21
22
23
#include "context.h"

#include "tgt/assert.h"
#include "tgt/logmanager.h"
schultezub's avatar
schultezub committed
24
25
#include "kisscl/device.h"
#include "kisscl/platform.h"
26

schultezub's avatar
schultezub committed
27
28
29
30
31
32
33
34
35
#ifdef WIN32
#include <windows.h>
#endif

#if !(defined(WIN32) || defined(__APPLE__))
#include <GL/glx.h>
#define CL_GLX_DISPLAY_KHR 0x200A
#endif

schultezub's avatar
schultezub committed
36
namespace kisscl {
37
38
39

    void CL_API_CALL clContextCallback(const char* errinfo, const void* private_info, size_t cb, void* user_data) {
        tgtAssert (user_data == 0, "user_data expected to be 0 - check what happened!");
schultezub's avatar
schultezub committed
40
        LINFOC("kisscl.Context.clContextCallback", std::string(errinfo));
41
42
    }

schultezub's avatar
schultezub committed
43
    const std::string Context::loggerCat_ = "kisscl.Context";
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118


    Context::Context(Device* device, const std::vector<ContextProperty>& properties /*= std::vector<ContextProperty>()*/)
        : CLWrapper<cl_context>(0)
        , _properties(properties)
    {
        _devices.push_back(device);
        initContext();
    }

    Context::Context(std::vector<Device*> devices, const std::vector<ContextProperty>& properties /*= std::vector<ContextProperty>()*/)
        : CLWrapper<cl_context>(0)
        , _devices(devices)
        , _properties(properties)
    {
        tgtAssert(devices.size() > 0, "Must provide at least one OpenCL device.");
        initContext();
    }


    void Context::initContext() {
        cl_int err;

        // prepare device list for API call
        cl_uint numDevices = _devices.size();
        cl_device_id* deviceIds = new cl_device_id[numDevices];
        cl_platform_id platformId = _devices[0]->getPlatform()->getId();
        for (size_t i = 0; i < numDevices; ++i) {
            deviceIds[i] = _devices[i]->getId();
            if (_devices[i]->getPlatform()->getId() != platformId) {
                LWARNING("The platforms of the given OpenCL devices differ. This results in undefined behavior!");
            }
        }

        // prepare properties list for API call
        int numProps = static_cast<int>((2 * _properties.size()) + 1); // +1 for terminating 0
        cl_context_properties* props = new cl_context_properties[numProps];
        for(size_t i = 0; i < _properties.size(); ++i) {
            props[2*i] = _properties[i]._name;
            props[(2*i) + 1] = _properties[i]._value;
        }
        props[numProps - 1] = 0;

        // API call
        _id = clCreateContext(props, numDevices, deviceIds, &clContextCallback, 0, &err);
        LCL_ERROR(err);

        // clean up
        delete[] deviceIds;
        delete[] props;
    }

    std::vector<ContextProperty> Context::generateGlSharingProperties() {
        std::vector<ContextProperty> toReturn;
#ifdef WIN32
        //Windows:
        toReturn.push_back(ContextProperty(CL_GL_CONTEXT_KHR, (cl_context_properties) wglGetCurrentContext()));
        toReturn.push_back(ContextProperty(CL_WGL_HDC_KHR, (cl_context_properties) wglGetCurrentDC()));
#elif defined(linux) || defined(__linux__)
        //Linux:
        toReturn.push_back(ContextProperty(CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext()));
        toReturn.push_back(ContextProperty(CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay()));
#endif
        return toReturn;
    }

    bool Context::isValid() const {
        return _id != 0;
    }

    const std::vector<Device*>& Context::getDevices() const {
        return _devices;
    }

}