From 3233d2089f70fffbd4d5a7d95157c61527f68b34 Mon Sep 17 00:00:00 2001 From: Marcin Hajder Date: Tue, 10 Jun 2025 17:41:20 +0200 Subject: [PATCH] Added comparability verification for GL associated devices query (#2231) Fixes #1485 according to work plan from issue description. --- test_common/gl/setup.h | 13 ++- test_common/gl/setup_osx.cpp | 131 ++++++++++++----------- test_common/gl/setup_win32.cpp | 31 ++++-- test_common/gl/setup_x11.cpp | 35 +++++-- test_conformance/gl/CMakeLists.txt | 3 +- test_conformance/gl/main.cpp | 8 +- test_conformance/gl/procs.h | 6 +- test_conformance/gl/test_queries.cpp | 150 +++++++++++++++++++++++++++ 8 files changed, 285 insertions(+), 92 deletions(-) create mode 100644 test_conformance/gl/test_queries.cpp diff --git a/test_common/gl/setup.h b/test_common/gl/setup.h index 6ee810bb..18cfee68 100644 --- a/test_common/gl/setup.h +++ b/test_common/gl/setup.h @@ -13,12 +13,13 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#ifndef _setup_h -#define _setup_h +#ifndef _gl_setup_h +#define _gl_setup_h #include #include #include +#include #include "gl_headers.h" #ifdef __APPLE__ #include @@ -36,13 +37,11 @@ class GLEnvironment GLEnvironment() {} virtual ~GLEnvironment() {} - virtual int Init( int *argc, char **argv, int use_opengl_32 ) = 0; + virtual int Init(int *argc, char **argv, int use_opengl_32) = 0; virtual cl_context CreateCLContext( void ) = 0; virtual int SupportsCLGLInterop( cl_device_type device_type) = 0; - static GLEnvironment * Instance( void ); - - + static GLEnvironment *Instance(void); }; -#endif // _setup_h +#endif // _gl_setup_h diff --git a/test_common/gl/setup_osx.cpp b/test_common/gl/setup_osx.cpp index 298f1a92..6d1b2e7d 100644 --- a/test_common/gl/setup_osx.cpp +++ b/test_common/gl/setup_osx.cpp @@ -1,6 +1,6 @@ // -// Copyright (c) 2017 The Khronos Group Inc. -// +// Copyright (c) 2024 The Khronos Group Inc. +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -25,65 +25,74 @@ private: public: OSXGLEnvironment() { - mCGLContext = NULL; mIsGlutInit = false; + mCGLContext = NULL; + mShareGroup = NULL; + mPlatform = NULL; } - virtual int Init( int *argc, char **argv, int use_opengl_32 ) + int Init(int *argc, char **argv, int use_opengl_32) override + { + if (!use_opengl_32) { - if (!use_opengl_32) { - if (!mIsGlutInit) - { - // Create a GLUT window to render into - glutInit(argc, argv); - glutInitWindowSize(512, 512); - glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); - glutCreateWindow("OpenCL <-> OpenGL Test"); - mIsGlutInit = true; - } - } - - else { - - CGLPixelFormatAttribute attribs[] = { - kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core, - kCGLPFAAllowOfflineRenderers, - kCGLPFANoRecovery, - kCGLPFAAccelerated, - kCGLPFADoubleBuffer, - (CGLPixelFormatAttribute)0 - }; - - CGLError err; - CGLPixelFormatObj pix; - GLint npix; - err = CGLChoosePixelFormat (attribs, &pix, &npix); - if(err != kCGLNoError) - { - log_error("Failed to choose pixel format\n"); - return -1; - } - err = CGLCreateContext(pix, NULL, &mCGLContext); - if(err != kCGLNoError) - { - log_error("Failed to create GL context\n"); - return -1; - } - CGLSetCurrentContext(mCGLContext); - } - - return 0; + if (!mIsGlutInit) + { + // Create a GLUT window to render into + glutInit(argc, argv); + glutInitWindowSize(512, 512); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("OpenCL <-> OpenGL Test"); + mIsGlutInit = true; + } } - virtual cl_context CreateCLContext( void ) + else + { + + CGLPixelFormatAttribute attribs[] = { + kCGLPFAOpenGLProfile, + (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core, + kCGLPFAAllowOfflineRenderers, + kCGLPFANoRecovery, + kCGLPFAAccelerated, + kCGLPFADoubleBuffer, + (CGLPixelFormatAttribute)0 + }; + + CGLError err; + CGLPixelFormatObj pix; + GLint npix; + err = CGLChoosePixelFormat(attribs, &pix, &npix); + if (err != kCGLNoError) + { + log_error("Failed to choose pixel format\n"); + return -1; + } + err = CGLCreateContext(pix, NULL, &mCGLContext); + if (err != kCGLNoError) + { + log_error("Failed to create GL context\n"); + return -1; + } + CGLSetCurrentContext(mCGLContext); + } + + return 0; + } + + cl_context CreateCLContext(void) override { int error; if( mCGLContext == NULL ) mCGLContext = CGLGetCurrentContext(); - CGLShareGroupObj share_group = CGLGetShareGroup(mCGLContext); - cl_context_properties properties[] = { CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)share_group, 0 }; + mShareGroup = CGLGetShareGroup(mCGLContext); + cl_context_properties properties[] = { + CL_CONTEXT_PLATFORM, (cl_context_properties)mPlatform, + CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, + (cl_context_properties)mShareGroup, 0 + }; cl_context context = clCreateContext(properties, 0, 0, 0, 0, &error); if (error) { print_error(error, "clCreateContext failed"); @@ -108,16 +117,24 @@ public: return context; } - virtual int SupportsCLGLInterop( cl_device_type device_type ) + int SupportsCLGLInterop(cl_device_type device_type) override { int found_valid_device = 0; cl_device_id devices[64]; cl_uint num_of_devices; int error; - error = clGetDeviceIDs(NULL, device_type, 64, devices, &num_of_devices); + error = clGetPlatformIDs(1, &mPlatform, NULL); + if (error) + { + print_error(error, "clGetPlatformIDs failed"); + return 0; + } + + error = + clGetDeviceIDs(mPlatform, device_type, 64, devices, &num_of_devices); if (error) { print_error(error, "clGetDeviceIDs failed"); - return -1; + return 0; } for (int i=0; i<(int)num_of_devices; i++) { @@ -131,13 +148,11 @@ public: return found_valid_device; } - virtual ~OSXGLEnvironment() - { - CGLDestroyContext( mCGLContext ); - } - - CGLContextObj mCGLContext; + virtual ~OSXGLEnvironment() { CGLDestroyContext(mCGLContext); } + CGLContextObj mCGLContext; + CGLShareGroupObj mShareGroup; + cl_platform_id mPlatform; }; GLEnvironment * GLEnvironment::Instance( void ) diff --git a/test_common/gl/setup_win32.cpp b/test_common/gl/setup_win32.cpp index 708e681d..d503695a 100644 --- a/test_common/gl/setup_win32.cpp +++ b/test_common/gl/setup_win32.cpp @@ -1,6 +1,6 @@ // -// Copyright (c) 2017 The Khronos Group Inc. -// +// Copyright (c) 2024 The Khronos Group Inc. +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -42,14 +42,19 @@ private: cl_platform_id m_platform; bool m_is_glut_init; + HGLRC m_hGLRC; + HDC m_hDC; + public: WGLEnvironment() { m_device_count = 0; m_platform = 0; m_is_glut_init = false; + m_hGLRC = 0; + m_hDC = 0; } - virtual int Init( int *argc, char **argv, int use_opengl_32 ) + int Init(int *argc, char **argv, int use_opengl_32) override { if (!m_is_glut_init) { @@ -64,21 +69,25 @@ public: return 0; } - virtual cl_context CreateCLContext( void ) + cl_context CreateCLContext(void) override { - HGLRC hGLRC = wglGetCurrentContext(); - HDC hDC = wglGetCurrentDC(); + m_hGLRC = wglGetCurrentContext(); + m_hDC = wglGetCurrentDC(); cl_context_properties properties[] = { - CL_CONTEXT_PLATFORM, (cl_context_properties) m_platform, - CL_GL_CONTEXT_KHR, (cl_context_properties) hGLRC, - CL_WGL_HDC_KHR, (cl_context_properties) hDC, + CL_CONTEXT_PLATFORM, + (cl_context_properties)m_platform, + CL_GL_CONTEXT_KHR, + (cl_context_properties)m_hGLRC, + CL_WGL_HDC_KHR, + (cl_context_properties)m_hDC, 0 }; cl_device_id devices[MAX_DEVICES]; size_t dev_size; cl_int status; - if (!hGLRC || !hDC) { + if (!m_hGLRC || !m_hDC) + { print_error(CL_INVALID_CONTEXT, "No GL context bound"); return 0; } @@ -155,7 +164,7 @@ public: return clCreateContext(properties, 1, &ctxDevice, NULL, NULL, &status); } - virtual int SupportsCLGLInterop( cl_device_type device_type ) + int SupportsCLGLInterop(cl_device_type device_type) override { cl_device_id devices[MAX_DEVICES]; cl_uint num_of_devices; diff --git a/test_common/gl/setup_x11.cpp b/test_common/gl/setup_x11.cpp index 3292902f..f06b8b23 100644 --- a/test_common/gl/setup_x11.cpp +++ b/test_common/gl/setup_x11.cpp @@ -28,13 +28,21 @@ private: cl_uint m_device_count; bool m_glut_init; + cl_platform_id m_platform; + GLXContext m_context; + Display *m_dpy; + public: X11GLEnvironment() { m_device_count = 0; m_glut_init = false; + m_platform = 0; + m_context = 0; + m_dpy = nullptr; } - virtual int Init( int *argc, char **argv, int use_opencl_32 ) + + int Init(int *argc, char **argv, int use_opencl_32) override { // Create a GLUT window to render into if (!m_glut_init) @@ -49,19 +57,24 @@ public: return 0; } - virtual cl_context CreateCLContext( void ) + cl_context CreateCLContext(void) override { - GLXContext context = glXGetCurrentContext(); - Display *dpy = glXGetCurrentDisplay(); + m_context = glXGetCurrentContext(); + m_dpy = glXGetCurrentDisplay(); cl_context_properties properties[] = { - CL_GL_CONTEXT_KHR, (cl_context_properties) context, - CL_GLX_DISPLAY_KHR, (cl_context_properties) dpy, + CL_CONTEXT_PLATFORM, + (cl_context_properties)m_platform, + CL_GL_CONTEXT_KHR, + (cl_context_properties)m_context, + CL_GLX_DISPLAY_KHR, + (cl_context_properties)m_dpy, 0 }; cl_int status; - if (!context || !dpy) { + if (!m_context || !m_dpy) + { print_error(CL_INVALID_CONTEXT, "No GL context bound"); return 0; } @@ -69,19 +82,19 @@ public: return clCreateContext(properties, 1, m_devices, NULL, NULL, &status); } - virtual int SupportsCLGLInterop( cl_device_type device_type ) + int SupportsCLGLInterop(cl_device_type device_type) override { int found_valid_device = 0; - cl_platform_id platform; cl_device_id devices[64]; cl_uint num_of_devices; int error; - error = clGetPlatformIDs(1, &platform, NULL); + error = clGetPlatformIDs(1, &m_platform, NULL); if (error) { print_error(error, "clGetPlatformIDs failed"); return -1; } - error = clGetDeviceIDs(platform, device_type, 64, devices, &num_of_devices); + error = clGetDeviceIDs(m_platform, device_type, 64, devices, + &num_of_devices); // If this platform doesn't have any of the requested device_type (namely GPUs) then return 0 if (error == CL_DEVICE_NOT_FOUND) return 0; diff --git a/test_conformance/gl/CMakeLists.txt b/test_conformance/gl/CMakeLists.txt index dbabe605..b4adb4d7 100644 --- a/test_conformance/gl/CMakeLists.txt +++ b/test_conformance/gl/CMakeLists.txt @@ -29,6 +29,7 @@ set (${MODULE_NAME}_SOURCES test_renderbuffer.cpp test_renderbuffer_info.cpp test_fence_sync.cpp + test_queries.cpp helpers.cpp ../../test_common/gl/helpers.cpp ) @@ -59,4 +60,4 @@ set_source_files_properties( # folder. include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -include(../CMakeCommon.txt) \ No newline at end of file +include(../CMakeCommon.txt) diff --git a/test_conformance/gl/main.cpp b/test_conformance/gl/main.cpp index e5d6b65d..43df1d19 100644 --- a/test_conformance/gl/main.cpp +++ b/test_conformance/gl/main.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 The Khronos Group Inc. +// Copyright (c) 2024 The Khronos Group Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -103,6 +103,8 @@ TEST_FN_REDIRECTOR(renderbuffer_getinfo) TEST_FN_REDIRECTOR(fence_sync) +TEST_FN_REDIRECTOR(queries) + test_definition test_list[] = { TEST_FN_REDIRECT(buffers), TEST_FN_REDIRECT(buffers_getinfo), @@ -132,7 +134,9 @@ test_definition test_list[] = { TEST_FN_REDIRECT(buffers), TEST_FN_REDIRECT(renderbuffer_read), TEST_FN_REDIRECT(renderbuffer_write), - TEST_FN_REDIRECT(renderbuffer_getinfo) }; + TEST_FN_REDIRECT(renderbuffer_getinfo), + + TEST_FN_REDIRECT(queries) }; test_definition test_list32[] = { TEST_FN_REDIRECT(images_read_texturebuffer), diff --git a/test_conformance/gl/procs.h b/test_conformance/gl/procs.h index 111de7a6..738f7c81 100644 --- a/test_conformance/gl/procs.h +++ b/test_conformance/gl/procs.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 The Khronos Group Inc. +// Copyright (c) 2024 The Khronos Group Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -150,4 +150,6 @@ extern int test_image_methods_multisample(cl_device_id device, cl_command_queue queue, int); extern int test_renderbuffer_getinfo(cl_device_id device, cl_context context, - cl_command_queue queue, int numElements); \ No newline at end of file + cl_command_queue queue, int numElements); +extern int test_queries(cl_device_id device, cl_context context, + cl_command_queue queue, int); diff --git a/test_conformance/gl/test_queries.cpp b/test_conformance/gl/test_queries.cpp new file mode 100644 index 00000000..36798ca8 --- /dev/null +++ b/test_conformance/gl/test_queries.cpp @@ -0,0 +1,150 @@ +// +// Copyright (c) 2024 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "common.h" +#include "testBase.h" +#include "gl/setup.h" + +namespace { + +struct FindDeviceFunctor +{ + FindDeviceFunctor() + { + if (init()) throw std::runtime_error("FindDeviceFunctor failed"); + } + + cl_int init() + { + cl_uint num_platforms = 0; + cl_int error = clGetPlatformIDs(0, nullptr, &num_platforms); + test_error(error, "clGetPlatformIDs failed"); + + platforms.resize(num_platforms); + + error = + clGetPlatformIDs(num_platforms, platforms.data(), &num_platforms); + test_error(error, "clGetPlatformIDs failed"); + + return CL_SUCCESS; + } + + bool find(const cl_device_id id) + { + cl_uint num_devices = 0; + for (size_t p = 0; p < platforms.size(); p++) + { + cl_int error = clGetDeviceIDs(platforms[p], CL_DEVICE_TYPE_ALL, 0, + nullptr, &num_devices); + test_error(error, "clGetDeviceIDs failed"); + + std::vector devices(num_devices); + error = clGetDeviceIDs(platforms[p], CL_DEVICE_TYPE_ALL, + num_devices, devices.data(), nullptr); + test_error(error, "clGetDeviceIDs failed"); + + for (auto did : devices) + if (did == id) return false; + } + return true; + } + std::vector platforms; +}; + +} // anonymous namespace + +int test_queries(cl_device_id device, cl_context context, + cl_command_queue queue, int) +{ + // get a platform associated with device id + cl_platform_id platform; + cl_int error = clGetDeviceInfo(device, CL_DEVICE_PLATFORM, + sizeof(cl_platform_id), &platform, NULL); + test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed"); + + size_t returned_size = 0; + error = clGetContextInfo(context, CL_CONTEXT_PROPERTIES, 0, nullptr, + &returned_size); + test_error(error, "clGetContextInfo failed"); + + std::vector props( + returned_size / sizeof(cl_context_properties), 0); + + error = clGetContextInfo(context, CL_CONTEXT_PROPERTIES, + sizeof(cl_context_properties) * props.size(), + props.data(), nullptr); + test_error(error, "clGetContextInfo failed"); + + // get GL context info function pointer + size_t dev_size = 0; + clGetGLContextInfoKHR_fn clGetGLContextInfoKHR = + (clGetGLContextInfoKHR_fn)clGetExtensionFunctionAddressForPlatform( + platform, "clGetGLContextInfoKHR"); + + test_assert_error(clGetGLContextInfoKHR != NULL, + "unable to get the function pointer for " + "clGetGLContextInfoKHR\n"); + + // get the size of all GL interop capable devices + error = clGetGLContextInfoKHR(props.data(), CL_DEVICES_FOR_GL_CONTEXT_KHR, + 0, nullptr, &dev_size); + test_error(error, + "clGetGLContextInfoKHR(CL_DEVICES_FOR_GL_CONTEXT_KHR) failed"); + + dev_size /= sizeof(cl_device_id); + log_info("GL _context supports %zu compute devices\n", dev_size); + + + // get all GL interop capable devices + std::vector devices(dev_size, 0); + error = clGetGLContextInfoKHR(props.data(), CL_DEVICES_FOR_GL_CONTEXT_KHR, + devices.size() * sizeof(cl_device_id), + devices.data(), &dev_size); + test_error(error, + "clGetGLContextInfoKHR(CL_DEVICES_FOR_GL_CONTEXT_KHR) failed"); + if (devices.size() != dev_size / sizeof(cl_device_id)) + { + log_error("unexpected clGetGLContextInfoKHR result"); + return TEST_FAIL; + } + + // comparability test for CL_DEVICES_FOR_GL_CONTEXT_KHR + FindDeviceFunctor fdf; + for (auto &did : devices) + if (fdf.find(did) != 0) return TEST_FAIL; + + // get current device associated with GL environment + error = clGetGLContextInfoKHR( + props.data(), CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, + devices.size() * sizeof(cl_device_id), devices.data(), &dev_size); + test_error( + error, + "clGetGLContextInfoKHR(CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR) failed"); + + // verify if CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR query result with only one + // device + if (dev_size != sizeof(cl_device_id)) + { + log_info("GL _context current device is not a CL device.\n"); + return TEST_FAIL; + } + + // comparability test for CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR + test_assert_error(device == devices[0], + "Unexpected result returned by clGetGLContextInfo for " + "CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR query"); + + return TEST_PASS; +}