Build: Cycles: Backport a DPC++ fix for caching of GPU binaries #117844

Merged
Nikita Sirgienko merged 1 commits from Sirgienko/blender:dpcpp_runtime_caching_bugfix into main 2024-02-05 13:55:48 +01:00
1 changed files with 90 additions and 0 deletions

View File

@ -187,3 +187,93 @@ index 17eeaafae194..09e6d2217aaa 100644
return SYCLDeviceImages;
}
diff --git a/sycl/source/detail/pi.cpp b/sycl/source/detail/pi.cpp
index fb228cd85979..94e8438ee964 100644
--- a/sycl/source/detail/pi.cpp
+++ b/sycl/source/detail/pi.cpp
@@ -635,45 +635,47 @@ static uint16_t getELFHeaderType(const unsigned char *ImgData, size_t ImgSize) {
RT::PiDeviceBinaryType getBinaryImageFormat(const unsigned char *ImgData,
size_t ImgSize) {
// Top-level magic numbers for the recognized binary image formats.
- struct {
- RT::PiDeviceBinaryType Fmt;
- const uint32_t Magic;
- } Fmts[] = {{PI_DEVICE_BINARY_TYPE_SPIRV, 0x07230203},
- {PI_DEVICE_BINARY_TYPE_LLVMIR_BITCODE, 0xDEC04342},
- // 'I', 'N', 'T', 'C' ; Intel native
- {PI_DEVICE_BINARY_TYPE_NATIVE, 0x43544E49}};
-
- if (ImgSize >= sizeof(Fmts[0].Magic)) {
- detail::remove_const_t<decltype(Fmts[0].Magic)> Hdr = 0;
- std::copy(ImgData, ImgData + sizeof(Hdr), reinterpret_cast<char *>(&Hdr));
-
- // Check headers for direct formats.
- for (const auto &Fmt : Fmts) {
- if (Hdr == Fmt.Magic)
- return Fmt.Fmt;
- }
-
- // ELF e_type for recognized binary image formats.
- struct {
- RT::PiDeviceBinaryType Fmt;
- const uint16_t Magic;
- } ELFFmts[] = {{PI_DEVICE_BINARY_TYPE_NATIVE, 0xFF04}, // OpenCL executable
- {PI_DEVICE_BINARY_TYPE_NATIVE, 0xFF12}}; // ZEBIN executable
-
- // ELF files need to be parsed separately. The header type ends after 18
- // bytes.
- if (Hdr == 0x464c457F && ImgSize >= 18) {
- uint16_t HdrType = getELFHeaderType(ImgData, ImgSize);
- for (const auto &ELFFmt : ELFFmts) {
- if (HdrType == ELFFmt.Magic)
- return ELFFmt.Fmt;
- }
- // Newer ZEBIN format does not have a special header type, but can instead
- // be identified by having a required .ze_info section.
- if (checkELFSectionPresent(".ze_info", ImgData, ImgSize))
- return PI_DEVICE_BINARY_TYPE_NATIVE;
- }
+ auto MatchMagicNumber = [&](auto Number) {
+ return ImgSize >= sizeof(Number) &&
+ std::memcmp(ImgData, &Number, sizeof(Number)) == 0;
+ };
+
+ if (MatchMagicNumber(uint32_t{0x07230203}))
+ return PI_DEVICE_BINARY_TYPE_SPIRV;
+
+ if (MatchMagicNumber(uint32_t{0xDEC04342}))
+ return PI_DEVICE_BINARY_TYPE_LLVMIR_BITCODE;
+
+ if (MatchMagicNumber(uint32_t{0x43544E49}))
+ // 'I', 'N', 'T', 'C' ; Intel native
+ return PI_DEVICE_BINARY_TYPE_LLVMIR_BITCODE;
+
+ // Check for ELF format, size requirements include data we'll read in case of
+ // succesful match.
+ if (ImgSize >= 18 && MatchMagicNumber(uint32_t{0x464c457F})) {
+ uint16_t ELFHdrType = getELFHeaderType(ImgData, ImgSize);
+ if (ELFHdrType == 0xFF04)
+ // OpenCL executable.
+ return PI_DEVICE_BINARY_TYPE_NATIVE;
+
+ if (ELFHdrType == 0xFF12)
+ // ZEBIN executable.
+ return PI_DEVICE_BINARY_TYPE_NATIVE;
+
+ // Newer ZEBIN format does not have a special header type, but can instead
+ // be identified by having a required .ze_info section.
+ if (checkELFSectionPresent(".ze_info", ImgData, ImgSize))
+ return PI_DEVICE_BINARY_TYPE_NATIVE;
}
+
+ // "ar" format is used to pack binaries for multiple devices, e.g. via
+ //
+ // -Xsycl-target-backend=spir64_gen "-device acm-g10,acm-g11"
+ //
+ // option.
+ if (MatchMagicNumber(std::array{'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}))
+ return PI_DEVICE_BINARY_TYPE_NATIVE;
+
return PI_DEVICE_BINARY_TYPE_NONE;
}