Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 81 additions & 13 deletions unified-runtime/source/adapters/offload/program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urProgramCreateWithBinary(
Program->URContext = hContext;
Program->Binary = RealBinary;
Program->BinarySizeInBytes = RealLength;
Program->BinaryType = UR_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;

// Parse properties
if (pProperties) {
Expand Down Expand Up @@ -160,24 +161,68 @@ urProgramCreateWithIL(ur_context_handle_t hContext, const void *pIL,
}

UR_APIEXPORT ur_result_t UR_APICALL urProgramBuild(ur_context_handle_t,
ur_program_handle_t,
const char *) {
ur_program_handle_t hProgram,
const char *pOptions) {
// Do nothing, program is built upon creation
if (pOptions && *pOptions) {
hProgram->Error = "Liboffload doesn't support link options";
return UR_RESULT_ERROR_PROGRAM_LINK_FAILURE;
}
hProgram->BinaryType = UR_PROGRAM_BINARY_TYPE_EXECUTABLE;
return UR_RESULT_SUCCESS;
}

UR_APIEXPORT ur_result_t UR_APICALL urProgramBuildExp(ur_program_handle_t,
uint32_t,
ur_device_handle_t *,
const char *) {
UR_APIEXPORT ur_result_t UR_APICALL
urProgramBuildExp(ur_program_handle_t hProgram, uint32_t, ur_device_handle_t *,
const char *pOptions) {
// Do nothing, program is built upon creation
if (pOptions && *pOptions) {
hProgram->Error = "Liboffload doesn't support link options";
return UR_RESULT_ERROR_PROGRAM_LINK_FAILURE;
}
hProgram->BinaryType = UR_PROGRAM_BINARY_TYPE_EXECUTABLE;
return UR_RESULT_SUCCESS;
}

UR_APIEXPORT ur_result_t UR_APICALL urProgramCompile(ur_context_handle_t,
ur_program_handle_t,
const char *) {
UR_APIEXPORT ur_result_t UR_APICALL urProgramCompile(
ur_context_handle_t, ur_program_handle_t hProgram, const char *pOptions) {
// Do nothing, program is built upon creation
if (pOptions && *pOptions) {
hProgram->Error = "Liboffload doesn't support link options";
return UR_RESULT_ERROR_PROGRAM_LINK_FAILURE;
}
hProgram->BinaryType = UR_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
return UR_RESULT_SUCCESS;
}

UR_APIEXPORT ur_result_t UR_APICALL
urProgramLink(ur_context_handle_t hContext, uint32_t count,
const ur_program_handle_t *phPrograms, const char *pOptions,
ur_program_handle_t *phProgram) {
if (count > 1) {
*phProgram = ur_program_handle_t_::newErrorProgram(
hContext, nullptr, 0,
"Liboffload does not support linking multiple binaries");
return UR_RESULT_ERROR_PROGRAM_LINK_FAILURE;
}
if (pOptions) {
*phProgram = ur_program_handle_t_::newErrorProgram(
hContext, nullptr, 0, "Liboffload does not support linker options");
return UR_RESULT_ERROR_PROGRAM_LINK_FAILURE;
}
assert(count == 1);

// Offload programs are already fully linked on creation, just create a new
// program containing it
auto *InProgram = *phPrograms;
ur_program_handle_t Program = new ur_program_handle_t_{};
Program->URContext = hContext;
Program->Binary = InProgram->Binary;
Program->BinarySizeInBytes = InProgram->BinarySizeInBytes;
Program->GlobalIDMD = InProgram->GlobalIDMD;
Program->BinaryType = UR_PROGRAM_BINARY_TYPE_EXECUTABLE;
*phProgram = Program;

return UR_RESULT_SUCCESS;
}

Expand Down Expand Up @@ -230,6 +275,28 @@ urProgramGetInfo(ur_program_handle_t hProgram, ur_program_info_t propName,
return UR_RESULT_SUCCESS;
}

UR_APIEXPORT ur_result_t UR_APICALL
urProgramGetBuildInfo(ur_program_handle_t hProgram, ur_device_handle_t,
ur_program_build_info_t propName, size_t propSize,
void *pPropValue, size_t *pPropSizeRet) {
UrReturnHelper ReturnValue(propSize, pPropValue, pPropSizeRet);
switch (propName) {
case UR_PROGRAM_BUILD_INFO_STATUS:
return ReturnValue(hProgram->Error.empty() ? UR_PROGRAM_BUILD_STATUS_SUCCESS
: UR_PROGRAM_BUILD_STATUS_ERROR);
case UR_PROGRAM_BUILD_INFO_OPTIONS:
return ReturnValue("");
case UR_PROGRAM_BUILD_INFO_LOG:
return ReturnValue(hProgram->Error.c_str());
case UR_PROGRAM_BUILD_INFO_BINARY_TYPE:
return ReturnValue(hProgram->BinaryType);
default:
return UR_RESULT_ERROR_INVALID_ENUMERATION;
}

return UR_RESULT_SUCCESS;
}

UR_APIEXPORT ur_result_t UR_APICALL
urProgramRetain(ur_program_handle_t hProgram) {
hProgram->RefCount++;
Expand All @@ -239,11 +306,12 @@ urProgramRetain(ur_program_handle_t hProgram) {
UR_APIEXPORT ur_result_t UR_APICALL
urProgramRelease(ur_program_handle_t hProgram) {
if (--hProgram->RefCount == 0) {
auto Res = olDestroyProgram(hProgram->OffloadProgram);
if (Res) {
return offloadResultToUR(Res);
if (hProgram->OffloadProgram) {
if (auto Res = olDestroyProgram(hProgram->OffloadProgram)) {
return offloadResultToUR(Res);
}
delete hProgram;
}
delete hProgram;
}

return UR_RESULT_SUCCESS;
Expand Down
19 changes: 19 additions & 0 deletions unified-runtime/source/adapters/offload/program.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,23 @@ struct ur_program_handle_t_ : RefCounted {
size_t BinarySizeInBytes;
// A mapping from mangled global names -> names in the binary
std::unordered_map<std::string, std::string> GlobalIDMD;
// The UR offload backend doesn't draw distinctions between these types (we
// always have a fully built binary), but we need to track what state we are
// pretending to be in
ur_program_binary_type_t BinaryType;
std::string Error;

static ur_program_handle_t_ *newErrorProgram(ur_context_handle_t Context,
const uint8_t *Binary,
size_t BinarySizeInBytes,
std::string &&Error) {
return new ur_program_handle_t_{{},
nullptr,
Context,
Binary,
BinarySizeInBytes,
{},
UR_PROGRAM_BINARY_TYPE_NONE,
Error};
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetProgramProcAddrTable(
pDdiTable->pfnCreateWithBinary = urProgramCreateWithBinary;
pDdiTable->pfnCreateWithIL = urProgramCreateWithIL;
pDdiTable->pfnCreateWithNativeHandle = urProgramCreateWithNativeHandle;
pDdiTable->pfnGetBuildInfo = nullptr;
pDdiTable->pfnGetBuildInfo = urProgramGetBuildInfo;
pDdiTable->pfnGetFunctionPointer = urProgramGetFunctionPointer;
pDdiTable->pfnGetGlobalVariablePointer = urProgramGetGlobalVariablePointer;
pDdiTable->pfnGetInfo = urProgramGetInfo;
pDdiTable->pfnGetNativeHandle = urProgramGetNativeHandle;
pDdiTable->pfnLink = nullptr;
pDdiTable->pfnLink = urProgramLink;
pDdiTable->pfnRelease = urProgramRelease;
pDdiTable->pfnRetain = urProgramRetain;
pDdiTable->pfnSetSpecializationConstants =
Expand Down
29 changes: 14 additions & 15 deletions unified-runtime/test/conformance/program/urProgramBuild.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,28 @@ TEST_P(urProgramBuildTest, InvalidNullHandleProgram) {
}

TEST_P(urProgramBuildTest, BuildFailure) {
UUR_KNOWN_FAILURE_ON(uur::CUDA{}, uur::HIP{});

ur_program_handle_t program = nullptr;
std::shared_ptr<std::vector<char>> il_binary;
UUR_RETURN_ON_FATAL_FAILURE(uur::KernelsEnvironment::instance->LoadSource(
"build_failure", platform, il_binary));
if (!il_binary) {
// The build failure we are testing for happens at SYCL compile time on
// AMD and Nvidia, so no binary exists to check for a build failure
GTEST_SKIP() << "Build failure test not supported on AMD/Nvidia yet";
return;
// The build failure we are testing for happens at SYCL compile time on
// AMD and Nvidia, so no binary exists to check for a build failure
ur_backend_t backend;
ASSERT_SUCCESS(urPlatformGetInfo(platform, UR_PLATFORM_INFO_BACKEND,
sizeof(ur_backend_t), &backend, nullptr));
if (backend == UR_BACKEND_HIP || backend == UR_BACKEND_CUDA ||
backend == UR_BACKEND_OFFLOAD) {
GTEST_SKIP()
<< "Build failure test not supported on AMD/Nvidia/Offload yet";
}

// TODO: This seems to fail on opencl/device combination used in the Github
// runners (`2023.16.12.0.12_195853.xmain-hotfix`). It segfaults, so we just
// skip the test so other tests can run
ur_backend_t backend;
ASSERT_SUCCESS(urPlatformGetInfo(platform, UR_PLATFORM_INFO_BACKEND,
sizeof(ur_backend_t), &backend, nullptr));
if (backend == UR_BACKEND_OPENCL) {
GTEST_SKIP() << "Skipping opencl build failure test - segfaults on CI";
}

ur_program_handle_t program = nullptr;
std::shared_ptr<std::vector<char>> il_binary;
UUR_RETURN_ON_FATAL_FAILURE(uur::KernelsEnvironment::instance->LoadSource(
"build_failure", platform, il_binary));

ASSERT_EQ_RESULT(UR_RESULT_SUCCESS,
urProgramCreateWithIL(context, il_binary->data(),
il_binary->size(), nullptr, &program));
Expand Down
4 changes: 4 additions & 0 deletions unified-runtime/test/conformance/program/urProgramLink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ struct urProgramLinkErrorTest : uur::urQueueTest {
if (backend == UR_BACKEND_CUDA) {
GTEST_SKIP();
}
// Not meaningful for liboffload
if (backend == UR_BACKEND_OFFLOAD) {
GTEST_SKIP();
}

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