Skip to content

Commit 9895413

Browse files
authored
[UR] Make offload program CTS tests pass (#19948)
The CTS tests for the program part of the API now pass (or are skipped). This mostly was a matter of implementing olProgramGetBuildInfo and olProgramLink (but only for one binary - specifying more than one is an error). The build failure tests have also been tweaked a bit to better reflect their optional nature.
1 parent 3274ca1 commit 9895413

File tree

5 files changed

+120
-30
lines changed

5 files changed

+120
-30
lines changed

unified-runtime/source/adapters/offload/program.cpp

Lines changed: 81 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urProgramCreateWithBinary(
9797
Program->URContext = hContext;
9898
Program->Binary = RealBinary;
9999
Program->BinarySizeInBytes = RealLength;
100+
Program->BinaryType = UR_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
100101

101102
// Parse properties
102103
if (pProperties) {
@@ -160,24 +161,68 @@ urProgramCreateWithIL(ur_context_handle_t hContext, const void *pIL,
160161
}
161162

162163
UR_APIEXPORT ur_result_t UR_APICALL urProgramBuild(ur_context_handle_t,
163-
ur_program_handle_t,
164-
const char *) {
164+
ur_program_handle_t hProgram,
165+
const char *pOptions) {
165166
// Do nothing, program is built upon creation
167+
if (pOptions && *pOptions) {
168+
hProgram->Error = "Liboffload doesn't support link options";
169+
return UR_RESULT_ERROR_PROGRAM_LINK_FAILURE;
170+
}
171+
hProgram->BinaryType = UR_PROGRAM_BINARY_TYPE_EXECUTABLE;
166172
return UR_RESULT_SUCCESS;
167173
}
168174

169-
UR_APIEXPORT ur_result_t UR_APICALL urProgramBuildExp(ur_program_handle_t,
170-
uint32_t,
171-
ur_device_handle_t *,
172-
const char *) {
175+
UR_APIEXPORT ur_result_t UR_APICALL
176+
urProgramBuildExp(ur_program_handle_t hProgram, uint32_t, ur_device_handle_t *,
177+
const char *pOptions) {
173178
// Do nothing, program is built upon creation
179+
if (pOptions && *pOptions) {
180+
hProgram->Error = "Liboffload doesn't support link options";
181+
return UR_RESULT_ERROR_PROGRAM_LINK_FAILURE;
182+
}
183+
hProgram->BinaryType = UR_PROGRAM_BINARY_TYPE_EXECUTABLE;
174184
return UR_RESULT_SUCCESS;
175185
}
176186

177-
UR_APIEXPORT ur_result_t UR_APICALL urProgramCompile(ur_context_handle_t,
178-
ur_program_handle_t,
179-
const char *) {
187+
UR_APIEXPORT ur_result_t UR_APICALL urProgramCompile(
188+
ur_context_handle_t, ur_program_handle_t hProgram, const char *pOptions) {
180189
// Do nothing, program is built upon creation
190+
if (pOptions && *pOptions) {
191+
hProgram->Error = "Liboffload doesn't support link options";
192+
return UR_RESULT_ERROR_PROGRAM_LINK_FAILURE;
193+
}
194+
hProgram->BinaryType = UR_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
195+
return UR_RESULT_SUCCESS;
196+
}
197+
198+
UR_APIEXPORT ur_result_t UR_APICALL
199+
urProgramLink(ur_context_handle_t hContext, uint32_t count,
200+
const ur_program_handle_t *phPrograms, const char *pOptions,
201+
ur_program_handle_t *phProgram) {
202+
if (count > 1) {
203+
*phProgram = ur_program_handle_t_::newErrorProgram(
204+
hContext, nullptr, 0,
205+
"Liboffload does not support linking multiple binaries");
206+
return UR_RESULT_ERROR_PROGRAM_LINK_FAILURE;
207+
}
208+
if (pOptions) {
209+
*phProgram = ur_program_handle_t_::newErrorProgram(
210+
hContext, nullptr, 0, "Liboffload does not support linker options");
211+
return UR_RESULT_ERROR_PROGRAM_LINK_FAILURE;
212+
}
213+
assert(count == 1);
214+
215+
// Offload programs are already fully linked on creation, just create a new
216+
// program containing it
217+
auto *InProgram = *phPrograms;
218+
ur_program_handle_t Program = new ur_program_handle_t_{};
219+
Program->URContext = hContext;
220+
Program->Binary = InProgram->Binary;
221+
Program->BinarySizeInBytes = InProgram->BinarySizeInBytes;
222+
Program->GlobalIDMD = InProgram->GlobalIDMD;
223+
Program->BinaryType = UR_PROGRAM_BINARY_TYPE_EXECUTABLE;
224+
*phProgram = Program;
225+
181226
return UR_RESULT_SUCCESS;
182227
}
183228

@@ -230,6 +275,28 @@ urProgramGetInfo(ur_program_handle_t hProgram, ur_program_info_t propName,
230275
return UR_RESULT_SUCCESS;
231276
}
232277

278+
UR_APIEXPORT ur_result_t UR_APICALL
279+
urProgramGetBuildInfo(ur_program_handle_t hProgram, ur_device_handle_t,
280+
ur_program_build_info_t propName, size_t propSize,
281+
void *pPropValue, size_t *pPropSizeRet) {
282+
UrReturnHelper ReturnValue(propSize, pPropValue, pPropSizeRet);
283+
switch (propName) {
284+
case UR_PROGRAM_BUILD_INFO_STATUS:
285+
return ReturnValue(hProgram->Error.empty() ? UR_PROGRAM_BUILD_STATUS_SUCCESS
286+
: UR_PROGRAM_BUILD_STATUS_ERROR);
287+
case UR_PROGRAM_BUILD_INFO_OPTIONS:
288+
return ReturnValue("");
289+
case UR_PROGRAM_BUILD_INFO_LOG:
290+
return ReturnValue(hProgram->Error.c_str());
291+
case UR_PROGRAM_BUILD_INFO_BINARY_TYPE:
292+
return ReturnValue(hProgram->BinaryType);
293+
default:
294+
return UR_RESULT_ERROR_INVALID_ENUMERATION;
295+
}
296+
297+
return UR_RESULT_SUCCESS;
298+
}
299+
233300
UR_APIEXPORT ur_result_t UR_APICALL
234301
urProgramRetain(ur_program_handle_t hProgram) {
235302
hProgram->RefCount++;
@@ -239,11 +306,12 @@ urProgramRetain(ur_program_handle_t hProgram) {
239306
UR_APIEXPORT ur_result_t UR_APICALL
240307
urProgramRelease(ur_program_handle_t hProgram) {
241308
if (--hProgram->RefCount == 0) {
242-
auto Res = olDestroyProgram(hProgram->OffloadProgram);
243-
if (Res) {
244-
return offloadResultToUR(Res);
309+
if (hProgram->OffloadProgram) {
310+
if (auto Res = olDestroyProgram(hProgram->OffloadProgram)) {
311+
return offloadResultToUR(Res);
312+
}
313+
delete hProgram;
245314
}
246-
delete hProgram;
247315
}
248316

249317
return UR_RESULT_SUCCESS;

unified-runtime/source/adapters/offload/program.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,23 @@ struct ur_program_handle_t_ : RefCounted {
2222
size_t BinarySizeInBytes;
2323
// A mapping from mangled global names -> names in the binary
2424
std::unordered_map<std::string, std::string> GlobalIDMD;
25+
// The UR offload backend doesn't draw distinctions between these types (we
26+
// always have a fully built binary), but we need to track what state we are
27+
// pretending to be in
28+
ur_program_binary_type_t BinaryType;
29+
std::string Error;
30+
31+
static ur_program_handle_t_ *newErrorProgram(ur_context_handle_t Context,
32+
const uint8_t *Binary,
33+
size_t BinarySizeInBytes,
34+
std::string &&Error) {
35+
return new ur_program_handle_t_{{},
36+
nullptr,
37+
Context,
38+
Binary,
39+
BinarySizeInBytes,
40+
{},
41+
UR_PROGRAM_BINARY_TYPE_NONE,
42+
Error};
43+
}
2544
};

unified-runtime/source/adapters/offload/ur_interface_loader.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetProgramProcAddrTable(
9090
pDdiTable->pfnCreateWithBinary = urProgramCreateWithBinary;
9191
pDdiTable->pfnCreateWithIL = urProgramCreateWithIL;
9292
pDdiTable->pfnCreateWithNativeHandle = urProgramCreateWithNativeHandle;
93-
pDdiTable->pfnGetBuildInfo = nullptr;
93+
pDdiTable->pfnGetBuildInfo = urProgramGetBuildInfo;
9494
pDdiTable->pfnGetFunctionPointer = urProgramGetFunctionPointer;
9595
pDdiTable->pfnGetGlobalVariablePointer = urProgramGetGlobalVariablePointer;
9696
pDdiTable->pfnGetInfo = urProgramGetInfo;
9797
pDdiTable->pfnGetNativeHandle = urProgramGetNativeHandle;
98-
pDdiTable->pfnLink = nullptr;
98+
pDdiTable->pfnLink = urProgramLink;
9999
pDdiTable->pfnRelease = urProgramRelease;
100100
pDdiTable->pfnRetain = urProgramRetain;
101101
pDdiTable->pfnSetSpecializationConstants =

unified-runtime/test/conformance/program/urProgramBuild.cpp

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,29 +30,28 @@ TEST_P(urProgramBuildTest, InvalidNullHandleProgram) {
3030
}
3131

3232
TEST_P(urProgramBuildTest, BuildFailure) {
33-
UUR_KNOWN_FAILURE_ON(uur::CUDA{}, uur::HIP{});
34-
35-
ur_program_handle_t program = nullptr;
36-
std::shared_ptr<std::vector<char>> il_binary;
37-
UUR_RETURN_ON_FATAL_FAILURE(uur::KernelsEnvironment::instance->LoadSource(
38-
"build_failure", platform, il_binary));
39-
if (!il_binary) {
40-
// The build failure we are testing for happens at SYCL compile time on
41-
// AMD and Nvidia, so no binary exists to check for a build failure
42-
GTEST_SKIP() << "Build failure test not supported on AMD/Nvidia yet";
43-
return;
33+
// The build failure we are testing for happens at SYCL compile time on
34+
// AMD and Nvidia, so no binary exists to check for a build failure
35+
ur_backend_t backend;
36+
ASSERT_SUCCESS(urPlatformGetInfo(platform, UR_PLATFORM_INFO_BACKEND,
37+
sizeof(ur_backend_t), &backend, nullptr));
38+
if (backend == UR_BACKEND_HIP || backend == UR_BACKEND_CUDA ||
39+
backend == UR_BACKEND_OFFLOAD) {
40+
GTEST_SKIP()
41+
<< "Build failure test not supported on AMD/Nvidia/Offload yet";
4442
}
45-
4643
// TODO: This seems to fail on opencl/device combination used in the Github
4744
// runners (`2023.16.12.0.12_195853.xmain-hotfix`). It segfaults, so we just
4845
// skip the test so other tests can run
49-
ur_backend_t backend;
50-
ASSERT_SUCCESS(urPlatformGetInfo(platform, UR_PLATFORM_INFO_BACKEND,
51-
sizeof(ur_backend_t), &backend, nullptr));
5246
if (backend == UR_BACKEND_OPENCL) {
5347
GTEST_SKIP() << "Skipping opencl build failure test - segfaults on CI";
5448
}
5549

50+
ur_program_handle_t program = nullptr;
51+
std::shared_ptr<std::vector<char>> il_binary;
52+
UUR_RETURN_ON_FATAL_FAILURE(uur::KernelsEnvironment::instance->LoadSource(
53+
"build_failure", platform, il_binary));
54+
5655
ASSERT_EQ_RESULT(UR_RESULT_SUCCESS,
5756
urProgramCreateWithIL(context, il_binary->data(),
5857
il_binary->size(), nullptr, &program));

unified-runtime/test/conformance/program/urProgramLink.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ struct urProgramLinkErrorTest : uur::urQueueTest {
9494
if (backend == UR_BACKEND_CUDA) {
9595
GTEST_SKIP();
9696
}
97+
// Not meaningful for liboffload
98+
if (backend == UR_BACKEND_OFFLOAD) {
99+
GTEST_SKIP();
100+
}
97101

98102
std::shared_ptr<std::vector<char>> il_binary{};
99103
UUR_RETURN_ON_FATAL_FAILURE(uur::KernelsEnvironment::instance->LoadSource(

0 commit comments

Comments
 (0)