From f85b6970a926c71a032e575bd7b6e8c4e2e9b808 Mon Sep 17 00:00:00 2001 From: Austin Annestrand Date: Thu, 18 Jan 2024 11:59:24 -0600 Subject: OpenCL/Vulkan: Implement program get[Build]Info Adding backend routines for: - clGetProgramInfo - clGetProgramBuildInfo Bug: angleproject:8549 Change-Id: I890bb957e687a429eb0ed3b4756427ac98e302f3 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5303565 Reviewed-by: Shahbaz Youssefi Commit-Queue: Austin Annestrand Reviewed-by: Geoff Lang --- src/libANGLE/renderer/vulkan/CLProgramVk.cpp | 139 ++++++++++++++++++++++++++- src/libANGLE/validationCL.cpp | 24 +++++ 2 files changed, 159 insertions(+), 4 deletions(-) diff --git a/src/libANGLE/renderer/vulkan/CLProgramVk.cpp b/src/libANGLE/renderer/vulkan/CLProgramVk.cpp index 15f5306ea4..624348bc35 100644 --- a/src/libANGLE/renderer/vulkan/CLProgramVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLProgramVk.cpp @@ -445,8 +445,94 @@ angle::Result CLProgramVk::getInfo(cl::ProgramInfo name, void *value, size_t *valueSizeRet) const { - UNIMPLEMENTED(); - ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + cl_uint valUInt = 0u; + void *valPointer = nullptr; + const void *copyValue = nullptr; + size_t copySize = 0u; + unsigned char **outputBins = reinterpret_cast(value); + std::string kernelNamesList; + std::vector vBinarySizes; + + switch (name) + { + case cl::ProgramInfo::NumKernels: + for (const auto &deviceProgram : mAssociatedDevicePrograms) + { + valUInt += static_cast(deviceProgram.second.numKernels()); + } + copyValue = &valUInt; + copySize = sizeof(valUInt); + break; + case cl::ProgramInfo::BinarySizes: + { + for (const auto &deviceProgram : mAssociatedDevicePrograms) + { + vBinarySizes.push_back( + sizeof(ProgramBinaryOutputHeader) + + (deviceProgram.second.binaryType == CL_PROGRAM_BINARY_TYPE_EXECUTABLE + ? deviceProgram.second.binary.size() * sizeof(uint32_t) + : deviceProgram.second.IR.size())); + } + valPointer = vBinarySizes.data(); + copyValue = valPointer; + copySize = vBinarySizes.size() * sizeof(size_t); + break; + } + case cl::ProgramInfo::Binaries: + for (const auto &deviceProgram : mAssociatedDevicePrograms) + { + const void *bin = + deviceProgram.second.binaryType == CL_PROGRAM_BINARY_TYPE_EXECUTABLE + ? reinterpret_cast(deviceProgram.second.binary.data()) + : reinterpret_cast(deviceProgram.second.IR.data()); + size_t binSize = + deviceProgram.second.binaryType == CL_PROGRAM_BINARY_TYPE_EXECUTABLE + ? deviceProgram.second.binary.size() * sizeof(uint32_t) + : deviceProgram.second.IR.size(); + ProgramBinaryOutputHeader header{.headerVersion = LatestSupportedBinaryVersion, + .binaryType = deviceProgram.second.binaryType}; + + if (outputBins != nullptr) + { + if (*outputBins != nullptr) + { + std::memcpy(*outputBins, &header, sizeof(ProgramBinaryOutputHeader)); + std::memcpy((*outputBins) + sizeof(ProgramBinaryOutputHeader), bin, + binSize); + } + outputBins++; + } + + // Spec just wants pointer size here + copySize += sizeof(unsigned char *); + } + // We already copied the (headers + binaries) over - nothing else left to copy + copyValue = nullptr; + break; + case cl::ProgramInfo::KernelNames: + for (const auto &deviceProgram : mAssociatedDevicePrograms) + { + kernelNamesList = deviceProgram.second.getKernelNames(); + } + valPointer = kernelNamesList.data(); + copyValue = valPointer; + copySize = kernelNamesList.size() + 1; + break; + default: + UNREACHABLE(); + } + + if ((value != nullptr) && (copyValue != nullptr)) + { + std::memcpy(value, copyValue, copySize); + } + + if (valueSizeRet != nullptr) + { + *valueSizeRet = copySize; + } + + return angle::Result::Continue; } angle::Result CLProgramVk::getBuildInfo(const cl::Device &device, @@ -455,8 +541,53 @@ angle::Result CLProgramVk::getBuildInfo(const cl::Device &device, void *value, size_t *valueSizeRet) const { - UNIMPLEMENTED(); - ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + cl_uint valUInt = 0; + cl_build_status valStatus = 0; + const void *copyValue = nullptr; + size_t copySize = 0; + const DeviceProgramData *deviceProgramData = getDeviceProgramData(device.getNative()); + + switch (name) + { + case cl::ProgramBuildInfo::Status: + valStatus = deviceProgramData->buildStatus; + copyValue = &valStatus; + copySize = sizeof(valStatus); + break; + case cl::ProgramBuildInfo::Log: + copyValue = deviceProgramData->buildLog.c_str(); + copySize = deviceProgramData->buildLog.size() + 1; + break; + case cl::ProgramBuildInfo::Options: + copyValue = mProgramOpts.c_str(); + copySize = mProgramOpts.size() + 1; + break; + case cl::ProgramBuildInfo::BinaryType: + valUInt = deviceProgramData->binaryType; + copyValue = &valUInt; + copySize = sizeof(valUInt); + break; + case cl::ProgramBuildInfo::GlobalVariableTotalSize: + // Returns 0 if device does not support program scope global variables. + valUInt = 0; + copyValue = &valUInt; + copySize = sizeof(valUInt); + break; + default: + UNREACHABLE(); + } + + if ((value != nullptr) && (copyValue != nullptr)) + { + memcpy(value, copyValue, std::min(valueSize, copySize)); + } + + if (valueSizeRet != nullptr) + { + *valueSizeRet = copySize; + } + + return angle::Result::Continue; } angle::Result CLProgramVk::createKernel(const cl::Kernel &kernel, diff --git a/src/libANGLE/validationCL.cpp b/src/libANGLE/validationCL.cpp index e37493d0b1..e4675cb18d 100644 --- a/src/libANGLE/validationCL.cpp +++ b/src/libANGLE/validationCL.cpp @@ -1232,6 +1232,18 @@ cl_int ValidateGetProgramInfo(cl_program program, break; } + // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type + // as described in the Program Object Queries table and param_value is not NULL. + if (param_value != nullptr) + { + size_t valueSizeRet = 0; + if (IsError(prog.getInfo(param_name, 0, nullptr, &valueSizeRet)) || + param_value_size < valueSizeRet) + { + return CL_INVALID_VALUE; + } + } + return CL_SUCCESS; } @@ -1272,6 +1284,18 @@ cl_int ValidateGetProgramBuildInfo(cl_program program, break; } + // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type + // as described in the Program Object Queries table and param_value is not NULL. + if (param_value != nullptr) + { + size_t valueSizeRet = 0; + if (IsError(prog.getBuildInfo(device, param_name, 0, nullptr, &valueSizeRet)) || + param_value_size < valueSizeRet) + { + return CL_INVALID_VALUE; + } + } + return CL_SUCCESS; } -- cgit v1.2.3