[Mesa-dev] [PATCH V3 05/13] mesa: Add validation helpers for new indirect draws
Chris Forbes
chrisf at ijw.co.nz
Tue Nov 19 11:36:00 PST 2013
OK, I'll go back to allowing zero. It's silly but harmless.
On Wed, Nov 20, 2013 at 8:29 AM, Ian Romanick <idr at freedesktop.org> wrote:
> On 11/09/2013 01:02 AM, Chris Forbes wrote:
>> 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;
>
> We can drop this check. We'll never get ctx->API == API_OPENGL_COMPAT
> because we won't even install the dispatch pointers.
>
>> + }
>> + }
>> +
>> + 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
>>
>
More information about the mesa-dev
mailing list