Skip to content

Commit 6cc5a73

Browse files
committed
add a global variable pointer sample
1 parent aafd72f commit 6cc5a73

3 files changed

Lines changed: 249 additions & 0 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright (c) 2025 Ben Ashbaugh
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
add_opencl_sample(
6+
TEST
7+
NUMBER 99
8+
TARGET globalvar
9+
VERSION 210
10+
SOURCES main.cpp)

samples/99_globalvar/main.cpp

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
/*
2+
// Copyright (c) 2019-2025 Ben Ashbaugh
3+
//
4+
// SPDX-License-Identifier: MIT
5+
*/
6+
7+
#include <popl/popl.hpp>
8+
9+
#include <CL/opencl.hpp>
10+
11+
#include <fstream>
12+
#include <string>
13+
14+
#include "util.hpp"
15+
16+
static std::vector<cl_uchar> readSPIRVFromFile(
17+
const std::string& filename )
18+
{
19+
std::ifstream is(filename, std::ios::binary);
20+
std::vector<cl_uchar> ret;
21+
if (!is.good()) {
22+
printf("Couldn't open file '%s'!\n", filename.c_str());
23+
return ret;
24+
}
25+
26+
size_t filesize = 0;
27+
is.seekg(0, std::ios::end);
28+
filesize = (size_t)is.tellg();
29+
is.seekg(0, std::ios::beg);
30+
31+
ret.reserve(filesize);
32+
ret.insert(
33+
ret.begin(),
34+
std::istreambuf_iterator<char>(is),
35+
std::istreambuf_iterator<char>() );
36+
37+
return ret;
38+
}
39+
40+
static cl::Program createProgramWithIL(
41+
const cl::Context& context,
42+
const std::vector<cl_uchar>& il )
43+
{
44+
cl_program program = nullptr;
45+
46+
// Use the core clCreateProgramWithIL if a device supports OpenCL 2.1 or
47+
// newer and SPIR-V.
48+
bool useCore = false;
49+
50+
// Use the extension clCreateProgramWithILKHR if a device supports
51+
// cl_khr_il_program.
52+
bool useExtension = false;
53+
54+
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
55+
for (auto device : devices) {
56+
#ifdef CL_VERSION_2_1
57+
// Note: This could look for "SPIR-V" in CL_DEVICE_IL_VERSION.
58+
if (getDeviceOpenCLVersion(device) >= CL_MAKE_VERSION(2, 1, 0) &&
59+
!device.getInfo<CL_DEVICE_IL_VERSION>().empty()) {
60+
useCore = true;
61+
}
62+
#endif
63+
if (checkDeviceForExtension(device, "cl_khr_il_program")) {
64+
useExtension = true;
65+
}
66+
}
67+
68+
#ifdef CL_VERSION_2_1
69+
if (useCore) {
70+
program = clCreateProgramWithIL(
71+
context(),
72+
il.data(),
73+
il.size(),
74+
nullptr);
75+
}
76+
else
77+
#endif
78+
if (useExtension) {
79+
cl::Platform platform{ devices[0].getInfo<CL_DEVICE_PLATFORM>() };
80+
81+
auto clCreateProgramWithILKHR_ = (clCreateProgramWithILKHR_fn)
82+
clGetExtensionFunctionAddressForPlatform(
83+
platform(),
84+
"clCreateProgramWithILKHR");
85+
86+
if (clCreateProgramWithILKHR_) {
87+
program = clCreateProgramWithILKHR_(
88+
context(),
89+
il.data(),
90+
il.size(),
91+
nullptr);
92+
}
93+
}
94+
95+
return cl::Program{ program };
96+
}
97+
98+
int main(
99+
int argc,
100+
char** argv )
101+
{
102+
int platformIndex = 0;
103+
int deviceIndex = 0;
104+
105+
std::string fileName(sizeof(void*) == 8 ? "sample_kernel64.spv" : "sample_kernel32.spv");
106+
std::string buildOptions;
107+
108+
{
109+
popl::OptionParser op("Supported Options");
110+
op.add<popl::Value<int>>("p", "platform", "Platform Index", platformIndex, &platformIndex);
111+
op.add<popl::Value<int>>("d", "device", "Device Index", deviceIndex, &deviceIndex);
112+
op.add<popl::Value<std::string>>("", "file", "Kernel File Name", fileName, &fileName);
113+
op.add<popl::Value<std::string>>("", "options", "Program Build Options", buildOptions, &buildOptions);
114+
bool printUsage = false;
115+
try {
116+
op.parse(argc, argv);
117+
} catch (std::exception& e) {
118+
fprintf(stderr, "Error: %s\n\n", e.what());
119+
printUsage = true;
120+
}
121+
122+
if (printUsage || !op.unknown_options().empty() || !op.non_option_args().empty()) {
123+
fprintf(stderr,
124+
"Usage: globalvar [options]\n"
125+
"%s", op.help().c_str());
126+
return -1;
127+
}
128+
}
129+
130+
std::vector<cl::Platform> platforms;
131+
cl::Platform::get(&platforms);
132+
cl::Platform& platform = platforms[platformIndex];
133+
134+
printf("Running on platform: %s\n",
135+
platform.getInfo<CL_PLATFORM_NAME>().c_str() );
136+
137+
std::vector<cl::Device> devices;
138+
platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);
139+
cl::Device& device = devices[deviceIndex];
140+
141+
printf("Running on device: %s\n",
142+
device.getInfo<CL_DEVICE_NAME>().c_str() );
143+
printf("CL_DEVICE_ADDRESS_BITS is %d for this device.\n",
144+
device.getInfo<CL_DEVICE_ADDRESS_BITS>() );
145+
146+
// Check for SPIR-V support. If the device supports OpenCL 2.1 or newer
147+
// we can use the core clCreateProgramWithIL API. Otherwise, if the device
148+
// the cl_khr_il_program extension we can use the clCreateProgramWithILKHR
149+
// extension API. If neither is supported then we cannot run this sample.
150+
#ifdef CL_VERSION_2_1
151+
// Note: This could look for "SPIR-V" in CL_DEVICE_IL_VERSION.
152+
if (getDeviceOpenCLVersion(device) >= CL_MAKE_VERSION(2, 1, 0) &&
153+
!device.getInfo<CL_DEVICE_IL_VERSION>().empty()) {
154+
printf("Device supports OpenCL 2.1 or newer, using clCreateProgramWithIL.\n");
155+
} else
156+
#endif
157+
if (checkDeviceForExtension(device, "cl_khr_il_program")) {
158+
printf("Device supports cl_khr_il_program, using clCreateProgramWithILKHR.\n");
159+
} else {
160+
printf("Device does not support SPIR-V, exiting.\n");
161+
return -1;
162+
}
163+
164+
cl::Context context{device};
165+
cl::CommandQueue commandQueue{context, device};
166+
167+
printf("Reading SPIR-V from file: %s\n", fileName.c_str());
168+
std::vector<cl_uchar> spirv = readSPIRVFromFile(fileName);
169+
170+
printf("Building program with build options: %s\n",
171+
buildOptions.empty() ? "(none)" : buildOptions.c_str() );
172+
cl::Program program = createProgramWithIL( context, spirv );
173+
program.build(buildOptions.c_str());
174+
for( auto& device : program.getInfo<CL_PROGRAM_DEVICES>() )
175+
{
176+
printf("Program build log for device %s:\n",
177+
device.getInfo<CL_DEVICE_NAME>().c_str() );
178+
printf("%s\n",
179+
program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device).c_str() );
180+
}
181+
182+
typedef cl_int CL_API_CALL
183+
clGetDeviceGlobalVariablePointerINTEL_t(
184+
cl_device_id device,
185+
cl_program program,
186+
const char *globalVariableName,
187+
size_t *globalVariableSizeRet,
188+
void **globalVariablePointerRet);
189+
190+
typedef clGetDeviceGlobalVariablePointerINTEL_t *
191+
clGetDeviceGlobalVariablePointerINTEL_fn;
192+
193+
typedef cl_int CL_API_CALL
194+
clGetMemAllocInfoINTEL_t(
195+
cl_context context,
196+
const void* ptr,
197+
cl_mem_info_intel param_name,
198+
size_t param_value_size,
199+
void* param_value,
200+
size_t* param_value_size_ret);
201+
202+
typedef clGetMemAllocInfoINTEL_t *
203+
clGetMemAllocInfoINTEL_fn ;
204+
205+
auto clGetDeviceGlobalVariablePointerINTEL = (clGetDeviceGlobalVariablePointerINTEL_fn)
206+
clGetExtensionFunctionAddressForPlatform(platform(), "clGetDeviceGlobalVariablePointerINTEL");
207+
208+
auto clGetMemAllocInfoINTEL = (clGetMemAllocInfoINTEL_fn)
209+
clGetExtensionFunctionAddressForPlatform(platform(), "clGetMemAllocInfoINTEL");
210+
211+
if (clGetDeviceGlobalVariablePointerINTEL == nullptr) {
212+
printf("Couldn't get function pointer for clGetDeviceGlobalVariablePointerINTEL!\n");
213+
} else if (clGetMemAllocInfoINTEL == nullptr) {
214+
printf("Couldn't get function pointer for clGetMemAllocInfoINTEL!\n");
215+
} else {
216+
cl_int errorCode = CL_SUCCESS;
217+
size_t gvsize = 0; void* gvptr = nullptr;
218+
errorCode = clGetDeviceGlobalVariablePointerINTEL(
219+
device(), program(), "uid67f037ed289236e5____ZL2dg", &gvsize, &gvptr);
220+
printf("clGetDeviceGlobalVariablePointerINTEL with uid67f037ed289236e5____ZL2dg returned %d: %zu %p\n", errorCode, gvsize, gvptr);
221+
222+
gvsize = 0; gvptr = nullptr;
223+
errorCode = clGetDeviceGlobalVariablePointerINTEL(
224+
device(), program(), "_ZL2dg", &gvsize, &gvptr);
225+
printf("clGetDeviceGlobalVariablePointerINTEL with _ZL2dg returned %d: %zu %p\n", errorCode, gvsize, gvptr);
226+
227+
cl_unified_shared_memory_type_intel gvtype = 0;
228+
errorCode = clGetMemAllocInfoINTEL(
229+
context(), gvptr, CL_MEM_ALLOC_TYPE_INTEL, sizeof(gvtype), &gvtype, nullptr);
230+
231+
printf("clGetMemAllocInfoINTEL returned %d: %04X\n", errorCode, gvtype);
232+
}
233+
234+
printf("Done.\n");
235+
236+
return 0;
237+
}

samples/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ add_subdirectory( 06_ndrangekernelfromfile )
7878
add_subdirectory( 10_queueexperiments )
7979
add_subdirectory( 16_floatatomics )
8080

81+
add_subdirectory( 99_globalvar )
82+
8183
set(BUILD_EXTENSION_SAMPLES TRUE)
8284
if(NOT TARGET OpenCLExt)
8385
message(STATUS "Skipping Extension Samples - OpenCL Extension Loader is not found.")

0 commit comments

Comments
 (0)