mesa: implement SPIR-V loading in glShaderBinary
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Sat, 10 Jun 2017 18:35:21 +0000 (20:35 +0200)
committerEduardo Lima Mitev <elima@igalia.com>
Tue, 12 Dec 2017 07:18:32 +0000 (08:18 +0100)
v2: * Add a gl_shader_spirv_data member to gl_shader, which already
   encapsulates a gl_spirv_module where the binary will be saved.
   (Eduardo Lima)

    * Just use the 'spirv_data' member to know whether a gl_shader has
   the SPIR_V_BINARY_ARB state. (Timothy Arceri)

    * Remove redundant argument checks. Move extension presence check
   to API entry point where the rest of checks are. Retype 'n' and
   'length'arguments to use the correct and more standard types.
   (Ian Romanick)

    * Fix some nitpicks. (Ian Romanick)

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/mesa/main/glspirv.c
src/mesa/main/glspirv.h
src/mesa/main/mtypes.h
src/mesa/main/shaderapi.c
src/mesa/main/shaderobj.c

index 8d1e652e088e12a1a494e1248a20bcf85fe7bd00..7eb8f906c2d84b062ffdc18a635334bd7391f1a6 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "errors.h"
 
+#include "errors.h"
+
 #include "util/u_atomic.h"
 
 void
@@ -59,6 +61,47 @@ _mesa_shader_spirv_data_reference(struct gl_shader_spirv_data **dest,
       p_atomic_inc(&src->RefCount);
 }
 
+void
+_mesa_spirv_shader_binary(struct gl_context *ctx,
+                          unsigned n, struct gl_shader **shaders,
+                          const void* binary, size_t length)
+{
+   struct gl_spirv_module *module;
+   struct gl_shader_spirv_data *spirv_data;
+
+   assert(length >= 0);
+
+   module = malloc(sizeof(*module) + length);
+   if (!module) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderBinary");
+      return;
+   }
+
+   p_atomic_set(&module->RefCount, 0);
+   module->Length = length;
+   memcpy(&module->Binary[0], binary, length);
+
+   for (int i = 0; i < n; ++i) {
+      struct gl_shader *sh = shaders[i];
+
+      spirv_data = rzalloc(NULL, struct gl_shader_spirv_data);
+      _mesa_shader_spirv_data_reference(&sh->spirv_data, spirv_data);
+      _mesa_spirv_module_reference(&spirv_data->SpirVModule, module);
+
+      sh->CompileStatus = compile_failure;
+
+      free((void *)sh->Source);
+      sh->Source = NULL;
+      free((void *)sh->FallbackSource);
+      sh->FallbackSource = NULL;
+
+      ralloc_free(sh->ir);
+      sh->ir = NULL;
+      ralloc_free(sh->symbols);
+      sh->symbols = NULL;
+   }
+}
+
 void GLAPIENTRY
 _mesa_SpecializeShaderARB(GLuint shader,
                           const GLchar *pEntryPoint,
index b8a0125ea9f2d16087f7d1414ef5925dc9432c8f..ba281f68bef6559392b64c000d7f80bec99476cb 100644 (file)
@@ -71,6 +71,11 @@ void
 _mesa_shader_spirv_data_reference(struct gl_shader_spirv_data **dest,
                                   struct gl_shader_spirv_data *src);
 
+void
+_mesa_spirv_shader_binary(struct gl_context *ctx,
+                          unsigned n, struct gl_shader **shaders,
+                          const void* binary, size_t length);
+
 /**
  * \name API functions
  */
index ceb7ecc960921cb1002c8e7d99af1af045f63895..b372921e9f09c7eda3e1b5ccda745acd417b2589 100644 (file)
@@ -98,6 +98,7 @@ struct st_context;
 struct gl_uniform_storage;
 struct prog_instruction;
 struct gl_program_parameter_list;
+struct gl_shader_spirv_data;
 struct set;
 struct vbo_context;
 /*@}*/
@@ -2645,6 +2646,9 @@ struct gl_shader
    GLuint TransformFeedbackBufferStride[MAX_FEEDBACK_BUFFERS];
 
    struct gl_shader_info info;
+
+   /* ARB_gl_spirv related data */
+   struct gl_shader_spirv_data *spirv_data;
 };
 
 
index 4607cbb99bc811aeda274c1a3125c7f16cfc0015..f66172c4797ced9dc8abf80357805137d106df72 100644 (file)
@@ -42,6 +42,7 @@
 #include "main/context.h"
 #include "main/dispatch.h"
 #include "main/enums.h"
+#include "main/glspirv.h"
 #include "main/hash.h"
 #include "main/mtypes.h"
 #include "main/pipelineobj.h"
@@ -1056,6 +1057,16 @@ set_shader_source(struct gl_shader *sh, const GLchar *source)
 {
    assert(sh);
 
+   /* The GL_ARB_gl_spirv spec adds the following to the end of the description
+    * of ShaderSource:
+    *
+    *   "If <shader> was previously associated with a SPIR-V module (via the
+    *    ShaderBinary command), that association is broken. Upon successful
+    *    completion of this command the SPIR_V_BINARY_ARB state of <shader>
+    *    is set to FALSE."
+    */
+   _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL);
+
    if (sh->CompileStatus == compile_skipped && !sh->FallbackSource) {
       /* If shader was previously compiled back-up the source in case of cache
        * fallback.
@@ -2137,9 +2148,7 @@ _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat,
                    const void* binary, GLint length)
 {
    GET_CURRENT_CONTEXT(ctx);
-   (void) shaders;
-   (void) binaryformat;
-   (void) binary;
+   struct gl_shader **sh;
 
    /* Page 68, section 7.2 'Shader Binaries" of the of the OpenGL ES 3.1, and
     * page 88 of the OpenGL 4.5 specs state:
@@ -2153,6 +2162,37 @@ _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat,
       return;
    }
 
+   /* Get all shader objects at once so we can make the operation
+    * all-or-nothing.
+    */
+   if (n > SIZE_MAX / sizeof(*sh)) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderBinary(count)");
+      return;
+   }
+
+   sh = alloca(sizeof(*sh) * (size_t)n);
+   if (!sh) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderBinary");
+      return;
+   }
+
+   for (int i = 0; i < n; ++i) {
+      sh[i] = _mesa_lookup_shader_err(ctx, shaders[i], "glShaderBinary");
+      if (!sh[i])
+         return;
+   }
+
+   if (binaryformat == GL_SHADER_BINARY_FORMAT_SPIR_V_ARB) {
+      if (!ctx->Extensions.ARB_gl_spirv) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderBinary(SPIR-V)");
+      } else if (n > 0) {
+         _mesa_spirv_shader_binary(ctx, (unsigned) n, sh, binary,
+                                   (size_t) length);
+      }
+
+      return;
+   }
+
    _mesa_error(ctx, GL_INVALID_ENUM, "glShaderBinary(format)");
 }
 
index ce2e3df4faec33aa4b32ead7e2d541fa41d9fd6c..5c1cdd6b27ab59cf46018f51107a638d67e7e0f9 100644 (file)
@@ -33,6 +33,7 @@
 #include "compiler/glsl/string_to_uint_map.h"
 #include "main/glheader.h"
 #include "main/context.h"
+#include "main/glspirv.h"
 #include "main/hash.h"
 #include "main/mtypes.h"
 #include "main/shaderapi.h"
@@ -121,6 +122,7 @@ _mesa_new_shader(GLuint name, gl_shader_stage stage)
 void
 _mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh)
 {
+   _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL);
    free((void *)sh->Source);
    free((void *)sh->FallbackSource);
    free(sh->Label);