[Mesa-dev] [PATCH V3 05/13] mesa: Add validation helpers for new indirect draws
Chris Forbes
chrisf at ijw.co.nz
Sat Nov 9 01:02:31 PST 2013
Based on part of Patch 2 of Christoph Bumiller's ARB_draw_indirect series.
V3: - Disallow primcount==0 for DrawMulti*Indirect. The extension spec
contradicts itself on this, but the GL4.3 spec disallows it.
- Make it clear that the caller has dealt with stride==0
Signed-off-by: Chris Forbes <chrisf at ijw.co.nz>
Reviewed-by: Paul Berry <stereotype441 at gmail.com>
---
src/mesa/main/api_validate.c | 167 +++++++++++++++++++++++++++++++++++++++++++
src/mesa/main/api_validate.h | 26 +++++++
2 files changed, 193 insertions(+)
diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
index f285c97..f462b68 100644
--- a/src/mesa/main/api_validate.c
+++ b/src/mesa/main/api_validate.c
@@ -837,3 +837,170 @@ _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
return GL_TRUE;
}
+
+static GLboolean
+valid_draw_indirect(struct gl_context *ctx,
+ GLenum mode, const GLvoid *indirect,
+ GLsizei size, const char *name)
+{
+ const GLsizeiptr end = (GLsizeiptr)indirect + size;
+
+ if (!_mesa_valid_prim_mode(ctx, mode, name))
+ return GL_FALSE;
+
+ if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(indirect is not aligned)", name);
+ return GL_FALSE;
+ }
+
+ if (_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
+ if (_mesa_bufferobj_mapped(ctx->DrawIndirectBuffer)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(DRAW_INDIRECT_BUFFER is mapped)", name);
+ return GL_FALSE;
+ }
+ if (ctx->DrawIndirectBuffer->Size < end) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(DRAW_INDIRECT_BUFFER too small)", name);
+ return GL_FALSE;
+ }
+ } else {
+ if (ctx->API != API_OPENGL_COMPAT) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s: no buffer bound to DRAW_INDIRECT_BUFFER", name);
+ return GL_FALSE;
+ }
+ }
+
+ if (!check_valid_to_render(ctx, name))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+static inline GLboolean
+valid_draw_indirect_elements(struct gl_context *ctx,
+ GLenum mode, GLenum type, const GLvoid *indirect,
+ GLsizeiptr size, const char *name)
+{
+ if (!valid_elements_type(ctx, type, name))
+ return GL_FALSE;
+
+ /*
+ * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
+ * may not come from a client array and must come from an index buffer.
+ * If no element array buffer is bound, an INVALID_OPERATION error is
+ * generated.
+ */
+ if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(no buffer bound to GL_ELEMENT_ARRAY_BUFFER)", name);
+ return GL_FALSE;
+ }
+
+ return valid_draw_indirect(ctx, mode, indirect, size, name);
+}
+
+static inline GLboolean
+valid_draw_indirect_multi(struct gl_context *ctx,
+ GLsizei primcount, GLsizei stride,
+ const char *name)
+{
+ if (primcount <= 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount <= 0)", name);
+ return GL_FALSE;
+ }
+
+ if (stride % 4) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
+ GLenum mode,
+ const GLvoid *indirect)
+{
+ const unsigned drawArraysNumParams = 4;
+
+ FLUSH_CURRENT(ctx, 0);
+
+ return valid_draw_indirect(ctx, mode,
+ indirect, drawArraysNumParams * sizeof(GLuint),
+ "glDrawArraysIndirect");
+}
+
+GLboolean
+_mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
+ GLenum mode, GLenum type,
+ const GLvoid *indirect)
+{
+ const unsigned drawElementsNumParams = 5;
+
+ FLUSH_CURRENT(ctx, 0);
+
+ return valid_draw_indirect_elements(ctx, mode, type,
+ indirect, drawElementsNumParams * sizeof(GLuint),
+ "glDrawElementsIndirect");
+}
+
+GLboolean
+_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
+ GLenum mode,
+ const GLvoid *indirect,
+ GLsizei primcount, GLsizei stride)
+{
+ GLsizeiptr size = 0;
+ const unsigned drawArraysNumParams = 4;
+
+ FLUSH_CURRENT(ctx, 0);
+
+ /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
+ assert(stride != 0);
+
+ if (!valid_draw_indirect_multi(ctx, primcount, stride,
+ "glMultiDrawArraysIndirect"))
+ return GL_FALSE;
+
+ /* number of bytes of the indirect buffer which will be read */
+ size = (primcount - 1) * stride + drawArraysNumParams * sizeof(GLuint);
+
+ if (!valid_draw_indirect(ctx, mode, indirect, size,
+ "glMultiDrawArraysIndirect"))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
+ GLenum mode, GLenum type,
+ const GLvoid *indirect,
+ GLsizei primcount, GLsizei stride)
+{
+ GLsizeiptr size = 0;
+ const unsigned drawElementsNumParams = 5;
+
+ FLUSH_CURRENT(ctx, 0);
+
+ /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
+ assert(stride != 0);
+
+ if (!valid_draw_indirect_multi(ctx, primcount, stride,
+ "glMultiDrawElementsIndirect"))
+ return GL_FALSE;
+
+ /* number of bytes of the indirect buffer which will be read */
+ size = (primcount - 1) * stride + drawElementsNumParams * sizeof(GLuint);
+
+ if (!valid_draw_indirect_elements(ctx, mode, type,
+ indirect, size,
+ "glMultiDrawElementsIndirect"))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h
index f2b753c..8238df1 100644
--- a/src/mesa/main/api_validate.h
+++ b/src/mesa/main/api_validate.h
@@ -87,5 +87,31 @@ _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
GLuint stream,
GLsizei numInstances);
+extern GLboolean
+_mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
+ GLenum mode,
+ const GLvoid *indirect);
+
+extern GLboolean
+_mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
+ GLenum mode,
+ GLenum type,
+ const GLvoid *indirect);
+
+extern GLboolean
+_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
+ GLenum mode,
+ const GLvoid *indirect,
+ GLsizei primcount,
+ GLsizei stride);
+
+extern GLboolean
+_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
+ GLenum mode,
+ GLenum type,
+ const GLvoid *indirect,
+ GLsizei primcount,
+ GLsizei stride);
+
#endif
--
1.8.4.2
More information about the mesa-dev
mailing list