diff options
-rw-r--r-- | src/mesa/main/glspirv.c | 43 | ||||
-rw-r--r-- | src/mesa/main/glspirv.h | 5 | ||||
-rw-r--r-- | src/mesa/main/mtypes.h | 4 | ||||
-rw-r--r-- | src/mesa/main/shaderapi.c | 46 | ||||
-rw-r--r-- | src/mesa/main/shaderobj.c | 2 |
5 files changed, 97 insertions, 3 deletions
diff --git a/src/mesa/main/glspirv.c b/src/mesa/main/glspirv.c index 8d1e652e088..7eb8f906c2d 100644 --- a/src/mesa/main/glspirv.c +++ b/src/mesa/main/glspirv.c @@ -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, diff --git a/src/mesa/main/glspirv.h b/src/mesa/main/glspirv.h index b8a0125ea9f..ba281f68bef 100644 --- a/src/mesa/main/glspirv.h +++ b/src/mesa/main/glspirv.h @@ -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 */ diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index ceb7ecc9609..b372921e9f0 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -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; }; diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 4607cbb99bc..f66172c4797 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -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)"); } diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c index ce2e3df4fae..5c1cdd6b27a 100644 --- a/src/mesa/main/shaderobj.c +++ b/src/mesa/main/shaderobj.c @@ -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); |