mesa/glthread: add custom marshalling for ClearBufferfv()
authorTimothy Arceri <tarceri@itsqueeze.com>
Fri, 24 Mar 2017 06:46:20 +0000 (17:46 +1100)
committerTimothy Arceri <tarceri@itsqueeze.com>
Sat, 25 Mar 2017 02:39:12 +0000 (13:39 +1100)
This is one of the main causes of syncs in Civ6.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/mapi/glapi/gen/GL3x.xml
src/mesa/main/marshal.c
src/mesa/main/marshal.h

index b603e1f82f6743ee0c054975badfbfcf35e42bea..f38a2876dfeb9e27321cc2d766e0dbb1d0523da8 100644 (file)
     <param name="value" type="const GLuint *"/>
   </function>
 
-  <function name="ClearBufferfv" es2="3.0">
+  <function name="ClearBufferfv" es2="3.0" marshal="custom">
     <param name="buffer" type="GLenum"/>
     <param name="drawbuffer" type="GLint"/>
     <param name="value" type="const GLfloat *"/>
index cdc7fed8a5883c04eae2011f6c671b1674f5c3e3..03da140d8764f9f04bcb3435918436abbdcf2134 100644 (file)
@@ -27,6 +27,8 @@
  * thread when automatic code generation isn't appropriate.
  */
 
+#include "main/enums.h"
+#include "main/macros.h"
 #include "marshal.h"
 #include "dispatch.h"
 #include "marshal_generated.h"
@@ -384,4 +386,76 @@ _mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
    }
 }
 
+/* ClearBufferfv: marshalled asynchronously */
+struct marshal_cmd_ClearBufferfv
+{
+   struct marshal_cmd_base cmd_base;
+   GLenum buffer;
+   GLint drawbuffer;
+};
+
+void
+_mesa_unmarshal_ClearBufferfv(struct gl_context *ctx,
+                              const struct marshal_cmd_ClearBufferfv *cmd)
+{
+   const GLenum buffer = cmd->buffer;
+   const GLint drawbuffer = cmd->drawbuffer;
+   const char *variable_data = (const char *) (cmd + 1);
+   const GLfloat *value = (const GLfloat *) variable_data;
+
+   CALL_ClearBufferfv(ctx->CurrentServerDispatch,
+                      (buffer, drawbuffer, value));
+}
+
+void GLAPIENTRY
+_mesa_marshal_ClearBufferfv(GLenum buffer, GLint drawbuffer,
+                            const GLfloat *value)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   debug_print_marshal("ClearBufferfv");
+
+   size_t size;
+   switch (buffer) {
+   case GL_DEPTH:
+      size = sizeof(GLfloat);
+      break;
+   case GL_COLOR:
+      size = sizeof(GLfloat) * 4;
+      break;
+   default:
+      _mesa_glthread_finish(ctx);
+
+      /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
+       * of the OpenGL 4.5 spec states:
+       *
+       *    "An INVALID_ENUM error is generated by ClearBufferfv and
+       *     ClearNamedFramebufferfv if buffer is not COLOR or DEPTH."
+       */
+      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
+                  _mesa_enum_to_string(buffer));
+      return;
+   }
+
+   size_t cmd_size = sizeof(struct marshal_cmd_ClearBufferfv) + size;
+   if (cmd_size <= MARSHAL_MAX_CMD_SIZE) {
+      struct marshal_cmd_ClearBufferfv *cmd =
+         _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_ClearBufferfv,
+                                         cmd_size);
+      cmd->buffer = buffer;
+      cmd->drawbuffer = drawbuffer;
+      GLfloat *variable_data = (GLfloat *) (cmd + 1);
+      if (buffer == GL_COLOR)
+         COPY_4V(variable_data, value);
+      else
+         *variable_data = *value;
+
+      _mesa_post_marshal_hook(ctx);
+   } else {
+      debug_print_sync("ClearBufferfv");
+      _mesa_glthread_finish(ctx);
+      CALL_ClearBufferfv(ctx->CurrentServerDispatch,
+                         (buffer, drawbuffer, value));
+   }
+}
+
 #endif
index 4e9a6653b4ea47700af6fb39726439cbe64c57dc..52339aa1db2e0986ff0416e0f7c5e77b1bbdbf98 100644 (file)
@@ -189,6 +189,7 @@ struct marshal_cmd_Flush;
 struct marshal_cmd_BindBuffer;
 struct marshal_cmd_BufferData;
 struct marshal_cmd_BufferSubData;
+struct marshal_cmd_ClearBufferfv;
 
 void GLAPIENTRY
 _mesa_marshal_ShaderSource(GLuint shader, GLsizei count,
@@ -228,4 +229,12 @@ void GLAPIENTRY
 _mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
                             const GLvoid * data);
 
+void
+_mesa_unmarshal_ClearBufferfv(struct gl_context *ctx,
+                              const struct marshal_cmd_ClearBufferfv *cmd);
+
+void GLAPIENTRY
+_mesa_marshal_ClearBufferfv(GLenum buffer, GLint drawbuffer,
+                            const GLfloat *value);
+
 #endif /* MARSHAL_H */