What You Need To Know About SPIR-V 1.0
For those that haven't been paying attention to SPIR-V as the new intermediate representation that makes up OpenCL 2.1+ and Vulkan, here's various details about this newest Khronos Group specification you may not be familiar with now that Khronos formally released OpenCL 2.1 and SPIR-V 1.0..
Like all Khronos specifications, this IR specification was designed over the period of months by Khronos Group member companies. The authors of SPIR-V 1.0 are listed as:
Unlike the earlier SPIR specifications, SPIR-V isn't based on LLVM IR. Instead, it's a fresh design and with that has native support for graphics and compute constructs. SPIR-V is of importance to OpenGL, GLSL, OpenCL++, and -- of course -- Vulkan.
While SPIR-V isn't derived from LLVM IR, it still can be converted to/from LLVM IR. Khronos has made the translators available via GitHub along with some other SPIR-V 1.0 tools.
While a binary format, for those curious what SPIR-V looks like in disassembled, human-readable form, here's a look with the output from the SPIR-V documentation showing a GLSL fragment shader. Khronos made public their open-source SPIR-V assembler and disassembler too.
If you want to learn more about the IR, there is this white paper or the full specification.
SPIR-V 1.0 is very interesting and will be particularly interesting to see how the open-source community embraces it and what doors are opened up when leveraging LLVM.
Like all Khronos specifications, this IR specification was designed over the period of months by Khronos Group member companies. The authors of SPIR-V 1.0 are listed as:
Connor Abbott, IntelSo in looking at a company breakdown of the listed authors: NVIDIA [5], Intel [5], Qualcomm [4], Codeplay [4], AMD [3], Google [3], ARM [2], MediaTek [2], Valve [1], Unity [1], Epic Games [1], Broadcom [1], Imagination [1], Blizzard Entertainment [1], Oxide Games [1]. NVIDIA and Intel have the most involved. Also worth a shout out to one of the listed developers: Connor Abbott. If the name doesn't ring a bell, he began contributing to open-source graphics while in high school via the Lima driver project. When he was fresh out of high school, he interned at Intel and fleshed out NIR, the new intermediate representation used by some Mesa / Gallium3D drivers. So in between university and his time working on Mesa, he's also been working on SPIR-V through Intel.
Alexey Badar, Intel
Dan Baker, Oxide Games
Kenneth Benzie, Codeplay
Gordon Brown, Codeplay
Pat Brown, NVIDIA
Diana Po-Yu Chen, MediaTek
Stephen Clarke, Imagination
Patrick Doane, Blizzard Entertainment
Stefanus Du Toit, Google
Tim Foley, Intel
Ben Gaster, Qualcomm
Alexander Galazin, ARM
Christopher Gautier, ARM
Neil Henning, Codeplay
Kerch Holt, NVIDIA
Lee Howes, Qualcomm
Roy Ju, MediaTek
Daniel Koch, NVIDIA
Ashwin Kolhe, NVIDIA
Raun Krisch, Intel
Graeme Leese, Broadcom
Yuan Lin, NVIDIA
Yaxun Liu, AMD
Timothy Lottes, Epic Games
John McDonald, Valve
David Neto, Google
Christophe Riccio, Unity
Andrew Richards, Codeplay
Ian Romanick, Intel
Graham Sellers, AMD
Robert Simpson, Qualcomm
Brian Sumner, AMD
Andrew Woloszyn, Google
Weifeng Zhang, Qualcomm
Unlike the earlier SPIR specifications, SPIR-V isn't based on LLVM IR. Instead, it's a fresh design and with that has native support for graphics and compute constructs. SPIR-V is of importance to OpenGL, GLSL, OpenCL++, and -- of course -- Vulkan.
While SPIR-V isn't derived from LLVM IR, it still can be converted to/from LLVM IR. Khronos has made the translators available via GitHub along with some other SPIR-V 1.0 tools.
While a binary format, for those curious what SPIR-V looks like in disassembled, human-readable form, here's a look with the output from the SPIR-V documentation showing a GLSL fragment shader. Khronos made public their open-source SPIR-V assembler and disassembler too.
; Magic: 0x07230203 (SPIR-V) ; Version: 0x00010000 (Version: 1.0.0) ; Generator: 0x00080001 (Khronos Glslang Reference Front End; 1) ; Bound: 58 ; Schema: 0 OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %4 "main" %22 %38 %20 OpExecutionMode %4 OriginLowerLeft ; Debug information OpSource GLSL 450 OpName %4 "main" OpName %9 "scale" OpName %15 "cond" OpName %20 "color" OpName %22 "color1" OpName %28 "S" OpMemberName %28 0 "b" OpMemberName %28 1 "v" OpMemberName %28 2 "i" OpName %30 "s" OpName %38 "color2" OpName %44 "i" OpName %52 "multiplier" ; Annotations (non-debug) OpDecorate %38 NoPerspective ; All types, variables, and constants %2 = OpTypeVoid %3 = OpTypeFunction %2 ; void () %6 = OpTypeFloat 32 ; 32-bit float %7 = OpTypeVector %6 4 ; vec4 %8 = OpTypePointer Function %7 ; function-local vec4* %10 = OpConstant %6 1.0 %11 = OpConstant %6 2.0 %12 = OpConstantComposite %7 %10 %10 %11 %10 ; vec4(1.0, 1.0, 2.0, 1.0) %13 = OpTypeBool %14 = OpTypePointer UniformConstant %13 ; uniform bool* %15 = OpVariable %14 UniformConstant ; cond %19 = OpTypePointer Output %7 ; out vec4 %20 = OpVariable %19 Output ; color %21 = OpTypePointer Input %7 ; in vec4 %22 = OpVariable %21 Input ; color1 %24 = OpTypeInt 32 0 %25 = OpConstant %24 5 %26 = OpTypeArray %7 %25 %27 = OpTypeInt 32 1 %28 = OpTypeStruct %13 %26 %27 ; struct S %29 = OpTypePointer UniformConstant %28 ; uniform struct S* %30 = OpVariable %29 UniformConstant ; s %31 = OpConstant %27 1 %32 = OpConstant %27 2 %33 = OpTypePointer UniformConstant %7 ; uniform S %38 = OpVariable %21 Input ; color2 %43 = OpTypePointer Function %27 %45 = OpConstant %27 0 %50 = OpConstant %27 4 %52 = OpVariable %33 UniformConstant ; multiplier ; All functions %4 = OpFunction %2 None %3 ; main %5 = OpLabel %9 = OpVariable %8 Function %44 = OpVariable %43 Function OpStore %9 %12 %16 = OpLoad %13 %15 OpSelectionMerge %18 None ; structured if OpBranchConditional %16 %17 %37 ; if (cond) %17 = OpLabel ; then %23 = OpLoad %7 %22 %34 = OpAccessChain %33 %30 %31 %32 ; s.v[2] %35 = OpLoad %7 %34 %36 = OpFAdd %7 %23 %35 OpStore %20 %36 OpBranch %18 %37 = OpLabel ; else %39 = OpLoad %7 %38 %40 = OpExtInst %7 %1 Sqrt %39 %41 = OpLoad %7 %9 %42 = OpFMul %7 %40 %41 OpStore %20 %42 OpBranch %18 %18 = OpLabel ; end if OpStore %44 %45 OpBranch %46 %46 = OpLabel ; loop header %49 = OpLoad %27 %44 %51 = OpSLessThan %13 %49 %50 OpLoopMerge %47 %46 None ; structured loop OpBranchConditional %51 %48 %47 ; body or break %48 = OpLabel ; body %53 = OpLoad %7 %52 %54 = OpLoad %7 %20 %55 = OpFMul %7 %54 %53 OpStore %20 %55 %56 = OpLoad %27 %44 %57 = OpIAdd %27 %56 %31 OpStore %44 %57 OpBranch %46 ; loop %47 = OpLabel OpReturn OpFunctionEnd
If you want to learn more about the IR, there is this white paper or the full specification.
SPIR-V 1.0 is very interesting and will be particularly interesting to see how the open-source community embraces it and what doors are opened up when leveraging LLVM.
12 Comments