#include "main/shaderobj.h"
#include "main/transformfeedback.h"
#include "main/uniforms.h"
-#include "glsl/glsl_parser_extras.h"
-#include "glsl/ir_uniform.h"
+#include "compiler/glsl/glsl_parser_extras.h"
+#include "compiler/glsl/ir_uniform.h"
#include "program/program.h"
#include "program/prog_parameter.h"
#include "util/ralloc.h"
* Callback for deleting a pipeline object. Called by _mesa_HashDeleteAll().
*/
static void
-delete_pipelineobj_cb(GLuint id, void *data, void *userData)
+delete_pipelineobj_cb(UNUSED GLuint id, void *data, void *userData)
{
struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data;
struct gl_context *ctx = (struct gl_context *) userData;
* shader stages in the pipeline program pipeline object are not
* modified."
*/
- if (!shProg->LinkStatus) {
+ if (!shProg->data->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUseProgramStages(program not linked)");
return;
if ((stages & GL_COMPUTE_SHADER_BIT) != 0)
_mesa_use_shader_program(ctx, GL_COMPUTE_SHADER, shProg, pipe);
+
+ pipe->Validated = false;
}
/**
*/
pipe->EverBound = GL_TRUE;
- if ((shProg != NULL) && !shProg->LinkStatus) {
+ if ((shProg != NULL) && !shProg->data->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glActiveShaderProgram(program %u not linked)", shProg->Name);
return;
_mesa_bind_pipeline(struct gl_context *ctx,
struct gl_pipeline_object *pipe)
{
+ int i;
/* First bind the Pipeline to pipeline binding point */
_mesa_reference_pipeline_object(ctx, &ctx->Pipeline.Current, pipe);
FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
- if (ctx->Driver.UseProgram)
- ctx->Driver.UseProgram(ctx, NULL);
+ for (i = 0; i < MESA_SHADER_STAGES; i++)
+ _mesa_shader_program_init_subroutine_defaults(ctx, ctx->_Shader->CurrentProgram[i]);
}
}
/* Are geometry shaders available in this context?
*/
const bool has_gs = _mesa_has_geometry_shaders(ctx);
- const bool has_tess = _mesa_has_tessellation(ctx);;
+ const bool has_tess = _mesa_has_tessellation(ctx);
if (!pipe) {
_mesa_error(ctx, GL_INVALID_OPERATION,
*params = pipe->ActiveProgram ? pipe->ActiveProgram->Name : 0;
return;
case GL_INFO_LOG_LENGTH:
- *params = pipe->InfoLog ? strlen(pipe->InfoLog) + 1 : 0;
+ *params = (pipe->InfoLog && pipe->InfoLog[0] != '\0') ?
+ strlen(pipe->InfoLog) + 1 : 0;
return;
case GL_VALIDATE_STATUS:
*params = pipe->Validated;
static bool
program_stages_interleaved_illegally(const struct gl_pipeline_object *pipe)
{
- struct gl_shader_program *prev = NULL;
- unsigned i, j;
+ unsigned prev_linked_stages = 0;
/* Look for programs bound to stages: A -> B -> A, with any intervening
* sequence of unrelated programs or empty stages.
*/
- for (i = 0; i < MESA_SHADER_STAGES; i++) {
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_shader_program *cur = pipe->CurrentProgram[i];
- /* Empty stages anywhere in the pipe are OK */
- if (!cur || cur == prev)
+ /* Empty stages anywhere in the pipe are OK. Also we can be confident
+ * that if the linked_stages mask matches we are looking at the same
+ * linked program because a previous validation call to
+ * program_stages_all_active() will have already failed if two different
+ * programs with the sames stages linked are not active for all linked
+ * stages.
+ */
+ if (!cur || cur->data->linked_stages == prev_linked_stages)
continue;
- if (prev) {
+ if (prev_linked_stages) {
/* We've seen an A -> B transition; look at the rest of the pipe
* to see if we ever see A again.
*/
- for (j = i + 1; j < MESA_SHADER_STAGES; j++) {
- if (pipe->CurrentProgram[j] == prev)
- return true;
- }
+ if (prev_linked_stages >> (i + 1))
+ return true;
}
- prev = cur;
+ prev_linked_stages = cur->data->linked_stages;
}
return false;
extern GLboolean
_mesa_validate_program_pipeline(struct gl_context* ctx,
- struct gl_pipeline_object *pipe,
- GLboolean IsBound)
+ struct gl_pipeline_object *pipe)
{
unsigned i;
bool program_empty = true;
*/
for (i = 0; i < MESA_SHADER_STAGES; i++) {
if (!program_stages_all_active(pipe, pipe->CurrentProgram[i])) {
- goto err;
+ return GL_FALSE;
}
}
ralloc_strdup(pipe,
"Program is active for multiple shader stages with an "
"intervening stage provided by another program");
- goto err;
+ return GL_FALSE;
}
/* Section 2.11.11 (Shader Execution), subheading "Validation," of the
pipe->CurrentProgram[MESA_SHADER_TESS_CTRL] ||
pipe->CurrentProgram[MESA_SHADER_TESS_EVAL])) {
pipe->InfoLog = ralloc_strdup(pipe, "Program lacks a vertex shader");
- goto err;
+ return GL_FALSE;
}
/* Section 2.11.11 (Shader Execution), subheading "Validation," of the
"Program %d was relinked without "
"PROGRAM_SEPARABLE state",
pipe->CurrentProgram[i]->Name);
- goto err;
+ return GL_FALSE;
}
}
}
if (program_empty) {
- goto err;
+ return GL_FALSE;
}
/* Section 2.11.11 (Shader Execution), subheading "Validation," of the
* maximum number of texture image units allowed."
*/
if (!_mesa_sampler_uniforms_pipeline_are_valid(pipe))
- goto err;
+ return GL_FALSE;
- pipe->Validated = GL_TRUE;
- return GL_TRUE;
+ /* Validate inputs against outputs, this cannot be done during linking
+ * since programs have been linked separately from each other.
+ *
+ * Section 11.1.3.11 (Validation) of the OpenGL 4.5 Core Profile spec says:
+ *
+ * "Separable program objects may have validation failures that cannot be
+ * detected without the complete program pipeline. Mismatched interfaces,
+ * improper usage of program objects together, and the same
+ * state-dependent failures can result in validation errors for such
+ * program objects."
+ *
+ * OpenGL ES 3.1 specification has the same text.
+ *
+ * Section 11.1.3.11 (Validation) of the OpenGL ES spec also says:
+ *
+ * An INVALID_OPERATION error is generated by any command that transfers
+ * vertices to the GL or launches compute work if the current set of
+ * active program objects cannot be executed, for reasons including:
+ *
+ * * The current program pipeline object contains a shader interface
+ * that doesn't have an exact match (see section 7.4.1)
+ *
+ * Based on this, only perform the most-strict checking on ES or when the
+ * application has created a debug context.
+ */
+ if ((_mesa_is_gles(ctx) || (ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT)) &&
+ !_mesa_validate_pipeline_io(pipe)) {
+ if (_mesa_is_gles(ctx))
+ return GL_FALSE;
-err:
- if (IsBound)
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glValidateProgramPipeline failed to validate the pipeline");
+ static GLuint msg_id = 0;
+
+ _mesa_gl_debug(ctx, &msg_id,
+ MESA_DEBUG_SOURCE_API,
+ MESA_DEBUG_TYPE_PORTABILITY,
+ MESA_DEBUG_SEVERITY_MEDIUM,
+ "glValidateProgramPipeline: pipeline %u does not meet "
+ "strict OpenGL ES 3.1 requirements and may not be "
+ "portable across desktop hardware\n",
+ pipe->Name);
+ }
- return GL_FALSE;
+ pipe->Validated = GL_TRUE;
+ return GL_TRUE;
}
/**
return;
}
- /* ValidateProgramPipeline should not throw errors when pipeline validation
- * fails and should instead only update the validation status. We pass
- * false for IsBound to avoid an error being thrown.
- */
- _mesa_validate_program_pipeline(ctx, pipe, false);
-
- /* Validate inputs against outputs, this cannot be done during linking
- * since programs have been linked separately from each other.
- *
- * From OpenGL 4.5 Core spec:
- * "Separable program objects may have validation failures that cannot be
- * detected without the complete program pipeline. Mismatched interfaces,
- * improper usage of program objects together, and the same
- * state-dependent failures can result in validation errors for such
- * program objects."
- *
- * OpenGL ES 3.1 specification has the same text.
- */
- if (!_mesa_validate_pipeline_io(pipe))
- pipe->Validated = GL_FALSE;
+ _mesa_validate_program_pipeline(ctx, pipe);
}
void GLAPIENTRY
return;
}
- if (pipe->InfoLog)
- _mesa_copy_string(infoLog, bufSize, length, pipe->InfoLog);
- else
- *length = 0;
+ _mesa_copy_string(infoLog, bufSize, length, pipe->InfoLog);
}