Skip to content

Commit 23ce38e

Browse files
authored
Merge pull request #724 from jszuppe/pr_program_with_il
Add program::create_program_with_il()
2 parents 8979846 + d1bc634 commit 23ce38e

File tree

7 files changed

+169
-1
lines changed

7 files changed

+169
-1
lines changed

include/boost/compute/detail/get_object_info.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ struct get_object_info_impl<std::vector<T> >
183183
BOOST_THROW_EXCEPTION(opencl_error(ret));
184184
}
185185

186+
if(size == 0) return std::vector<T>();
187+
186188
std::vector<T> vector(size / sizeof(T));
187189
ret = function(info, size, &vector[0], 0);
188190
if(ret != CL_SUCCESS){

include/boost/compute/program.hpp

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,14 @@ class program
179179
return binary;
180180
}
181181

182+
#if defined(BOOST_COMPUTE_CL_VERSION_2_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
183+
/// Returns the SPIR-V binary for the program.
184+
std::vector<unsigned char> il_binary() const
185+
{
186+
return get_info<std::vector<unsigned char> >(CL_PROGRAM_IL);
187+
}
188+
#endif // BOOST_COMPUTE_CL_VERSION_2_1
189+
182190
std::vector<device> get_devices() const
183191
{
184192
std::vector<cl_device_id> device_ids =
@@ -318,7 +326,6 @@ class program
318326
);
319327
}
320328

321-
322329
if(ret != CL_SUCCESS){
323330
BOOST_THROW_EXCEPTION(opencl_error(ret));
324331
}
@@ -574,6 +581,65 @@ class program
574581
}
575582
#endif // BOOST_COMPUTE_CL_VERSION_1_2
576583

584+
#if defined(BOOST_COMPUTE_CL_VERSION_2_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
585+
/// Creates a new program with \p il_binary (SPIR-V binary)
586+
/// of \p il_size size in \p context.
587+
///
588+
/// \opencl_version_warning{2,1}
589+
///
590+
/// \see_opencl_ref{clCreateProgramWithIL}
591+
static program create_with_il(const void * il_binary,
592+
const size_t il_size,
593+
const context &context)
594+
{
595+
cl_int error = 0;
596+
597+
cl_program program_ = clCreateProgramWithIL(
598+
context.get(), il_binary, il_size, &error
599+
);
600+
601+
if(!program_){
602+
BOOST_THROW_EXCEPTION(opencl_error(error));
603+
}
604+
605+
return program(program_, false);
606+
}
607+
608+
/// Creates a new program with \p il_binary (SPIR-V binary)
609+
/// in \p context.
610+
///
611+
/// \opencl_version_warning{2,1}
612+
///
613+
/// \see_opencl_ref{clCreateProgramWithIL}
614+
static program create_with_il(const std::vector<unsigned char> &il_binary,
615+
const context &context)
616+
{
617+
return create_with_il(&il_binary[0], il_binary.size(), context);
618+
}
619+
620+
/// Creates a new program in \p context using SPIR-V
621+
/// binary \p file.
622+
///
623+
/// \opencl_version_warning{2,1}
624+
///
625+
/// \see_opencl_ref{clCreateProgramWithIL}
626+
static program create_with_il_file(const std::string &file,
627+
const context &context)
628+
{
629+
// open file stream
630+
std::ifstream stream(file.c_str(), std::ios::in | std::ios::binary);
631+
632+
// read binary
633+
std::vector<unsigned char> il(
634+
(std::istreambuf_iterator<char>(stream)),
635+
std::istreambuf_iterator<char>()
636+
);
637+
638+
// create program
639+
return create_with_il(&il[0], il.size(), context);
640+
}
641+
#endif // BOOST_COMPUTE_CL_VERSION_2_1
642+
577643
/// Create a new program with \p source in \p context and builds it with \p options.
578644
/**
579645
* In case BOOST_COMPUTE_USE_OFFLINE_CACHE macro is defined,
@@ -701,6 +767,12 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(program,
701767
)
702768
#endif // BOOST_COMPUTE_CL_VERSION_1_2
703769

770+
#ifdef BOOST_COMPUTE_CL_VERSION_2_1
771+
BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(program,
772+
((std::vector<unsigned char>, CL_PROGRAM_IL))
773+
)
774+
#endif // BOOST_COMPUTE_CL_VERSION_2_1
775+
704776
} // end compute namespace
705777
} // end boost namespace
706778

test/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ if(${BOOST_COMPUTE_ENABLE_COVERAGE} AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU
5050
add_definitions(-fprofile-arcs -ftest-coverage)
5151
endif()
5252

53+
# add path to test data dir
54+
add_definitions(-DBOOST_COMPUTE_TEST_DATA_PATH="${CMAKE_CURRENT_SOURCE_DIR}/data")
55+
5356
function(add_compute_test TEST_NAME TEST_SOURCE)
5457
get_filename_component(TEST_TARGET ${TEST_SOURCE} NAME_WE)
5558
add_executable(${TEST_TARGET} ${TEST_SOURCE})

test/data/program.cl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//---------------------------------------------------------------------------//
2+
// Copyright (c) 2017 Jakub Szuppe <j.szuppe@gmail.com>
3+
//
4+
// Distributed under the Boost Software License, Version 1.0
5+
// See accompanying file LICENSE_1_0.txt or copy at
6+
// http://www.boost.org/LICENSE_1_0.txt
7+
//
8+
// See http://boostorg.github.com/compute for more information.
9+
//---------------------------------------------------------------------------//
10+
11+
__kernel void foobar(__global int* x)
12+
{
13+
const int gid = get_global_id(0);
14+
x[gid] = gid;
15+
}

test/data/program.spirv32

472 Bytes
Binary file not shown.

test/data/program.spirv64

528 Bytes
Binary file not shown.

test/test_program.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,82 @@ BOOST_AUTO_TEST_CASE(create_with_binary)
126126
BOOST_CHECK_EQUAL(binary_bar_kernel.name(), std::string("bar"));
127127
}
128128

129+
#ifdef BOOST_COMPUTE_CL_VERSION_2_1
130+
BOOST_AUTO_TEST_CASE(create_with_il)
131+
{
132+
size_t device_address_space_size = device.address_bits();
133+
std::string file_path(BOOST_COMPUTE_TEST_DATA_PATH);
134+
if(device_address_space_size == 64)
135+
{
136+
file_path += "/program.spirv64";
137+
}
138+
else
139+
{
140+
file_path += "/program.spirv32";
141+
}
142+
143+
// create program from il
144+
boost::compute::program il_program;
145+
BOOST_CHECK_NO_THROW(
146+
il_program = boost::compute::program::create_with_il_file(
147+
file_path, context
148+
)
149+
);
150+
BOOST_CHECK_NO_THROW(il_program.build());
151+
152+
// create kernel (to check if program was loaded correctly)
153+
BOOST_CHECK_NO_THROW(il_program.create_kernel("foobar"));
154+
}
155+
156+
BOOST_AUTO_TEST_CASE(get_program_il_binary)
157+
{
158+
size_t device_address_space_size = device.address_bits();
159+
std::string file_path(BOOST_COMPUTE_TEST_DATA_PATH);
160+
if(device_address_space_size == 64)
161+
{
162+
file_path += "/program.spirv64";
163+
}
164+
else
165+
{
166+
file_path += "/program.spirv32";
167+
}
168+
169+
// create program from il
170+
boost::compute::program il_program;
171+
BOOST_CHECK_NO_THROW(
172+
il_program = boost::compute::program::create_with_il_file(
173+
file_path, context
174+
)
175+
);
176+
BOOST_CHECK_NO_THROW(il_program.build());
177+
178+
std::vector<unsigned char> il_binary;
179+
BOOST_CHECK_NO_THROW(il_binary = il_program.il_binary());
180+
181+
// create program from loaded il binary
182+
BOOST_CHECK_NO_THROW(
183+
il_program = boost::compute::program::create_with_il(il_binary, context)
184+
);
185+
BOOST_CHECK_NO_THROW(il_program.build());
186+
187+
// create kernel (to check if program was loaded correctly)
188+
BOOST_CHECK_NO_THROW(il_program.create_kernel("foobar"));
189+
}
190+
191+
BOOST_AUTO_TEST_CASE(get_program_il_binary_empty)
192+
{
193+
boost::compute::program program;
194+
BOOST_CHECK_NO_THROW(
195+
program = boost::compute::program::create_with_source(source, context)
196+
);
197+
BOOST_CHECK_NO_THROW(program.build());
198+
199+
std::vector<unsigned char> il_binary;
200+
il_binary = program.il_binary();
201+
BOOST_CHECK(il_binary.empty());
202+
}
203+
#endif // BOOST_COMPUTE_CL_VERSION_2_1
204+
129205
BOOST_AUTO_TEST_CASE(create_with_source_doctest)
130206
{
131207
//! [create_with_source]

0 commit comments

Comments
 (0)