diff options
author | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2017-06-10 20:35:21 +0200 |
---|---|---|
committer | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2017-07-13 13:27:38 +0200 |
commit | 91c8e79e01a3f68fc4e9a4dab69fb559ce2ddf50 (patch) | |
tree | 1ce36349aa7fd3edf77cb04e2b81e0efb46064b9 | |
parent | 91450ce25ed64881883342ff9fb8dbca191f8584 (diff) |
mesa: implement SPIR-V loading in glShaderBinary
-rw-r--r-- | src/mesa/main/glspirv.c | 47 | ||||
-rw-r--r-- | src/mesa/main/glspirv.h | 5 | ||||
-rw-r--r-- | src/mesa/main/shaderapi.c | 31 |
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)"); } |