[1/7] mesa: implement ARB/KHR_parallel_shader_compile

Submitted by Marek Olšák on Feb. 25, 2019, 6:27 p.m.

Details

Message ID 20190225182752.1804-1-maraeo@gmail.com
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Mesa

Not browsing as part of any series.

Commit Message

Marek Olšák Feb. 25, 2019, 6:27 p.m.
From: Marek Olšák <marek.olsak@amd.com>

Tested by piglit.
---
 docs/features.txt                       |  2 +-
 docs/relnotes/19.0.0.html               |  2 ++
 src/mapi/glapi/gen/gl_API.xml           | 15 ++++++++++++++-
 src/mesa/main/dd.h                      |  7 +++++++
 src/mesa/main/extensions_table.h        |  2 ++
 src/mesa/main/get_hash_params.py        |  3 +++
 src/mesa/main/hint.c                    | 12 ++++++++++++
 src/mesa/main/hint.h                    |  4 ++++
 src/mesa/main/mtypes.h                  |  1 +
 src/mesa/main/shaderapi.c               | 10 ++++++++++
 src/mesa/main/tests/dispatch_sanity.cpp |  5 +++++
 11 files changed, 61 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/docs/features.txt b/docs/features.txt
index 6c2b6d59377..440192be8f0 100644
--- a/docs/features.txt
+++ b/docs/features.txt
@@ -295,21 +295,21 @@  GLES3.2, GLSL ES 3.2 -- all DONE: i965/gen9+, radeonsi, virgl
   GL_OES_texture_storage_multisample_2d_array           DONE (all drivers that support GL_ARB_texture_multisample)
 
 Khronos, ARB, and OES extensions that are not part of any OpenGL or OpenGL ES version:
 
   GL_ARB_bindless_texture                               DONE (nvc0, radeonsi)
   GL_ARB_cl_event                                       not started
   GL_ARB_compute_variable_group_size                    DONE (nvc0, radeonsi)
   GL_ARB_ES3_2_compatibility                            DONE (i965/gen8+, radeonsi, virgl)
   GL_ARB_fragment_shader_interlock                      DONE (i965)
   GL_ARB_gpu_shader_int64                               DONE (i965/gen8+, nvc0, radeonsi, softpipe, llvmpipe)
-  GL_ARB_parallel_shader_compile                        not started, but Chia-I Wu did some related work in 2014
+  GL_ARB_parallel_shader_compile                        DONE (all drivers)
   GL_ARB_post_depth_coverage                            DONE (i965, nvc0)
   GL_ARB_robustness_isolation                           not started
   GL_ARB_sample_locations                               DONE (nvc0)
   GL_ARB_seamless_cubemap_per_texture                   DONE (freedreno, i965, nvc0, radeonsi, r600, softpipe, swr, virgl)
   GL_ARB_shader_ballot                                  DONE (i965/gen8+, nvc0, radeonsi)
   GL_ARB_shader_clock                                   DONE (i965/gen7+, nv50, nvc0, r600, radeonsi, virgl)
   GL_ARB_shader_stencil_export                          DONE (i965/gen9+, r600, radeonsi, softpipe, llvmpipe, swr, virgl)
   GL_ARB_shader_viewport_layer_array                    DONE (i965/gen6+, nvc0, radeonsi)
   GL_ARB_sparse_buffer                                  DONE (radeonsi/CIK+)
   GL_ARB_sparse_texture                                 not started
diff --git a/docs/relnotes/19.0.0.html b/docs/relnotes/19.0.0.html
index 1b4edd7ce76..69d9649721f 100644
--- a/docs/relnotes/19.0.0.html
+++ b/docs/relnotes/19.0.0.html
@@ -33,25 +33,27 @@  Compatibility contexts may report a lower version depending on each driver.
 <h2>SHA256 checksums</h2>
 <pre>
 TBD.
 </pre>
 
 
 <h2>New features</h2>
 
 <ul>
 <li>GL_AMD_texture_texture4 on all GL 4.0 drivers.</li>
+<li>GL_ARB_parallel_shader_compile on all drivers.</li>
 <li>GL_EXT_shader_implicit_conversions on all drivers (ES extension).</li>
 <li>GL_EXT_texture_compression_bptc on all GL 4.0 drivers (ES extension).</li>
 <li>GL_EXT_texture_compression_rgtc on all GL 3.0 drivers (ES extension).</li>
 <li>GL_EXT_render_snorm on gallium drivers (ES extension).</li>
 <li>GL_EXT_texture_view on drivers supporting texture views (ES extension).</li>
+<li>GL_KHR_parallel_shader_compile on all drivers.</li>
 <li>GL_OES_texture_view on drivers supporting texture views (ES extension).</li>
 <li>GL_NV_shader_atomic_float on nvc0 (Fermi/Kepler only).</li>
 <li>Shader-based software implementations of GL_ARB_gpu_shader_fp64, GL_ARB_gpu_shader_int64, GL_ARB_vertex_attrib_64bit, and GL_ARB_shader_ballot on i965.</li>
 <li>VK_ANDROID_external_memory_android_hardware_buffer on Intel</li>
 <li>Fixed and re-exposed VK_EXT_pci_bus_info on Intel and RADV</li>
 <li>VK_EXT_scalar_block_layout on Intel and RADV</li>
 <li>VK_KHR_depth_stencil_resolve on Intel</li>
 <li>VK_KHR_draw_indirect_count on Intel</li>
 <li>VK_EXT_conditional_rendering on Intel</li>
 <li>VK_EXT_memory_budget on RADV</li>
diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index 929e5f6b024..9b8998532d5 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -8393,21 +8393,34 @@ 
         <param name="maxX" type="GLfloat"/>
         <param name="maxY" type="GLfloat"/>
         <param name="maxZ" type="GLfloat"/>
         <param name="maxW" type="GLfloat"/>
     </function>
 
 </category>
 
 <xi:include href="ARB_gpu_shader_int64.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
 
-<!-- ARB extension 179 - 189 -->
+<category name="ARB_parallel_shader_compile" number="179">
+    <enum name="MAX_SHADER_COMPILER_THREADS_ARB"   value="0x91B0"/>
+    <enum name="COMPLETION_STATUS_ARB"             value="0x91B1"/>
+
+    <function name="MaxShaderCompilerThreadsKHR" es2="2.0">
+        <param name="count" type="GLuint"/>
+    </function>
+
+    <function name="MaxShaderCompilerThreadsARB" alias="MaxShaderCompilerThreadsKHR">
+        <param name="count" type="GLuint"/>
+    </function>
+</category>
+
+<!-- ARB extension 180 - 189 -->
 
 <xi:include href="ARB_gl_spirv.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
 
 <!-- Non-ARB extensions sorted by extension number. -->
 
 <category name="GL_EXT_blend_color" number="2">
     <enum name="CONSTANT_COLOR_EXT"                       value="0x8001"/>
     <enum name="ONE_MINUS_CONSTANT_COLOR_EXT"             value="0x8002"/>
     <enum name="CONSTANT_ALPHA_EXT"                       value="0x8003"/>
     <enum name="ONE_MINUS_CONSTANT_ALPHA_EXT"             value="0x8004"/>
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 1214eeaa474..8251af3f667 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -1291,20 +1291,27 @@  struct dd_function_table {
    /**
     * Called to initialize gl_program::driver_cache_blob (and size) with a
     * ralloc allocated buffer.
     *
     * This buffer will be saved and restored as part of the gl_program
     * serialization and deserialization.
     */
    void (*ShaderCacheSerializeDriverBlob)(struct gl_context *ctx,
                                           struct gl_program *prog);
    /*@}*/
+
+   /**
+    * \name Set the number of compiler threads for ARB_parallel_shader_compile
+    */
+   void (*SetMaxShaderCompilerThreads)(struct gl_context *ctx, unsigned count);
+   bool (*GetShaderProgramCompletionStatus)(struct gl_context *ctx,
+                                            struct gl_shader_program *shprog);
 };
 
 
 /**
  * Per-vertex functions.
  *
  * These are the functions which can appear between glBegin and glEnd.
  * Depending on whether we're inside or outside a glBegin/End pair
  * and whether we're in immediate mode or building a display list, these
  * functions behave differently.  This structure allows us to switch
diff --git a/src/mesa/main/extensions_table.h b/src/mesa/main/extensions_table.h
index b0492fed698..10ad3209963 100644
--- a/src/mesa/main/extensions_table.h
+++ b/src/mesa/main/extensions_table.h
@@ -92,20 +92,21 @@  EXT(ARB_internalformat_query                , ARB_internalformat_query
 EXT(ARB_internalformat_query2               , ARB_internalformat_query2              , GLL, GLC,  x ,  x , 2013)
 EXT(ARB_invalidate_subdata                  , dummy_true                             , GLL, GLC,  x ,  x , 2012)
 EXT(ARB_map_buffer_alignment                , dummy_true                             , GLL, GLC,  x ,  x , 2011)
 EXT(ARB_map_buffer_range                    , ARB_map_buffer_range                   , GLL, GLC,  x ,  x , 2008)
 EXT(ARB_multi_bind                          , dummy_true                             , GLL, GLC,  x ,  x , 2013)
 EXT(ARB_multi_draw_indirect                 , ARB_draw_indirect                      , GLL, GLC,  x ,  x , 2012)
 EXT(ARB_multisample                         , dummy_true                             , GLL,  x ,  x ,  x , 1994)
 EXT(ARB_multitexture                        , dummy_true                             , GLL,  x ,  x ,  x , 1998)
 EXT(ARB_occlusion_query                     , ARB_occlusion_query                    , GLL,  x ,  x ,  x , 2001)
 EXT(ARB_occlusion_query2                    , ARB_occlusion_query2                   , GLL, GLC,  x ,  x , 2003)
+EXT(ARB_parallel_shader_compile             , dummy_true                             , GLL, GLC,  x ,  x , 2015)
 EXT(ARB_pipeline_statistics_query           , ARB_pipeline_statistics_query          , GLL, GLC,  x ,  x , 2014)
 EXT(ARB_pixel_buffer_object                 , EXT_pixel_buffer_object                , GLL, GLC,  x ,  x , 2004)
 EXT(ARB_point_parameters                    , EXT_point_parameters                   , GLL,  x ,  x ,  x , 1997)
 EXT(ARB_point_sprite                        , ARB_point_sprite                       , GLL, GLC,  x ,  x , 2003)
 EXT(ARB_polygon_offset_clamp                , ARB_polygon_offset_clamp               , GLL, GLC,  x ,  x , 2017)
 EXT(ARB_post_depth_coverage                 , ARB_post_depth_coverage                , GLL, GLC,  x ,  x,  2015)
 EXT(ARB_program_interface_query             , dummy_true                             , GLL, GLC,  x ,  x , 2012)
 EXT(ARB_provoking_vertex                    , EXT_provoking_vertex                   , GLL, GLC,  x ,  x , 2009)
 EXT(ARB_query_buffer_object                 , ARB_query_buffer_object                , GLL, GLC,  x ,  x , 2013)
 EXT(ARB_robust_buffer_access_behavior       , ARB_robust_buffer_access_behavior      , GLL, GLC,  x ,  x , 2012)
@@ -328,20 +329,21 @@  EXT(INGR_blend_func_separate                , EXT_blend_func_separate
 
 EXT(INTEL_conservative_rasterization        , INTEL_conservative_rasterization       ,  x , GLC,  x ,  31, 2013)
 EXT(INTEL_performance_query                 , INTEL_performance_query                , GLL, GLC,  x , ES2, 2013)
 EXT(INTEL_shader_atomic_float_minmax        , INTEL_shader_atomic_float_minmax       , GLL, GLC,  x ,  x , 2018)
 
 EXT(KHR_blend_equation_advanced             , KHR_blend_equation_advanced            , GLL, GLC,  x , ES2, 2014)
 EXT(KHR_blend_equation_advanced_coherent    , KHR_blend_equation_advanced_coherent   , GLL, GLC,  x , ES2, 2014)
 EXT(KHR_context_flush_control               , dummy_true                             , GLL, GLC,  x , ES2, 2014)
 EXT(KHR_debug                               , dummy_true                             , GLL, GLC,  11, ES2, 2012)
 EXT(KHR_no_error                            , dummy_true                             , GLL, GLC, ES1, ES2, 2015)
+EXT(KHR_parallel_shader_compile             , dummy_true                             , GLL, GLC,  x , ES2, 2017)
 EXT(KHR_robust_buffer_access_behavior       , ARB_robust_buffer_access_behavior      , GLL, GLC,  x , ES2, 2014)
 EXT(KHR_robustness                          , KHR_robustness                         , GLL, GLC,  x , ES2, 2012)
 EXT(KHR_texture_compression_astc_hdr        , KHR_texture_compression_astc_hdr       , GLL, GLC,  x , ES2, 2012)
 EXT(KHR_texture_compression_astc_ldr        , KHR_texture_compression_astc_ldr       , GLL, GLC,  x , ES2, 2012)
 EXT(KHR_texture_compression_astc_sliced_3d  , KHR_texture_compression_astc_sliced_3d , GLL, GLC,  x , ES2, 2015)
 
 EXT(MESA_framebuffer_flip_y                 , MESA_framebuffer_flip_y                ,   x,   x,  x ,  31, 2018)
 EXT(MESA_pack_invert                        , MESA_pack_invert                       , GLL, GLC,  x ,  x , 2002)
 EXT(MESA_shader_integer_functions           , MESA_shader_integer_functions          , GLL, GLC,  x ,  30, 2016)
 EXT(MESA_texture_signed_rgba                , EXT_texture_snorm                      , GLL, GLC,  x ,  x , 2009)
diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py
index 8b351bcd2d2..60ec1a8598c 100644
--- a/src/mesa/main/get_hash_params.py
+++ b/src/mesa/main/get_hash_params.py
@@ -273,20 +273,23 @@  descriptor=[
   [ "PACK_SKIP_ROWS", "CONTEXT_INT(Pack.SkipRows), NO_EXTRA" ],
   [ "UNPACK_ROW_LENGTH", "CONTEXT_INT(Unpack.RowLength), NO_EXTRA" ],
   [ "UNPACK_SKIP_PIXELS", "CONTEXT_INT(Unpack.SkipPixels), NO_EXTRA" ],
   [ "UNPACK_SKIP_ROWS", "CONTEXT_INT(Unpack.SkipRows), NO_EXTRA" ],
   [ "UNPACK_SKIP_IMAGES", "CONTEXT_INT(Unpack.SkipImages), NO_EXTRA" ],
   [ "UNPACK_IMAGE_HEIGHT", "CONTEXT_INT(Unpack.ImageHeight), NO_EXTRA" ],
 
 # GL_ARB_draw_buffers
   [ "MAX_DRAW_BUFFERS_ARB", "CONTEXT_INT(Const.MaxDrawBuffers), NO_EXTRA" ],
 
+# GL_ARB_parallel_shader_compile
+  [ "MAX_SHADER_COMPILER_THREADS_ARB", "CONTEXT_INT(Hint.MaxShaderCompilerThreads), NO_EXTRA" ],
+
 # GL_EXT_framebuffer_object / GL_NV_fbo_color_attachments
   [ "MAX_COLOR_ATTACHMENTS", "CONTEXT_INT(Const.MaxColorAttachments), NO_EXTRA" ],
 
 # GL_ARB_draw_buffers / GL_NV_draw_buffers (for ES 2.0)
   [ "DRAW_BUFFER0_ARB", "BUFFER_ENUM16(ColorDrawBuffer[0]), NO_EXTRA" ],
   [ "DRAW_BUFFER1_ARB", "BUFFER_ENUM16(ColorDrawBuffer[1]), extra_valid_draw_buffer" ],
   [ "DRAW_BUFFER2_ARB", "BUFFER_ENUM16(ColorDrawBuffer[2]), extra_valid_draw_buffer" ],
   [ "DRAW_BUFFER3_ARB", "BUFFER_ENUM16(ColorDrawBuffer[3]), extra_valid_draw_buffer" ],
   [ "DRAW_BUFFER4_ARB", "BUFFER_ENUM16(ColorDrawBuffer[4]), extra_valid_draw_buffer" ],
   [ "DRAW_BUFFER5_ARB", "BUFFER_ENUM16(ColorDrawBuffer[5]), extra_valid_draw_buffer" ],
diff --git a/src/mesa/main/hint.c b/src/mesa/main/hint.c
index 5d0c15d35ab..2bcaeebc4aa 100644
--- a/src/mesa/main/hint.c
+++ b/src/mesa/main/hint.c
@@ -123,27 +123,39 @@  _mesa_Hint( GLenum target, GLenum mode )
       default:
          goto invalid_target;
    }
    return;
 
 invalid_target:
    _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)");
    return;
 }
 
+/* GL_ARB_parallel_shader_compile */
+void GLAPIENTRY
+_mesa_MaxShaderCompilerThreadsKHR(GLuint count)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   ctx->Hint.MaxShaderCompilerThreads = count;
+
+   if (ctx->Driver.SetMaxShaderCompilerThreads)
+      ctx->Driver.SetMaxShaderCompilerThreads(ctx, count);
+}
 
 /**********************************************************************/
 /*****                      Initialization                        *****/
 /**********************************************************************/
 
 void _mesa_init_hint( struct gl_context * ctx )
 {
    /* Hint group */
    ctx->Hint.PerspectiveCorrection = GL_DONT_CARE;
    ctx->Hint.PointSmooth = GL_DONT_CARE;
    ctx->Hint.LineSmooth = GL_DONT_CARE;
    ctx->Hint.PolygonSmooth = GL_DONT_CARE;
    ctx->Hint.Fog = GL_DONT_CARE;
    ctx->Hint.TextureCompression = GL_DONT_CARE;
    ctx->Hint.GenerateMipmap = GL_DONT_CARE;
    ctx->Hint.FragmentShaderDerivative = GL_DONT_CARE;
+   ctx->Hint.MaxShaderCompilerThreads = 0xffffffff;
 }
diff --git a/src/mesa/main/hint.h b/src/mesa/main/hint.h
index 87febfeecc0..2d7c710af26 100644
--- a/src/mesa/main/hint.h
+++ b/src/mesa/main/hint.h
@@ -36,14 +36,18 @@ 
 #ifndef HINT_H
 #define HINT_H
 
 #include "glheader.h"
 
 struct gl_context;
 
 extern void GLAPIENTRY
 _mesa_Hint( GLenum target, GLenum mode );
 
+/* GL_KHR_parallel_shader_compile */
+extern void GLAPIENTRY
+_mesa_MaxShaderCompilerThreadsKHR(GLuint count);
+
 extern void 
 _mesa_init_hint( struct gl_context * ctx );
 
 #endif
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 9bca5c153ad..9ccf3a7d94a 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -596,20 +596,21 @@  struct gl_fog_attrib
 struct gl_hint_attrib
 {
    GLenum16 PerspectiveCorrection;
    GLenum16 PointSmooth;
    GLenum16 LineSmooth;
    GLenum16 PolygonSmooth;
    GLenum16 Fog;
    GLenum16 TextureCompression;   /**< GL_ARB_texture_compression */
    GLenum16 GenerateMipmap;       /**< GL_SGIS_generate_mipmap */
    GLenum16 FragmentShaderDerivative; /**< GL_ARB_fragment_shader */
+   GLuint MaxShaderCompilerThreads; /**< GL_ARB_parallel_shader_compile */
 };
 
 
 /**
  * Lighting attribute group (GL_LIGHT_BIT).
  */
 struct gl_light_attrib
 {
    struct gl_light Light[MAX_LIGHTS];	/**< Array of light sources */
    struct gl_lightmodel Model;		/**< Lighting model */
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 2ea8d965aba..01342c04e8f 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -682,20 +682,26 @@  get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
       || _mesa_is_gles3(ctx);
 
    if (!shProg) {
       return;
    }
 
    switch (pname) {
    case GL_DELETE_STATUS:
       *params = shProg->DeletePending;
       return;
+   case GL_COMPLETION_STATUS_ARB:
+      if (ctx->Driver.GetShaderProgramCompletionStatus)
+         *params = ctx->Driver.GetShaderProgramCompletionStatus(ctx, shProg);
+      else
+         *params = GL_TRUE;
+      return;
    case GL_LINK_STATUS:
       *params = shProg->data->LinkStatus ? GL_TRUE : GL_FALSE;
       return;
    case GL_VALIDATE_STATUS:
       *params = shProg->data->Validated;
       return;
    case GL_INFO_LOG_LENGTH:
       *params = (shProg->data->InfoLog && shProg->data->InfoLog[0] != '\0') ?
          strlen(shProg->data->InfoLog) + 1 : 0;
       return;
@@ -953,20 +959,24 @@  get_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params)
       return;
    }
 
    switch (pname) {
    case GL_SHADER_TYPE:
       *params = shader->Type;
       break;
    case GL_DELETE_STATUS:
       *params = shader->DeletePending;
       break;
+   case GL_COMPLETION_STATUS_ARB:
+      /* _mesa_glsl_compile_shader is not offloaded to other threads. */
+      *params = GL_TRUE;
+      return;
    case GL_COMPILE_STATUS:
       *params = shader->CompileStatus ? GL_TRUE : GL_FALSE;
       break;
    case GL_INFO_LOG_LENGTH:
       *params = (shader->InfoLog && shader->InfoLog[0] != '\0') ?
          strlen(shader->InfoLog) + 1 : 0;
       break;
    case GL_SHADER_SOURCE_LENGTH:
       *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
       break;
diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp
index 672e4ce892a..37edfee587d 100644
--- a/src/mesa/main/tests/dispatch_sanity.cpp
+++ b/src/mesa/main/tests/dispatch_sanity.cpp
@@ -1191,20 +1191,22 @@  const struct function common_desktop_functions_possible[] = {
    { "glEvaluateDepthValuesARB", 30, -1 },
 
    /* GL_ARB_indirect_parameters */
    { "glMultiDrawArraysIndirectCountARB", 11, -1 },
    { "glMultiDrawElementsIndirectCountARB", 11, -1 },
 
    /* GL_AMD_framebuffer_multisample_advanced */
    { "glRenderbufferStorageMultisampleAdvancedAMD", 11, -1 },
    { "glNamedRenderbufferStorageMultisampleAdvancedAMD", 11, -1 },
 
+   { "glMaxShaderCompilerThreadsKHR", 11, -1 },
+
    { NULL, 0, -1 }
 };
 
 const struct function gl_compatibility_functions_possible[] = {
    { "glNewList", 10, _gloffset_NewList },
    { "glEndList", 10, _gloffset_EndList },
    { "glCallList", 10, _gloffset_CallList },
    { "glCallLists", 10, _gloffset_CallLists },
    { "glDeleteLists", 10, _gloffset_DeleteLists },
    { "glGenLists", 10, _gloffset_GenLists },
@@ -2237,20 +2239,23 @@  const struct function gles2_functions_possible[] = {
    /* GL_NV_conservative_raster_dilate */
    { "glConservativeRasterParameterfNV", 20, -1 },
 
    /* GL_NV_conservative_raster_pre_snap_triangles */
    { "glConservativeRasterParameteriNV", 20, -1 },
 
    /* GL_EXT_multisampled_render_to_texture */
    { "glRenderbufferStorageMultisampleEXT", 20, -1 },
    { "glFramebufferTexture2DMultisampleEXT", 20, -1 },
 
+   /* GL_KHR_parallel_shader_compile */
+   { "glMaxShaderCompilerThreadsKHR", 20, -1 },
+
    { NULL, 0, -1 }
 };
 
 const struct function gles3_functions_possible[] = {
    // We check for the aliased -EXT version in GLES 2
    // { "glBeginQuery", 30, -1 },
    { "glBeginTransformFeedback", 30, -1 },
    { "glBindBufferBase", 30, -1 },
    { "glBindBufferRange", 30, -1 },
    { "glBindSampler", 30, -1 },