Re: [Mesa-dev] [PATCH 7/7] mesa: add KHR_no_error support for glUseProgram

2017-05-07 Thread Timothy Arceri

On 08/05/17 06:29, Nicolai Hähnle wrote:

On 04.05.2017 16:28, Nicolai Hähnle wrote:

On 04.05.2017 05:34, Timothy Arceri wrote:



On 04/05/17 13:31, Dave Airlie wrote:

+/* The ARB_separate_shader_object spec says:
+ *
+ * "The executable code for an individual shader stage is taken
from
+ * the current program for that stage.  If there is a current
program
+ * object established by UseProgram, that program is considered
current
+ * for all stages.  Otherwise, if there is a bound program
pipeline
+ * object (section 2.14.PPO), the program bound to the 
appropriate

+ * stage of the pipeline object is considered current."
+ */
+#define
USE_PROGRAM(no_error)\
+   if (program)
{\
+  /* Attach shader state to the binding point
*/ \
+  _mesa_reference_pipeline_object(ctx, >_Shader,
>Shader); \
+  /* Update the program
*/   \
+  _mesa_use_shader_program(ctx,
shProg); \
+   } else
{  \
+  /* Must be done first: detach the progam
*/\
+  _mesa_use_shader_program(ctx,
shProg); \
+  /* Unattach shader_state binding point
*/  \
+  _mesa_reference_pipeline_object(ctx,
>_Shader,\
+
ctx->Pipeline.Default);\
+  /* If a pipeline was bound, rebind it
*/   \
+  if (ctx->Pipeline.Current)
{   \
+
_mesa_BindProgramPipeline##no_error(ctx->Pipeline.Current->Name);   \
+
}
\
+
}
\
+


why the macro, inline functions are a thing, or just one common
function that both entrypoints call.



So that we can avoid adding an if to call

_mesa_BindProgramPipeline_no_error vs _mesa_BindProgramPipeline


I have to say I also don't like this very much. Do you have benchmarks
to back up the usefulness of this?

This is where C++ templates would be great, because there could just be
a boolean no_error template parameter. Maybe there's a way to get
somewhere similar in C, even if it requires some compiler extensions?


I thought about this some more, and I feel that at least with gcc/clang, 
the always_inline attributes provides a reasonably elegant solution. I 
mean this code pattern:


__attribute((always_inline))
static inline void useprogram(GLuint program, bool check_error)
{
   GET_CURRENT_CTX(ctx);

   ...
}

void GLAPIENTRY
_mesa_UseProgram(GLuint program)
{
   useprogram(program, true);
}

void GLAPIENTRY
_mesa_UseProgram_no_error(GLuint program)
{
   useprogram(program, false);
}

This would avoid the code duplication and macro magic that I'm finding a 
bit worrisome while still getting fully optimized code in both paths. 
This could also be used to clean up some of the other _no_error variants. >
There's a bit of a question of other compiler support. At least judging 
from the online docs, MSVC's __forceinline should have the same effect, 
so it looks like all the relevant bases are covered.


What do you think?


I'm happy with this solution, thanks. I'll send out a new version for 
review.




Cheers,
Nicolai






Cheers,
Nicolai





Dave.


+void GLAPIENTRY
+_mesa_UseProgram_no_error(GLuint program)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg = NULL;
+
+   if (program) {
+  shProg = _mesa_lookup_shader_program(ctx, program);
+   }
+
+   USE_PROGRAM(_no_error)
+}
+

  void GLAPIENTRY
  _mesa_UseProgram(GLuint program)
  {
 GET_CURRENT_CONTEXT(ctx);
 struct gl_shader_program *shProg = NULL;

 if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glUseProgram %u\n", program);

@@ -1875,44 +1915,21 @@ _mesa_UseProgram(GLuint program)
   return;
}

  #ifdef DEBUG
if (ctx->_Shader->Flags & GLSL_USE_PROG) {
   print_shader_info(shProg);
}
  #endif
 }

-   /* The ARB_separate_shader_object spec says:
-*
-* "The executable code for an individual shader stage is
taken from
-* the current program for that stage.  If there is a current
program
-* object established by UseProgram, that program is
considered current
-* for all stages.  Otherwise, if there is a bound program
pipeline
-* object (section 2.14.PPO), the program bound to the
appropriate
-* stage of the pipeline object is considered current."
-*/
-   if (program) {
-  /* Attach shader state to the binding point */
-  _mesa_reference_pipeline_object(ctx, >_Shader,
>Shader);
-  /* Update the program */
-  _mesa_use_shader_program(ctx, shProg);
-   } else {
-  /* Must be done first: detach the progam */
-  

Re: [Mesa-dev] [PATCH 7/7] mesa: add KHR_no_error support for glUseProgram

2017-05-07 Thread Nicolai Hähnle

On 04.05.2017 16:28, Nicolai Hähnle wrote:

On 04.05.2017 05:34, Timothy Arceri wrote:



On 04/05/17 13:31, Dave Airlie wrote:

+/* The ARB_separate_shader_object spec says:
+ *
+ * "The executable code for an individual shader stage is taken
from
+ * the current program for that stage.  If there is a current
program
+ * object established by UseProgram, that program is considered
current
+ * for all stages.  Otherwise, if there is a bound program
pipeline
+ * object (section 2.14.PPO), the program bound to the appropriate
+ * stage of the pipeline object is considered current."
+ */
+#define
USE_PROGRAM(no_error)\
+   if (program)
{\
+  /* Attach shader state to the binding point
*/ \
+  _mesa_reference_pipeline_object(ctx, >_Shader,
>Shader); \
+  /* Update the program
*/   \
+  _mesa_use_shader_program(ctx,
shProg); \
+   } else
{  \
+  /* Must be done first: detach the progam
*/\
+  _mesa_use_shader_program(ctx,
shProg); \
+  /* Unattach shader_state binding point
*/  \
+  _mesa_reference_pipeline_object(ctx,
>_Shader,\
+
ctx->Pipeline.Default);\
+  /* If a pipeline was bound, rebind it
*/   \
+  if (ctx->Pipeline.Current)
{   \
+
_mesa_BindProgramPipeline##no_error(ctx->Pipeline.Current->Name);   \
+
}
\
+
}
\
+


why the macro, inline functions are a thing, or just one common
function that both entrypoints call.



So that we can avoid adding an if to call

_mesa_BindProgramPipeline_no_error vs _mesa_BindProgramPipeline


I have to say I also don't like this very much. Do you have benchmarks
to back up the usefulness of this?

This is where C++ templates would be great, because there could just be
a boolean no_error template parameter. Maybe there's a way to get
somewhere similar in C, even if it requires some compiler extensions?


I thought about this some more, and I feel that at least with gcc/clang, 
the always_inline attributes provides a reasonably elegant solution. I 
mean this code pattern:


   __attribute((always_inline))
   static inline void useprogram(GLuint program, bool check_error)
   {
  GET_CURRENT_CTX(ctx);

  ...
   }

   void GLAPIENTRY
   _mesa_UseProgram(GLuint program)
   {
  useprogram(program, true);
   }

   void GLAPIENTRY
   _mesa_UseProgram_no_error(GLuint program)
   {
  useprogram(program, false);
   }

This would avoid the code duplication and macro magic that I'm finding a 
bit worrisome while still getting fully optimized code in both paths. 
This could also be used to clean up some of the other _no_error variants.


There's a bit of a question of other compiler support. At least judging 
from the online docs, MSVC's __forceinline should have the same effect, 
so it looks like all the relevant bases are covered.


What do you think?

Cheers,
Nicolai






Cheers,
Nicolai





Dave.


+void GLAPIENTRY
+_mesa_UseProgram_no_error(GLuint program)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg = NULL;
+
+   if (program) {
+  shProg = _mesa_lookup_shader_program(ctx, program);
+   }
+
+   USE_PROGRAM(_no_error)
+}
+

  void GLAPIENTRY
  _mesa_UseProgram(GLuint program)
  {
 GET_CURRENT_CONTEXT(ctx);
 struct gl_shader_program *shProg = NULL;

 if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glUseProgram %u\n", program);

@@ -1875,44 +1915,21 @@ _mesa_UseProgram(GLuint program)
   return;
}

  #ifdef DEBUG
if (ctx->_Shader->Flags & GLSL_USE_PROG) {
   print_shader_info(shProg);
}
  #endif
 }

-   /* The ARB_separate_shader_object spec says:
-*
-* "The executable code for an individual shader stage is
taken from
-* the current program for that stage.  If there is a current
program
-* object established by UseProgram, that program is
considered current
-* for all stages.  Otherwise, if there is a bound program
pipeline
-* object (section 2.14.PPO), the program bound to the
appropriate
-* stage of the pipeline object is considered current."
-*/
-   if (program) {
-  /* Attach shader state to the binding point */
-  _mesa_reference_pipeline_object(ctx, >_Shader,
>Shader);
-  /* Update the program */
-  _mesa_use_shader_program(ctx, shProg);
-   } else {
-  /* Must be done first: detach the progam */
-  _mesa_use_shader_program(ctx, shProg);
-  /* Unattach shader_state binding point */
-  _mesa_reference_pipeline_object(ctx, >_Shader,
ctx->Pipeline.Default);
- 

Re: [Mesa-dev] [PATCH 7/7] mesa: add KHR_no_error support for glUseProgram

2017-05-04 Thread Nicolai Hähnle

On 04.05.2017 05:34, Timothy Arceri wrote:



On 04/05/17 13:31, Dave Airlie wrote:

+/* The ARB_separate_shader_object spec says:
+ *
+ * "The executable code for an individual shader stage is taken
from
+ * the current program for that stage.  If there is a current
program
+ * object established by UseProgram, that program is considered
current
+ * for all stages.  Otherwise, if there is a bound program pipeline
+ * object (section 2.14.PPO), the program bound to the appropriate
+ * stage of the pipeline object is considered current."
+ */
+#define
USE_PROGRAM(no_error)\
+   if (program)
{\
+  /* Attach shader state to the binding point
*/ \
+  _mesa_reference_pipeline_object(ctx, >_Shader,
>Shader); \
+  /* Update the program
*/   \
+  _mesa_use_shader_program(ctx,
shProg); \
+   } else
{  \
+  /* Must be done first: detach the progam
*/\
+  _mesa_use_shader_program(ctx,
shProg); \
+  /* Unattach shader_state binding point
*/  \
+  _mesa_reference_pipeline_object(ctx,
>_Shader,\
+
ctx->Pipeline.Default);\
+  /* If a pipeline was bound, rebind it
*/   \
+  if (ctx->Pipeline.Current)
{   \
+
_mesa_BindProgramPipeline##no_error(ctx->Pipeline.Current->Name);   \
+
}  \
+
}
\
+


why the macro, inline functions are a thing, or just one common
function that both entrypoints call.



So that we can avoid adding an if to call

_mesa_BindProgramPipeline_no_error vs _mesa_BindProgramPipeline


I have to say I also don't like this very much. Do you have benchmarks 
to back up the usefulness of this?


This is where C++ templates would be great, because there could just be 
a boolean no_error template parameter. Maybe there's a way to get 
somewhere similar in C, even if it requires some compiler extensions?


Cheers,
Nicolai





Dave.


+void GLAPIENTRY
+_mesa_UseProgram_no_error(GLuint program)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg = NULL;
+
+   if (program) {
+  shProg = _mesa_lookup_shader_program(ctx, program);
+   }
+
+   USE_PROGRAM(_no_error)
+}
+

  void GLAPIENTRY
  _mesa_UseProgram(GLuint program)
  {
 GET_CURRENT_CONTEXT(ctx);
 struct gl_shader_program *shProg = NULL;

 if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glUseProgram %u\n", program);

@@ -1875,44 +1915,21 @@ _mesa_UseProgram(GLuint program)
   return;
}

  #ifdef DEBUG
if (ctx->_Shader->Flags & GLSL_USE_PROG) {
   print_shader_info(shProg);
}
  #endif
 }

-   /* The ARB_separate_shader_object spec says:
-*
-* "The executable code for an individual shader stage is
taken from
-* the current program for that stage.  If there is a current
program
-* object established by UseProgram, that program is
considered current
-* for all stages.  Otherwise, if there is a bound program
pipeline
-* object (section 2.14.PPO), the program bound to the
appropriate
-* stage of the pipeline object is considered current."
-*/
-   if (program) {
-  /* Attach shader state to the binding point */
-  _mesa_reference_pipeline_object(ctx, >_Shader,
>Shader);
-  /* Update the program */
-  _mesa_use_shader_program(ctx, shProg);
-   } else {
-  /* Must be done first: detach the progam */
-  _mesa_use_shader_program(ctx, shProg);
-  /* Unattach shader_state binding point */
-  _mesa_reference_pipeline_object(ctx, >_Shader,
ctx->Pipeline.Default);
-  /* If a pipeline was bound, rebind it */
-  if (ctx->Pipeline.Current) {
- _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name);
-  }
-   }
+   USE_PROGRAM()
  }


  void GLAPIENTRY
  _mesa_ValidateProgram(GLuint program)
  {
 GET_CURRENT_CONTEXT(ctx);
 validate_program(ctx, program);
  }

diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h
index 99b4fe8..0a28185 100644
--- a/src/mesa/main/shaderapi.h
+++ b/src/mesa/main/shaderapi.h
@@ -120,20 +120,22 @@ _mesa_IsProgram(GLuint name);

  extern GLboolean GLAPIENTRY
  _mesa_IsShader(GLuint name);

  extern void GLAPIENTRY
  _mesa_LinkProgram(GLuint programObj);

  extern void GLAPIENTRY
  _mesa_ShaderSource(GLuint, GLsizei, const GLchar* const *, const
GLint *);

+void GLAPIENTRY
+_mesa_UseProgram_no_error(GLuint);
  extern void GLAPIENTRY
  _mesa_UseProgram(GLuint);

  extern void GLAPIENTRY
  _mesa_ValidateProgram(GLuint);


  extern void GLAPIENTRY
  

Re: [Mesa-dev] [PATCH 7/7] mesa: add KHR_no_error support for glUseProgram

2017-05-03 Thread Timothy Arceri



On 04/05/17 13:31, Dave Airlie wrote:

+/* The ARB_separate_shader_object spec says:
+ *
+ * "The executable code for an individual shader stage is taken from
+ * the current program for that stage.  If there is a current program
+ * object established by UseProgram, that program is considered current
+ * for all stages.  Otherwise, if there is a bound program pipeline
+ * object (section 2.14.PPO), the program bound to the appropriate
+ * stage of the pipeline object is considered current."
+ */
+#define USE_PROGRAM(no_error)\
+   if (program) {\
+  /* Attach shader state to the binding point */ \
+  _mesa_reference_pipeline_object(ctx, >_Shader, >Shader); \
+  /* Update the program */   \
+  _mesa_use_shader_program(ctx, shProg); \
+   } else {  \
+  /* Must be done first: detach the progam */\
+  _mesa_use_shader_program(ctx, shProg); \
+  /* Unattach shader_state binding point */  \
+  _mesa_reference_pipeline_object(ctx, >_Shader,\
+  ctx->Pipeline.Default);\
+  /* If a pipeline was bound, rebind it */   \
+  if (ctx->Pipeline.Current) {   \
+ _mesa_BindProgramPipeline##no_error(ctx->Pipeline.Current->Name);   \
+  }  \
+   } \
+


why the macro, inline functions are a thing, or just one common
function that both entrypoints call.



So that we can avoid adding an if to call

_mesa_BindProgramPipeline_no_error vs _mesa_BindProgramPipeline


Dave.


+void GLAPIENTRY
+_mesa_UseProgram_no_error(GLuint program)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg = NULL;
+
+   if (program) {
+  shProg = _mesa_lookup_shader_program(ctx, program);
+   }
+
+   USE_PROGRAM(_no_error)
+}
+

  void GLAPIENTRY
  _mesa_UseProgram(GLuint program)
  {
 GET_CURRENT_CONTEXT(ctx);
 struct gl_shader_program *shProg = NULL;

 if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glUseProgram %u\n", program);

@@ -1875,44 +1915,21 @@ _mesa_UseProgram(GLuint program)
   return;
}

  #ifdef DEBUG
if (ctx->_Shader->Flags & GLSL_USE_PROG) {
   print_shader_info(shProg);
}
  #endif
 }

-   /* The ARB_separate_shader_object spec says:
-*
-* "The executable code for an individual shader stage is taken from
-* the current program for that stage.  If there is a current program
-* object established by UseProgram, that program is considered current
-* for all stages.  Otherwise, if there is a bound program pipeline
-* object (section 2.14.PPO), the program bound to the appropriate
-* stage of the pipeline object is considered current."
-*/
-   if (program) {
-  /* Attach shader state to the binding point */
-  _mesa_reference_pipeline_object(ctx, >_Shader, >Shader);
-  /* Update the program */
-  _mesa_use_shader_program(ctx, shProg);
-   } else {
-  /* Must be done first: detach the progam */
-  _mesa_use_shader_program(ctx, shProg);
-  /* Unattach shader_state binding point */
-  _mesa_reference_pipeline_object(ctx, >_Shader, 
ctx->Pipeline.Default);
-  /* If a pipeline was bound, rebind it */
-  if (ctx->Pipeline.Current) {
- _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name);
-  }
-   }
+   USE_PROGRAM()
  }


  void GLAPIENTRY
  _mesa_ValidateProgram(GLuint program)
  {
 GET_CURRENT_CONTEXT(ctx);
 validate_program(ctx, program);
  }

diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h
index 99b4fe8..0a28185 100644
--- a/src/mesa/main/shaderapi.h
+++ b/src/mesa/main/shaderapi.h
@@ -120,20 +120,22 @@ _mesa_IsProgram(GLuint name);

  extern GLboolean GLAPIENTRY
  _mesa_IsShader(GLuint name);

  extern void GLAPIENTRY
  _mesa_LinkProgram(GLuint programObj);

  extern void GLAPIENTRY
  _mesa_ShaderSource(GLuint, GLsizei, const GLchar* const *, const GLint *);

+void GLAPIENTRY
+_mesa_UseProgram_no_error(GLuint);
  extern void GLAPIENTRY
  _mesa_UseProgram(GLuint);

  extern void GLAPIENTRY
  _mesa_ValidateProgram(GLuint);


  extern void GLAPIENTRY
  _mesa_BindAttribLocation(GLuint program, GLuint, const GLchar *);

--
2.9.3

___
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev


Re: [Mesa-dev] [PATCH 7/7] mesa: add KHR_no_error support for glUseProgram

2017-05-03 Thread Dave Airlie
> +/* The ARB_separate_shader_object spec says:
> + *
> + * "The executable code for an individual shader stage is taken from
> + * the current program for that stage.  If there is a current program
> + * object established by UseProgram, that program is considered current
> + * for all stages.  Otherwise, if there is a bound program pipeline
> + * object (section 2.14.PPO), the program bound to the appropriate
> + * stage of the pipeline object is considered current."
> + */
> +#define USE_PROGRAM(no_error)
> \
> +   if (program) {
> \
> +  /* Attach shader state to the binding point */ 
> \
> +  _mesa_reference_pipeline_object(ctx, >_Shader, >Shader); 
> \
> +  /* Update the program */   
> \
> +  _mesa_use_shader_program(ctx, shProg); 
> \
> +   } else {  
> \
> +  /* Must be done first: detach the progam */
> \
> +  _mesa_use_shader_program(ctx, shProg); 
> \
> +  /* Unattach shader_state binding point */  
> \
> +  _mesa_reference_pipeline_object(ctx, >_Shader,
> \
> +  ctx->Pipeline.Default);
> \
> +  /* If a pipeline was bound, rebind it */   
> \
> +  if (ctx->Pipeline.Current) {   
> \
> + _mesa_BindProgramPipeline##no_error(ctx->Pipeline.Current->Name);   
> \
> +  }  
> \
> +   } 
> \
> +

why the macro, inline functions are a thing, or just one common
function that both entrypoints call.

Dave.

> +void GLAPIENTRY
> +_mesa_UseProgram_no_error(GLuint program)
> +{
> +   GET_CURRENT_CONTEXT(ctx);
> +   struct gl_shader_program *shProg = NULL;
> +
> +   if (program) {
> +  shProg = _mesa_lookup_shader_program(ctx, program);
> +   }
> +
> +   USE_PROGRAM(_no_error)
> +}
> +
>
>  void GLAPIENTRY
>  _mesa_UseProgram(GLuint program)
>  {
> GET_CURRENT_CONTEXT(ctx);
> struct gl_shader_program *shProg = NULL;
>
> if (MESA_VERBOSE & VERBOSE_API)
>_mesa_debug(ctx, "glUseProgram %u\n", program);
>
> @@ -1875,44 +1915,21 @@ _mesa_UseProgram(GLuint program)
>   return;
>}
>
>  #ifdef DEBUG
>if (ctx->_Shader->Flags & GLSL_USE_PROG) {
>   print_shader_info(shProg);
>}
>  #endif
> }
>
> -   /* The ARB_separate_shader_object spec says:
> -*
> -* "The executable code for an individual shader stage is taken from
> -* the current program for that stage.  If there is a current program
> -* object established by UseProgram, that program is considered 
> current
> -* for all stages.  Otherwise, if there is a bound program pipeline
> -* object (section 2.14.PPO), the program bound to the appropriate
> -* stage of the pipeline object is considered current."
> -*/
> -   if (program) {
> -  /* Attach shader state to the binding point */
> -  _mesa_reference_pipeline_object(ctx, >_Shader, >Shader);
> -  /* Update the program */
> -  _mesa_use_shader_program(ctx, shProg);
> -   } else {
> -  /* Must be done first: detach the progam */
> -  _mesa_use_shader_program(ctx, shProg);
> -  /* Unattach shader_state binding point */
> -  _mesa_reference_pipeline_object(ctx, >_Shader, 
> ctx->Pipeline.Default);
> -  /* If a pipeline was bound, rebind it */
> -  if (ctx->Pipeline.Current) {
> - _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name);
> -  }
> -   }
> +   USE_PROGRAM()
>  }
>
>
>  void GLAPIENTRY
>  _mesa_ValidateProgram(GLuint program)
>  {
> GET_CURRENT_CONTEXT(ctx);
> validate_program(ctx, program);
>  }
>
> diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h
> index 99b4fe8..0a28185 100644
> --- a/src/mesa/main/shaderapi.h
> +++ b/src/mesa/main/shaderapi.h
> @@ -120,20 +120,22 @@ _mesa_IsProgram(GLuint name);
>
>  extern GLboolean GLAPIENTRY
>  _mesa_IsShader(GLuint name);
>
>  extern void GLAPIENTRY
>  _mesa_LinkProgram(GLuint programObj);
>
>  extern void GLAPIENTRY
>  _mesa_ShaderSource(GLuint, GLsizei, const GLchar* const *, const GLint *);
>
> +void GLAPIENTRY
> +_mesa_UseProgram_no_error(GLuint);
>  extern void GLAPIENTRY
>  _mesa_UseProgram(GLuint);
>
>  extern void GLAPIENTRY
>  _mesa_ValidateProgram(GLuint);
>
>
>  extern void GLAPIENTRY
>  _mesa_BindAttribLocation(GLuint program, GLuint, const GLchar *);
>
> --
> 2.9.3
>
> ___
> mesa-dev mailing list
> 

[Mesa-dev] [PATCH 7/7] mesa: add KHR_no_error support for glUseProgram

2017-05-03 Thread Timothy Arceri
---
 src/mapi/glapi/gen/gl_API.xml |  2 +-
 src/mesa/main/shaderapi.c | 65 +++
 src/mesa/main/shaderapi.h |  2 ++
 3 files changed, 44 insertions(+), 25 deletions(-)

diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index 83f4c01..c271887 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -5493,21 +5493,21 @@
 
 
 
 
 
 
 
 
 
 
-
+
 
 
 
 
 
 
 
 
 
 
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index eb75a3e..0a73d40 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -1841,20 +1841,60 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count,
   free(source);
   source = replacement;
}
 #endif /* ENABLE_SHADER_CACHE */
 
shader_source(sh, source);
 
free(offsets);
 }
 
+/* The ARB_separate_shader_object spec says:
+ *
+ * "The executable code for an individual shader stage is taken from
+ * the current program for that stage.  If there is a current program
+ * object established by UseProgram, that program is considered current
+ * for all stages.  Otherwise, if there is a bound program pipeline
+ * object (section 2.14.PPO), the program bound to the appropriate
+ * stage of the pipeline object is considered current."
+ */
+#define USE_PROGRAM(no_error)\
+   if (program) {\
+  /* Attach shader state to the binding point */ \
+  _mesa_reference_pipeline_object(ctx, >_Shader, >Shader); \
+  /* Update the program */   \
+  _mesa_use_shader_program(ctx, shProg); \
+   } else {  \
+  /* Must be done first: detach the progam */\
+  _mesa_use_shader_program(ctx, shProg); \
+  /* Unattach shader_state binding point */  \
+  _mesa_reference_pipeline_object(ctx, >_Shader,\
+  ctx->Pipeline.Default);\
+  /* If a pipeline was bound, rebind it */   \
+  if (ctx->Pipeline.Current) {   \
+ _mesa_BindProgramPipeline##no_error(ctx->Pipeline.Current->Name);   \
+  }  \
+   } \
+
+void GLAPIENTRY
+_mesa_UseProgram_no_error(GLuint program)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg = NULL;
+
+   if (program) {
+  shProg = _mesa_lookup_shader_program(ctx, program);
+   }
+
+   USE_PROGRAM(_no_error)
+}
+
 
 void GLAPIENTRY
 _mesa_UseProgram(GLuint program)
 {
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg = NULL;
 
if (MESA_VERBOSE & VERBOSE_API)
   _mesa_debug(ctx, "glUseProgram %u\n", program);
 
@@ -1875,44 +1915,21 @@ _mesa_UseProgram(GLuint program)
  return;
   }
 
 #ifdef DEBUG
   if (ctx->_Shader->Flags & GLSL_USE_PROG) {
  print_shader_info(shProg);
   }
 #endif
}
 
-   /* The ARB_separate_shader_object spec says:
-*
-* "The executable code for an individual shader stage is taken from
-* the current program for that stage.  If there is a current program
-* object established by UseProgram, that program is considered current
-* for all stages.  Otherwise, if there is a bound program pipeline
-* object (section 2.14.PPO), the program bound to the appropriate
-* stage of the pipeline object is considered current."
-*/
-   if (program) {
-  /* Attach shader state to the binding point */
-  _mesa_reference_pipeline_object(ctx, >_Shader, >Shader);
-  /* Update the program */
-  _mesa_use_shader_program(ctx, shProg);
-   } else {
-  /* Must be done first: detach the progam */
-  _mesa_use_shader_program(ctx, shProg);
-  /* Unattach shader_state binding point */
-  _mesa_reference_pipeline_object(ctx, >_Shader, 
ctx->Pipeline.Default);
-  /* If a pipeline was bound, rebind it */
-  if (ctx->Pipeline.Current) {
- _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name);
-  }
-   }
+   USE_PROGRAM()
 }
 
 
 void GLAPIENTRY
 _mesa_ValidateProgram(GLuint program)
 {
GET_CURRENT_CONTEXT(ctx);
validate_program(ctx, program);
 }
 
diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h
index 99b4fe8..0a28185 100644
--- a/src/mesa/main/shaderapi.h
+++ b/src/mesa/main/shaderapi.h
@@ -120,20 +120,22 @@ _mesa_IsProgram(GLuint name);