[Mesa-dev] [RFC PATCH 00/17] Introducing SPIR-V support to clover

Hello everyone, I have been working on converting SPIR-V to NVIR in order to run OpenCL kernels on Nouveau, and I would like to submit the first part of that work for review. Pieces from the SPIR-V to NVIR conversion work will be submitted once I have cleaned it up and this series has progressed through the reviewing process. What’s in this Series? ---------------------- The focus of this series is to let clover accept SPIR-V binaries, either through `clCreateProgramWithBinary()`, or through `clCreateProgramWithIL()`. The latter function is the proper way to feed SPIR-V binaries using the OpenCL API, however it was only introduced in OpenCL 2.1 (more on “why supporting SPIR-V through `clCreateProgramWithBinary()` can be interesting” further down). As several SPIR-V binaries can be linked together using the OpenCL API, I implemented a SPIR-V linker, which is not perfect, but does the job. I tested linking against a variable, a function, a library, and a function containing a switch statement; switch-statements require you to keep some extra stuff around to be properly parsed. I also added a few “utilities” functions for retrieving and setting a word / retrieving a string from a SPIR-V binary, and converting a SPIR-V binary to the same endianness as the host CPU. For validating SPIR-V binaries, I use an external tool, SPIRV-Tools [1]. It could also be used in anv, and possibly radv if there is no validation done already, but I haven’t looked into that. A few modifications have been made to the pipe interface, to add a define for the SPIR-V IR, and store the program’s byte-size along the program in `struct pipe_compute_state`. The latter will only be needed by the consumer of the SPIR-V, which is not part of this series. However, since clover needs to fill that information in and I was modifying clover already, I decided to add the new attribute in this series. Missing ------- * As there is no upstream version of LLVM which can produce SPIR-V out of OpenCL code, clCreateProgramWithSource will refuse to work if the target IR is SPIR-V, for now. * Optimisation linking options are parsed by the SPIR-V code in clover but are not passed along to the linker as it does not support them. To Improve ---------- The SPIR-V binary resulting from the linking of multiple SPIR-V binaries could be cleaned up: * As capabilities are simply copied from all the involved binaries, you can end up with multiple times the same capabilities in the resulting binary; this shouldn’t have any impact though. * Similarly, types can end up being duplicated under different IDs, which should have no other impact than making SPIR-V validators unhappy. Misc. ----- Being able to feed SPIR-V binaries through `clCreateProgramWithBinary()` is not really useful at the moment: the same can be achieved using `clCreateProgramWithIL()`. However it will be interesting once there is an upstream version of LLVM which can generate SPIR-V binaries, as the application could query the binary created by `clCreateProgramWithSource()` on the first run, and give it to `clCreateProgramWithBinary()`on later runs. Once NIR supports pointers, and anything else that could be missing to support OpenCL kernels, it should be possible and easy to convert input SPIR-V binaries to NIR, for drivers that do not accept SPIR-V as IR. I have sent patches to Mesa in the past, but never series, so the splitting of the patches in the series could be completely wrong, and I apologise for that in advance. Also, I am sure I abused of macros, gotos and manual memory managements, as I am not that comfortable at writing too much C code: I’ll try to learn from your comments. Thank you in advance for reviewing/commenting, Pierre [1]: https://github.com/KhronosGroup/SPIRV-Tools/ Pierre Moreau (17): auxiliary: Introduce utilities for SPIR-V binaries auxiliary: Implement a linker for SPIR-V binaries include/pipe: Define SPIRV as an IR include/pipe: Store the byte-size of a SPIR-V binary include/CL: Add clCreateProgramWithIL from OpenCL 2.1 include/CL: Add new option to clGetProgramInfo from OpenCL 2.1 configure.ac: Check for SPIRV-Tools header and library clover: Fill in the program byte-size in pipe_compute_state clover: Add additional functions to query supported IRs clover/spirv: Import spirv.hpp11 version 1.0 (rev 10) clover/spirv: Add functions for parsing arguments, linking programs, etc. clover: Refuse to compile source code to SPIR-V clover: Handle the case when linking SPIR-V binaries together clover: Accept SPIR-V binaries in clCreateProgramWithBinary clover: Implement clCreateProgramWithIL from OpenCL 2.1 clover: Add a pointer property to return ILs clover: Handle CL_PROGRAM_IL in clGetProgramInfo configure.ac | 16 + include/CL/cl.h | 7 + include/CL/cl_platform.h | 1 + src/gallium/auxiliary/Makefile.am | 1 + src/gallium/auxiliary/Makefile.sources | 6 + src/gallium/auxiliary/spirv/spirv_linker.c | 1324 ++++++++++++++++++++ src/gallium/auxiliary/spirv/spirv_linker.h | 67 + src/gallium/auxiliary/spirv/spirv_utils.c | 75 ++ src/gallium/auxiliary/spirv/spirv_utils.h | 86 ++ src/gallium/include/pipe/p_defines.h | 1 + src/gallium/include/pipe/p_state.h | 1 + src/gallium/state_trackers/clover/Makefile.am | 10 +- src/gallium/state_trackers/clover/Makefile.sources | 4 + src/gallium/state_trackers/clover/api/program.cpp | 74 +- src/gallium/state_trackers/clover/core/device.cpp | 11 + src/gallium/state_trackers/clover/core/device.hpp | 3 + src/gallium/state_trackers/clover/core/kernel.cpp | 1 + src/gallium/state_trackers/clover/core/program.cpp | 80 +- src/gallium/state_trackers/clover/core/program.hpp | 14 + .../state_trackers/clover/core/property.hpp | 39 + .../state_trackers/clover/spirv/invocation.cpp | 481 +++++++ .../state_trackers/clover/spirv/invocation.hpp | 40 + .../state_trackers/clover/spirv/spirv.hpp11 | 952 ++++++++++++++ 23 files changed, 3272 insertions(+), 22 deletions(-) create mode 100644 src/gallium/auxiliary/spirv/spirv_linker.c create mode 100644 src/gallium/auxiliary/spirv/spirv_linker.h create mode 100644 src/gallium/auxiliary/spirv/spirv_utils.c create mode 100644 src/gallium/auxiliary/spirv/spirv_utils.h create mode 100644 src/gallium/state_trackers/clover/spirv/invocation.cpp create mode 100644 src/gallium/state_trackers/clover/spirv/invocation.hpp create mode 100644 src/gallium/state_trackers/clover/spirv/spirv.hpp11 -- 2.12.2