1*6467f958SSadaf Ebrahimi //
2*6467f958SSadaf Ebrahimi // Copyright (c) 2017 The Khronos Group Inc.
3*6467f958SSadaf Ebrahimi //
4*6467f958SSadaf Ebrahimi // Licensed under the Apache License, Version 2.0 (the "License");
5*6467f958SSadaf Ebrahimi // you may not use this file except in compliance with the License.
6*6467f958SSadaf Ebrahimi // You may obtain a copy of the License at
7*6467f958SSadaf Ebrahimi //
8*6467f958SSadaf Ebrahimi // http://www.apache.org/licenses/LICENSE-2.0
9*6467f958SSadaf Ebrahimi //
10*6467f958SSadaf Ebrahimi // Unless required by applicable law or agreed to in writing, software
11*6467f958SSadaf Ebrahimi // distributed under the License is distributed on an "AS IS" BASIS,
12*6467f958SSadaf Ebrahimi // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6467f958SSadaf Ebrahimi // See the License for the specific language governing permissions and
14*6467f958SSadaf Ebrahimi // limitations under the License.
15*6467f958SSadaf Ebrahimi //
16*6467f958SSadaf Ebrahimi
17*6467f958SSadaf Ebrahimi #include "setup.h"
18*6467f958SSadaf Ebrahimi #include "testBase.h"
19*6467f958SSadaf Ebrahimi #include "harness/errorHelpers.h"
20*6467f958SSadaf Ebrahimi
21*6467f958SSadaf Ebrahimi #include <CL/cl_ext.h>
22*6467f958SSadaf Ebrahimi
23*6467f958SSadaf Ebrahimi typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetGLContextInfoKHR_fn)(
24*6467f958SSadaf Ebrahimi const cl_context_properties *properties,
25*6467f958SSadaf Ebrahimi cl_gl_context_info param_name,
26*6467f958SSadaf Ebrahimi size_t param_value_size,
27*6467f958SSadaf Ebrahimi void *param_value,
28*6467f958SSadaf Ebrahimi size_t *param_value_size_ret);
29*6467f958SSadaf Ebrahimi
30*6467f958SSadaf Ebrahimi // Rename references to this dynamically linked function to avoid
31*6467f958SSadaf Ebrahimi // collision with static link version
32*6467f958SSadaf Ebrahimi #define clGetGLContextInfoKHR clGetGLContextInfoKHR_proc
33*6467f958SSadaf Ebrahimi static clGetGLContextInfoKHR_fn clGetGLContextInfoKHR;
34*6467f958SSadaf Ebrahimi
35*6467f958SSadaf Ebrahimi #define MAX_DEVICES 32
36*6467f958SSadaf Ebrahimi
37*6467f958SSadaf Ebrahimi class WGLEnvironment : public GLEnvironment
38*6467f958SSadaf Ebrahimi {
39*6467f958SSadaf Ebrahimi private:
40*6467f958SSadaf Ebrahimi cl_device_id m_devices[MAX_DEVICES];
41*6467f958SSadaf Ebrahimi int m_device_count;
42*6467f958SSadaf Ebrahimi cl_platform_id m_platform;
43*6467f958SSadaf Ebrahimi bool m_is_glut_init;
44*6467f958SSadaf Ebrahimi
45*6467f958SSadaf Ebrahimi public:
WGLEnvironment()46*6467f958SSadaf Ebrahimi WGLEnvironment()
47*6467f958SSadaf Ebrahimi {
48*6467f958SSadaf Ebrahimi m_device_count = 0;
49*6467f958SSadaf Ebrahimi m_platform = 0;
50*6467f958SSadaf Ebrahimi m_is_glut_init = false;
51*6467f958SSadaf Ebrahimi }
Init(int * argc,char ** argv,int use_opengl_32)52*6467f958SSadaf Ebrahimi virtual int Init( int *argc, char **argv, int use_opengl_32 )
53*6467f958SSadaf Ebrahimi {
54*6467f958SSadaf Ebrahimi if (!m_is_glut_init)
55*6467f958SSadaf Ebrahimi {
56*6467f958SSadaf Ebrahimi // Create a GLUT window to render into
57*6467f958SSadaf Ebrahimi glutInit( argc, argv );
58*6467f958SSadaf Ebrahimi glutInitWindowSize( 512, 512 );
59*6467f958SSadaf Ebrahimi glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
60*6467f958SSadaf Ebrahimi glutCreateWindow( "OpenCL <-> OpenGL Test" );
61*6467f958SSadaf Ebrahimi glewInit();
62*6467f958SSadaf Ebrahimi m_is_glut_init = true;
63*6467f958SSadaf Ebrahimi }
64*6467f958SSadaf Ebrahimi return 0;
65*6467f958SSadaf Ebrahimi }
66*6467f958SSadaf Ebrahimi
CreateCLContext(void)67*6467f958SSadaf Ebrahimi virtual cl_context CreateCLContext( void )
68*6467f958SSadaf Ebrahimi {
69*6467f958SSadaf Ebrahimi HGLRC hGLRC = wglGetCurrentContext();
70*6467f958SSadaf Ebrahimi HDC hDC = wglGetCurrentDC();
71*6467f958SSadaf Ebrahimi cl_context_properties properties[] = {
72*6467f958SSadaf Ebrahimi CL_CONTEXT_PLATFORM, (cl_context_properties) m_platform,
73*6467f958SSadaf Ebrahimi CL_GL_CONTEXT_KHR, (cl_context_properties) hGLRC,
74*6467f958SSadaf Ebrahimi CL_WGL_HDC_KHR, (cl_context_properties) hDC,
75*6467f958SSadaf Ebrahimi 0
76*6467f958SSadaf Ebrahimi };
77*6467f958SSadaf Ebrahimi cl_device_id devices[MAX_DEVICES];
78*6467f958SSadaf Ebrahimi size_t dev_size;
79*6467f958SSadaf Ebrahimi cl_int status;
80*6467f958SSadaf Ebrahimi
81*6467f958SSadaf Ebrahimi if (!hGLRC || !hDC) {
82*6467f958SSadaf Ebrahimi print_error(CL_INVALID_CONTEXT, "No GL context bound");
83*6467f958SSadaf Ebrahimi return 0;
84*6467f958SSadaf Ebrahimi }
85*6467f958SSadaf Ebrahimi
86*6467f958SSadaf Ebrahimi if (!clGetGLContextInfoKHR) {
87*6467f958SSadaf Ebrahimi // As OpenCL for the platforms. Warn if more than one platform found,
88*6467f958SSadaf Ebrahimi // since this might not be the platform we want. By default, we simply
89*6467f958SSadaf Ebrahimi // use the first returned platform.
90*6467f958SSadaf Ebrahimi
91*6467f958SSadaf Ebrahimi cl_uint nplatforms;
92*6467f958SSadaf Ebrahimi cl_platform_id platform;
93*6467f958SSadaf Ebrahimi clGetPlatformIDs(0, NULL, &nplatforms);
94*6467f958SSadaf Ebrahimi clGetPlatformIDs(1, &platform, NULL);
95*6467f958SSadaf Ebrahimi
96*6467f958SSadaf Ebrahimi if (nplatforms > 1) {
97*6467f958SSadaf Ebrahimi log_info("clGetPlatformIDs returned multiple values. This is not "
98*6467f958SSadaf Ebrahimi "an error, but might result in obtaining incorrect function "
99*6467f958SSadaf Ebrahimi "pointers if you do not want the first returned platform.\n");
100*6467f958SSadaf Ebrahimi
101*6467f958SSadaf Ebrahimi // Show them the platform name, in case it is a problem.
102*6467f958SSadaf Ebrahimi
103*6467f958SSadaf Ebrahimi size_t size;
104*6467f958SSadaf Ebrahimi char *name;
105*6467f958SSadaf Ebrahimi
106*6467f958SSadaf Ebrahimi clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size);
107*6467f958SSadaf Ebrahimi name = (char*)malloc(size);
108*6467f958SSadaf Ebrahimi clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, name, NULL);
109*6467f958SSadaf Ebrahimi
110*6467f958SSadaf Ebrahimi log_info("Using platform with name: %s \n", name);
111*6467f958SSadaf Ebrahimi free(name);
112*6467f958SSadaf Ebrahimi }
113*6467f958SSadaf Ebrahimi
114*6467f958SSadaf Ebrahimi clGetGLContextInfoKHR = (clGetGLContextInfoKHR_fn) clGetExtensionFunctionAddressForPlatform(platform, "clGetGLContextInfoKHR");
115*6467f958SSadaf Ebrahimi if (!clGetGLContextInfoKHR) {
116*6467f958SSadaf Ebrahimi print_error(CL_INVALID_PLATFORM, "Failed to query proc address for clGetGLContextInfoKHR");
117*6467f958SSadaf Ebrahimi }
118*6467f958SSadaf Ebrahimi }
119*6467f958SSadaf Ebrahimi
120*6467f958SSadaf Ebrahimi status = clGetGLContextInfoKHR(properties,
121*6467f958SSadaf Ebrahimi CL_DEVICES_FOR_GL_CONTEXT_KHR,
122*6467f958SSadaf Ebrahimi sizeof(devices),
123*6467f958SSadaf Ebrahimi devices,
124*6467f958SSadaf Ebrahimi &dev_size);
125*6467f958SSadaf Ebrahimi if (status != CL_SUCCESS) {
126*6467f958SSadaf Ebrahimi print_error(status, "clGetGLContextInfoKHR failed");
127*6467f958SSadaf Ebrahimi return 0;
128*6467f958SSadaf Ebrahimi }
129*6467f958SSadaf Ebrahimi dev_size /= sizeof(cl_device_id);
130*6467f958SSadaf Ebrahimi log_info("GL context supports %d compute devices\n", dev_size);
131*6467f958SSadaf Ebrahimi
132*6467f958SSadaf Ebrahimi status = clGetGLContextInfoKHR(properties,
133*6467f958SSadaf Ebrahimi CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
134*6467f958SSadaf Ebrahimi sizeof(devices),
135*6467f958SSadaf Ebrahimi devices,
136*6467f958SSadaf Ebrahimi &dev_size);
137*6467f958SSadaf Ebrahimi if (status != CL_SUCCESS) {
138*6467f958SSadaf Ebrahimi print_error(status, "clGetGLContextInfoKHR failed");
139*6467f958SSadaf Ebrahimi return 0;
140*6467f958SSadaf Ebrahimi }
141*6467f958SSadaf Ebrahimi
142*6467f958SSadaf Ebrahimi cl_device_id ctxDevice = m_devices[0];
143*6467f958SSadaf Ebrahimi if (dev_size > 0) {
144*6467f958SSadaf Ebrahimi log_info("GL context current device: 0x%x\n", devices[0]);
145*6467f958SSadaf Ebrahimi for (int i = 0; i < m_device_count; i++) {
146*6467f958SSadaf Ebrahimi if (m_devices[i] == devices[0]) {
147*6467f958SSadaf Ebrahimi ctxDevice = devices[0];
148*6467f958SSadaf Ebrahimi break;
149*6467f958SSadaf Ebrahimi }
150*6467f958SSadaf Ebrahimi }
151*6467f958SSadaf Ebrahimi } else {
152*6467f958SSadaf Ebrahimi log_info("GL context current device is not a CL device, using device %d.\n", ctxDevice);
153*6467f958SSadaf Ebrahimi }
154*6467f958SSadaf Ebrahimi
155*6467f958SSadaf Ebrahimi return clCreateContext(properties, 1, &ctxDevice, NULL, NULL, &status);
156*6467f958SSadaf Ebrahimi }
157*6467f958SSadaf Ebrahimi
SupportsCLGLInterop(cl_device_type device_type)158*6467f958SSadaf Ebrahimi virtual int SupportsCLGLInterop( cl_device_type device_type )
159*6467f958SSadaf Ebrahimi {
160*6467f958SSadaf Ebrahimi cl_device_id devices[MAX_DEVICES];
161*6467f958SSadaf Ebrahimi cl_uint num_of_devices;
162*6467f958SSadaf Ebrahimi int error;
163*6467f958SSadaf Ebrahimi error = clGetPlatformIDs(1, &m_platform, NULL);
164*6467f958SSadaf Ebrahimi if (error) {
165*6467f958SSadaf Ebrahimi print_error(error, "clGetPlatformIDs failed");
166*6467f958SSadaf Ebrahimi return -1;
167*6467f958SSadaf Ebrahimi }
168*6467f958SSadaf Ebrahimi error = clGetDeviceIDs(m_platform, device_type, MAX_DEVICES, devices, &num_of_devices);
169*6467f958SSadaf Ebrahimi if (error) {
170*6467f958SSadaf Ebrahimi print_error(error, "clGetDeviceIDs failed");
171*6467f958SSadaf Ebrahimi return -1;
172*6467f958SSadaf Ebrahimi }
173*6467f958SSadaf Ebrahimi
174*6467f958SSadaf Ebrahimi // Check all devices, search for one that supports cl_khr_gl_sharing
175*6467f958SSadaf Ebrahimi for (int i=0; i<(int)num_of_devices; i++) {
176*6467f958SSadaf Ebrahimi if (!is_extension_available(devices[i], "cl_khr_gl_sharing")) {
177*6467f958SSadaf Ebrahimi log_info("Device %d of %d does not support required extension cl_khr_gl_sharing.\n", i+1, num_of_devices);
178*6467f958SSadaf Ebrahimi } else {
179*6467f958SSadaf Ebrahimi log_info("Device %d of %d supports required extension cl_khr_gl_sharing.\n", i+1, num_of_devices);
180*6467f958SSadaf Ebrahimi m_devices[m_device_count++] = devices[i];
181*6467f958SSadaf Ebrahimi }
182*6467f958SSadaf Ebrahimi }
183*6467f958SSadaf Ebrahimi return m_device_count > 0;
184*6467f958SSadaf Ebrahimi }
185*6467f958SSadaf Ebrahimi
~WGLEnvironment()186*6467f958SSadaf Ebrahimi virtual ~WGLEnvironment()
187*6467f958SSadaf Ebrahimi {
188*6467f958SSadaf Ebrahimi }
189*6467f958SSadaf Ebrahimi };
190*6467f958SSadaf Ebrahimi
Instance(void)191*6467f958SSadaf Ebrahimi GLEnvironment * GLEnvironment::Instance( void )
192*6467f958SSadaf Ebrahimi {
193*6467f958SSadaf Ebrahimi static WGLEnvironment * env = NULL;
194*6467f958SSadaf Ebrahimi if( env == NULL )
195*6467f958SSadaf Ebrahimi env = new WGLEnvironment();
196*6467f958SSadaf Ebrahimi return env;
197*6467f958SSadaf Ebrahimi }
198