summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/main/glspirv.c43
-rw-r--r--src/mesa/main/glspirv.h5
-rw-r--r--src/mesa/main/mtypes.h4
-rw-r--r--src/mesa/main/shaderapi.c46
-rw-r--r--src/mesa/main/shaderobj.c2
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);