summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolai Hähnle <nicolai.haehnle@amd.com>2017-06-10 20:35:21 +0200
committerNicolai Hähnle <nicolai.haehnle@amd.com>2017-07-13 13:27:38 +0200
commit91c8e79e01a3f68fc4e9a4dab69fb559ce2ddf50 (patch)
tree1ce36349aa7fd3edf77cb04e2b81e0efb46064b9
parent91450ce25ed64881883342ff9fb8dbca191f8584 (diff)
mesa: implement SPIR-V loading in glShaderBinary
-rw-r--r--src/mesa/main/glspirv.c47
-rw-r--r--src/mesa/main/glspirv.h5
-rw-r--r--src/mesa/main/shaderapi.c31
3 files changed, 79 insertions, 4 deletions
diff --git a/src/mesa/main/glspirv.c b/src/mesa/main/glspirv.c
index eb86935663..e75286aeb7 100644
--- a/src/mesa/main/glspirv.c
+++ b/src/mesa/main/glspirv.c
@@ -23,6 +23,8 @@
#include "glspirv.h"
+#include "errors.h"
+
#include "util/u_atomic.h"
void
@@ -42,6 +44,51 @@ _mesa_spirv_module_reference(struct gl_spirv_module **dest,
p_atomic_inc(&src->RefCount);
}
+void
+_mesa_spirv_shader_binary(struct gl_context *ctx,
+ GLint n, struct gl_shader **shaders,
+ const void* binary, GLint length)
+{
+ struct gl_spirv_module *module;
+
+ if (!ctx->Extensions.ARB_gl_spirv) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderBinary(SPIR-V)");
+ return;
+ }
+
+ if (n <= 0)
+ return;
+
+ assert(length >= 0);
+
+ module = malloc(sizeof(*module) + (size_t)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];
+ _mesa_spirv_module_reference(&sh->SpirVModule, module);
+ sh->SpirVBinary = GL_TRUE;
+ 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,
diff --git a/src/mesa/main/glspirv.h b/src/mesa/main/glspirv.h
index 4e033735cf..67e7c593cb 100644
--- a/src/mesa/main/glspirv.h
+++ b/src/mesa/main/glspirv.h
@@ -46,6 +46,11 @@ void
_mesa_spirv_module_reference(struct gl_spirv_module **dest,
struct gl_spirv_module *src);
+void
+_mesa_spirv_shader_binary(struct gl_context *ctx,
+ GLint n, struct gl_shader **shaders,
+ const void* binary, GLint length);
+
/**
* \name API functions
*/
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 37b9884839..48e61387f2 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -36,7 +36,7 @@
* 2. Insert FLUSH_VERTICES calls in various places
*/
-
+#include <alloca.h>
#include <stdbool.h>
#include "main/glheader.h"
#include "main/context.h"
@@ -2057,9 +2057,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:
@@ -2073,6 +2071,31 @@ _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) {
+ _mesa_spirv_shader_binary(ctx, n, sh, binary, length);
+ return;
+ }
+
_mesa_error(ctx, GL_INVALID_ENUM, "glShaderBinary(format)");
}