Ejemplo n.º 1
0
extern GLboolean
_mesa_validate_program_pipeline(struct gl_context* ctx,
                                struct gl_pipeline_object *pipe,
                                GLboolean IsBound)
{
   unsigned i;

   pipe->Validated = GL_FALSE;

   /* Release and reset the info log.
    */
   if (pipe->InfoLog != NULL)
      ralloc_free(pipe->InfoLog);

   pipe->InfoLog = NULL;

   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
    * OpenGL 4.1 spec says:
    *
    *     "[INVALID_OPERATION] is generated by any command that transfers
    *     vertices to the GL if:
    *
    *         - A program object is active for at least one, but not all of
    *           the shader stages that were present when the program was
    *           linked."
    *
    * For each possible program stage, verify that the program bound to that
    * stage has all of its stages active.  In other words, if the program
    * bound to the vertex stage also has a fragment shader, the fragment
    * shader must also be bound to the fragment stage.
    */
   for (i = 0; i < MESA_SHADER_STAGES; i++) {
      if (!program_stages_all_active(pipe, pipe->CurrentProgram[i])) {
         goto err;
      }
   }

   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
    * OpenGL 4.1 spec says:
    *
    *     "[INVALID_OPERATION] is generated by any command that transfers
    *     vertices to the GL if:
    *
    *         ...
    *
    *         - One program object is active for at least two shader stages
    *           and a second program is active for a shader stage between two
    *           stages for which the first program was active."
    *
    * Without Tesselation, the only case where this can occur is the geometry
    * shader between the fragment shader and vertex shader.
    */
   if (pipe->CurrentProgram[MESA_SHADER_GEOMETRY]
       && pipe->CurrentProgram[MESA_SHADER_FRAGMENT]
       && pipe->CurrentProgram[MESA_SHADER_VERTEX]) {
      if (pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name == pipe->CurrentProgram[MESA_SHADER_FRAGMENT]->Name &&
          pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Name != pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name) {
         pipe->InfoLog =
            ralloc_asprintf(pipe,
                            "Program %d is active for geometry stage between "
                            "two stages for which another program %d is "
                            "active",
                            pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Name,
                            pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name);
         goto err;
      }
   }

   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
    * OpenGL 4.1 spec says:
    *
    *     "[INVALID_OPERATION] is generated by any command that transfers
    *     vertices to the GL if:
    *
    *         ...
    *
    *         - There is an active program for tessellation control,
    *           tessellation evaluation, or geometry stages with corresponding
    *           executable shader, but there is no active program with
    *           executable vertex shader."
    */
   if (!pipe->CurrentProgram[MESA_SHADER_VERTEX]
       && pipe->CurrentProgram[MESA_SHADER_GEOMETRY]) {
      pipe->InfoLog = ralloc_strdup(pipe, "Program lacks a vertex shader");
      goto err;
   }

   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
    * OpenGL 4.1 spec says:
    *
    *     "[INVALID_OPERATION] is generated by any command that transfers
    *     vertices to the GL if:
    *
    *         ...
    *
    *         - There is no current program object specified by UseProgram,
    *           there is a current program pipeline object, and the current
    *           program for any shader stage has been relinked since being
    *           applied to the pipeline object via UseProgramStages with the
    *           PROGRAM_SEPARABLE parameter set to FALSE.
    */
   for (i = 0; i < MESA_SHADER_STAGES; i++) {
      if (pipe->CurrentProgram[i] && !pipe->CurrentProgram[i]->SeparateShader) {
         pipe->InfoLog = ralloc_asprintf(pipe,
                                         "Program %d was relinked without "
                                         "PROGRAM_SEPARABLE state",
                                         pipe->CurrentProgram[i]->Name);
         goto err;
      }
   }

   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
    * OpenGL 4.1 spec says:
    *
    *     "[INVALID_OPERATION] is generated by any command that transfers
    *     vertices to the GL if:
    *
    *         ...
    *
    *         - Any two active samplers in the current program object are of
    *           different types, but refer to the same texture image unit.
    *
    *         - The number of active samplers in the program exceeds the
    *           maximum number of texture image units allowed."
    */
   if (!_mesa_sampler_uniforms_pipeline_are_valid(pipe))
      goto err;

   pipe->Validated = GL_TRUE;
   return GL_TRUE;

err:
   if (IsBound)
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glValidateProgramPipeline failed to validate the pipeline");

   return GL_FALSE;
}
extern GLboolean
_mesa_validate_program_pipeline(struct gl_context* ctx,
                                struct gl_pipeline_object *pipe,
                                GLboolean IsBound)
{
   unsigned i;
   bool program_empty = true;

   pipe->Validated = GL_FALSE;

   /* Release and reset the info log.
    */
   if (pipe->InfoLog != NULL)
      ralloc_free(pipe->InfoLog);

   pipe->InfoLog = NULL;

   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
    * OpenGL 4.1 spec says:
    *
    *     "[INVALID_OPERATION] is generated by any command that transfers
    *     vertices to the GL if:
    *
    *         - A program object is active for at least one, but not all of
    *           the shader stages that were present when the program was
    *           linked."
    *
    * For each possible program stage, verify that the program bound to that
    * stage has all of its stages active.  In other words, if the program
    * bound to the vertex stage also has a fragment shader, the fragment
    * shader must also be bound to the fragment stage.
    */
   for (i = 0; i < MESA_SHADER_STAGES; i++) {
      if (!program_stages_all_active(pipe, pipe->CurrentProgram[i])) {
         goto err;
      }
   }

   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
    * OpenGL 4.1 spec says:
    *
    *     "[INVALID_OPERATION] is generated by any command that transfers
    *     vertices to the GL if:
    *
    *         ...
    *
    *         - One program object is active for at least two shader stages
    *           and a second program is active for a shader stage between two
    *           stages for which the first program was active."
    */
   if (program_stages_interleaved_illegally(pipe)) {
      pipe->InfoLog =
         ralloc_strdup(pipe,
                       "Program is active for multiple shader stages with an "
                       "intervening stage provided by another program");
      goto err;
   }

   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
    * OpenGL 4.1 spec says:
    *
    *     "[INVALID_OPERATION] is generated by any command that transfers
    *     vertices to the GL if:
    *
    *         ...
    *
    *         - There is an active program for tessellation control,
    *           tessellation evaluation, or geometry stages with corresponding
    *           executable shader, but there is no active program with
    *           executable vertex shader."
    */
   if (!pipe->CurrentProgram[MESA_SHADER_VERTEX]
       && (pipe->CurrentProgram[MESA_SHADER_GEOMETRY] ||
           pipe->CurrentProgram[MESA_SHADER_TESS_CTRL] ||
           pipe->CurrentProgram[MESA_SHADER_TESS_EVAL])) {
      pipe->InfoLog = ralloc_strdup(pipe, "Program lacks a vertex shader");
      goto err;
   }

   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
    * OpenGL 4.1 spec says:
    *
    *     "[INVALID_OPERATION] is generated by any command that transfers
    *     vertices to the GL if:
    *
    *         ...
    *
    *         - There is no current program object specified by UseProgram,
    *           there is a current program pipeline object, and the current
    *           program for any shader stage has been relinked since being
    *           applied to the pipeline object via UseProgramStages with the
    *           PROGRAM_SEPARABLE parameter set to FALSE.
    */
   for (i = 0; i < MESA_SHADER_STAGES; i++) {
      if (pipe->CurrentProgram[i] && !pipe->CurrentProgram[i]->SeparateShader) {
         pipe->InfoLog = ralloc_asprintf(pipe,
                                         "Program %d was relinked without "
                                         "PROGRAM_SEPARABLE state",
                                         pipe->CurrentProgram[i]->Name);
         goto err;
      }
   }

   /* Section 11.1.3.11 (Validation) of the OpenGL 4.5 spec says:
    *
    *    "An INVALID_OPERATION error is generated by any command that trans-
    *    fers vertices to the GL or launches compute work if the current set
    *    of active program objects cannot be executed, for reasons including:
    *
    *       ...
    *
    *       - There is no current program object specified by UseProgram,
    *         there is a current program pipeline object, and that object is
    *         empty (no executable code is installed for any stage).
    */
   for (i = 0; i < MESA_SHADER_STAGES; i++) {
      if (pipe->CurrentProgram[i]) {
         program_empty = false;
         break;
      }
   }

   if (program_empty) {
      goto err;
   }

   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
    * OpenGL 4.1 spec says:
    *
    *     "[INVALID_OPERATION] is generated by any command that transfers
    *     vertices to the GL if:
    *
    *         ...
    *
    *         - Any two active samplers in the current program object are of
    *           different types, but refer to the same texture image unit.
    *
    *         - The number of active samplers in the program exceeds the
    *           maximum number of texture image units allowed."
    */
   if (!_mesa_sampler_uniforms_pipeline_are_valid(pipe))
      goto err;

   /* 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))
      goto err;

   pipe->Validated = GL_TRUE;
   return GL_TRUE;

err:
   if (IsBound)
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glValidateProgramPipeline failed to validate the pipeline");

   return GL_FALSE;
}