#include <stdbool.h>
+#include <c99_alloca.h>
#include "main/glheader.h"
#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"
#include "main/program_binary.h"
#include "main/shaderapi.h"
#include "main/shaderobj.h"
+#include "main/state.h"
#include "main/transformfeedback.h"
#include "main/uniforms.h"
#include "compiler/glsl/glsl_parser_extras.h"
{
for (int i = 0; i < MESA_SHADER_STAGES; i++) {
_mesa_reference_program(ctx, &ctx->Shader.CurrentProgram[i], NULL);
+ _mesa_reference_shader_program(ctx,
+ &ctx->Shader.ReferencedPrograms[i],
+ NULL);
}
_mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL);
/* True if geometry shaders (of the form that was adopted into GLSL 1.50
* and GL 3.2) are available in this context
*/
- const bool has_core_gs = _mesa_has_geometry_shaders(ctx);
+ const bool has_gs = _mesa_has_geometry_shaders(ctx);
const bool has_tess = _mesa_has_tessellation(ctx);
/* Are uniform buffer objects available in this context?
*params = shProg->TransformFeedback.BufferMode;
return;
case GL_GEOMETRY_VERTICES_OUT:
- if (!has_core_gs)
+ if (!has_gs)
break;
if (check_gs_query(ctx, shProg)) {
*params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
}
return;
case GL_GEOMETRY_SHADER_INVOCATIONS:
- if (!has_core_gs || !ctx->Extensions.ARB_gpu_shader5)
+ if (!has_gs || !ctx->Extensions.ARB_gpu_shader5)
break;
if (check_gs_query(ctx, shProg)) {
*params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
}
return;
case GL_GEOMETRY_INPUT_TYPE:
- if (!has_core_gs)
+ if (!has_gs)
break;
if (check_gs_query(ctx, shProg)) {
*params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
}
return;
case GL_GEOMETRY_OUTPUT_TYPE:
- if (!has_core_gs)
+ if (!has_gs)
break;
if (check_gs_query(ctx, shProg)) {
*params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
*params = shProg->BinaryRetreivableHint;
return;
case GL_PROGRAM_BINARY_LENGTH:
- if (ctx->Const.NumProgramBinaryFormats == 0) {
+ if (ctx->Const.NumProgramBinaryFormats == 0 || !shProg->data->LinkStatus) {
*params = 0;
} else {
_mesa_get_program_binary_length(ctx, shProg, params);
}
case GL_PROGRAM_SEPARABLE:
/* If the program has not been linked, return initial value 0. */
- *params = (shProg->data->LinkStatus == linking_failure) ? 0 : shProg->SeparateShader;
+ *params = (shProg->data->LinkStatus == LINKING_FAILURE) ? 0 : shProg->SeparateShader;
return;
/* ARB_tessellation_shader */
case GL_SHADER_SOURCE_LENGTH:
*params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
break;
+ case GL_SPIR_V_BINARY_ARB:
+ *params = (shader->spirv_data != NULL);
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
return;
{
assert(sh);
- if (sh->CompileStatus == compile_skipped && !sh->FallbackSource) {
+ /* 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.
*/
if (!sh)
return;
+ /* The GL_ARB_gl_spirv spec says:
+ *
+ * "Add a new error for the CompileShader command:
+ *
+ * An INVALID_OPERATION error is generated if the SPIR_V_BINARY_ARB
+ * state of <shader> is TRUE."
+ */
+ if (sh->spirv_data) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glCompileShader(SPIR-V)");
+ return;
+ }
+
if (!sh->Source) {
/* If the user called glCompileShader without first calling
* glShaderSource, we should fail to compile, but not raise a GL_ERROR.
*/
- sh->CompileStatus = compile_failure;
+ sh->CompileStatus = COMPILE_FAILURE;
} else {
if (ctx->_Shader->Flags & GLSL_DUMP) {
_mesa_log("GLSL source for %s shader %d:\n",
ralloc_free(filename);
}
- if (shProg->data->LinkStatus == linking_failure &&
+ if (shProg->data->LinkStatus == LINKING_FAILURE &&
(ctx->_Shader->Flags & GLSL_REPORT_ERRORS)) {
_mesa_debug(ctx, "Error linking program %u:\n%s\n",
shProg->Name, shProg->data->InfoLog);
}
+ _mesa_update_vertex_processing_mode(ctx);
+
/* debug code */
if (0) {
GLuint i;
_mesa_BindProgramPipeline(ctx->Pipeline.Current->Name);
}
}
+
+ _mesa_update_vertex_processing_mode(ctx);
}
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:
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)");
}
return;
}
- *length = 0;
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetProgramBinary(driver supports zero binary formats)");
-
- (void) binaryFormat;
- (void) binary;
+ if (ctx->Const.NumProgramBinaryFormats == 0) {
+ *length = 0;
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramBinary(driver supports zero binary formats)");
+ } else {
+ _mesa_get_program_binary(ctx, shProg, bufSize, length, binaryFormat,
+ binary);
+ assert(*length == 0 || *binaryFormat == GL_PROGRAM_BINARY_FORMAT_MESA);
+ }
}
void GLAPIENTRY
if (!shProg)
return;
- (void) binaryFormat;
- (void) binary;
+ _mesa_clear_shader_program_data(ctx, shProg);
+ shProg->data = _mesa_create_shader_program_data();
/* Section 2.3.1 (Errors) of the OpenGL 4.5 spec says:
*
return;
}
- /* The ARB_get_program_binary spec says:
- *
- * "<binaryFormat> and <binary> must be those returned by a previous
- * call to GetProgramBinary, and <length> must be the length of the
- * program binary as returned by GetProgramBinary or GetProgramiv with
- * <pname> PROGRAM_BINARY_LENGTH. Loading the program binary will fail,
- * setting the LINK_STATUS of <program> to FALSE, if these conditions
- * are not met."
- *
- * Since any value of binaryFormat passed "is not one of those specified as
- * allowable for [this] command, an INVALID_ENUM error is generated."
- */
- shProg->data->LinkStatus = linking_failure;
- _mesa_error(ctx, GL_INVALID_ENUM, "glProgramBinary");
+ if (ctx->Const.NumProgramBinaryFormats == 0 ||
+ binaryFormat != GL_PROGRAM_BINARY_FORMAT_MESA) {
+ /* The ARB_get_program_binary spec says:
+ *
+ * "<binaryFormat> and <binary> must be those returned by a previous
+ * call to GetProgramBinary, and <length> must be the length of the
+ * program binary as returned by GetProgramBinary or GetProgramiv with
+ * <pname> PROGRAM_BINARY_LENGTH. Loading the program binary will fail,
+ * setting the LINK_STATUS of <program> to FALSE, if these conditions
+ * are not met."
+ *
+ * Since any value of binaryFormat passed "is not one of those specified as
+ * allowable for [this] command, an INVALID_ENUM error is generated."
+ */
+ shProg->data->LinkStatus = LINKING_FAILURE;
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramBinary");
+ } else {
+ _mesa_program_binary(ctx, shProg, binaryFormat, binary, length);
+ }
}
&shTarget->ReferencedPrograms[stage],
shProg);
_mesa_reference_program(ctx, target, prog);
+ if (stage == MESA_SHADER_VERTEX)
+ _mesa_update_vertex_processing_mode(ctx);
return;
}
/* Possibly... */
if (active-user-defined-varyings-in-linked-program) {
append-error-to-info-log;
- shProg->data->LinkStatus = linking_failure;
+ shProg->data->LinkStatus = LINKING_FAILURE;
}
#endif
}