These checks do not generate any errors. Move them so we can add KHR_no_error support and still make sure we do these checks.
Reviewed-by: Nicolai Hähnle <nicolai.haeh...@amd.com> --- src/mesa/main/api_validate.c | 43 +---------------- src/mesa/vbo/vbo_exec_array.c | 106 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 41 deletions(-) diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c index af4f7cb..843cdf6 100644 --- a/src/mesa/main/api_validate.c +++ b/src/mesa/main/api_validate.c @@ -283,68 +283,37 @@ check_valid_to_render(struct gl_context *ctx, const char *function) * transfers vertices to the GL if the current program state has * one but not both of a tessellation control shader and tessellation * evaluation shader." */ if (_mesa_is_gles3(ctx) && ctx->TessEvalProgram._Current && !ctx->TessCtrlProgram._Current) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(tess ctrl shader is missing)", function); return false; } - - /* For ES2, we can draw if we have a vertex program/shader). */ - return ctx->VertexProgram._Current != NULL; - - case API_OPENGLES: - /* For OpenGL ES, only draw if we have vertex positions - */ - if (!ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Enabled) - return false; break; case API_OPENGL_CORE: /* Section 10.4 (Drawing Commands Using Vertex Arrays) of the OpenGL 4.5 * Core Profile spec says: * * "An INVALID_OPERATION error is generated if no vertex array * object is bound (see section 10.3.1)." */ if (ctx->Array.VAO == ctx->Array.DefaultVAO) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no VAO bound)", function); return false; } + break; - /* Section 7.3 (Program Objects) of the OpenGL 4.5 Core Profile spec - * says: - * - * "If there is no active program for the vertex or fragment shader - * stages, the results of vertex and/or fragment processing will be - * undefined. However, this is not an error." - * - * The fragment shader is not tested here because other state (e.g., - * GL_RASTERIZER_DISCARD) affects whether or not we actually care. - */ - return ctx->VertexProgram._Current != NULL; - + case API_OPENGLES: case API_OPENGL_COMPAT: - if (ctx->VertexProgram._Current != NULL) { - /* Draw regardless of whether or not we have any vertex arrays. - * (Ex: could draw a point using a constant vertex pos) - */ - return true; - } else { - /* Draw if we have vertex positions (GL_VERTEX_ARRAY or generic - * array [0]). - */ - return (ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Enabled || - ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled); - } break; default: unreachable("Invalid API value in check_valid_to_render()"); } return true; } @@ -693,28 +662,20 @@ validate_DrawElements_common(struct gl_context *ctx, if (!_mesa_valid_prim_mode(ctx, mode, caller)) { return false; } if (!valid_elements_type(ctx, type, caller)) return false; if (!check_valid_to_render(ctx, caller)) return false; - /* Not using a VBO for indices, so avoid NULL pointer derefs later. - */ - if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj) && indices == NULL) - return false; - - if (count == 0) - return false; - return true; } /** * Error checking for glDrawElements(). Includes parameter checking * and VBO bounds checking. * \return GL_TRUE if OK to render, GL_FALSE if error found */ GLboolean _mesa_validate_DrawElements(struct gl_context *ctx, diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 30c52d5..9452c65 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -173,20 +173,74 @@ check_draw_elements_data(struct gl_context *ctx, GLsizei count, * Check array data, looking for NaNs, etc. */ static void check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count) { /* TO DO */ } /** + * Check if we should skip the draw call even after validation was successful. + */ +static bool +skip_validated_draw(struct gl_context *ctx) +{ + switch (ctx->API) { + case API_OPENGLES2: + /* For ES2, we can draw if we have a vertex program/shader). */ + return ctx->VertexProgram._Current == NULL; + + case API_OPENGLES: + /* For OpenGL ES, only draw if we have vertex positions + */ + if (ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Enabled) + return false; + break; + + case API_OPENGL_CORE: + /* Section 7.3 (Program Objects) of the OpenGL 4.5 Core Profile spec + * says: + * + * "If there is no active program for the vertex or fragment shader + * stages, the results of vertex and/or fragment processing will be + * undefined. However, this is not an error." + * + * The fragment shader is not tested here because other state (e.g., + * GL_RASTERIZER_DISCARD) affects whether or not we actually care. + */ + return ctx->VertexProgram._Current == NULL; + + case API_OPENGL_COMPAT: + if (ctx->VertexProgram._Current != NULL) { + /* Draw regardless of whether or not we have any vertex arrays. + * (Ex: could draw a point using a constant vertex pos) + */ + return false; + } else { + /* Draw if we have vertex positions (GL_VERTEX_ARRAY or generic + * array [0]). + */ + return (!ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Enabled && + !ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled); + } + break; + + default: + unreachable("Invalid API value in check_valid_to_render()"); + } + + return false; +} + + +/** * Print info/data for glDrawArrays(), for debugging. */ static void print_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, GLsizei count) { const struct gl_vertex_array_object *vao = ctx->Array.VAO; printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n", mode, start, count); @@ -402,20 +456,23 @@ vbo_bind_arrays(struct gl_context *ctx) * arrays. If primitive restart is enabled, it typically means * splitting one DrawArrays() into two. */ static void vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, GLsizei count, GLuint numInstances, GLuint baseInstance) { struct vbo_context *vbo = vbo_context(ctx); struct _mesa_prim prim[2]; + if (skip_validated_draw(ctx)) + return; + vbo_bind_arrays(ctx); /* OpenGL 4.5 says that primitive restart is ignored with non-indexed * draws. */ memset(prim, 0, sizeof(prim)); prim[0].begin = 1; prim[0].end = 1; prim[0].mode = mode; prim[0].num_instances = numInstances; @@ -691,38 +748,60 @@ dump_element_buffer(struct gl_context *ctx, GLenum type) break; default: ; } ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, MAP_INTERNAL); } #endif +static bool +skip_draw_elements(struct gl_context *ctx, GLsizei count, + const GLvoid *indices) +{ + if (count == 0) + return true; + + /* Not using a VBO for indices, so avoid NULL pointer derefs later. + */ + if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj) && indices == NULL) + return true; + + if (skip_validated_draw(ctx)) + return true; + + return false; +} + + /** * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements. * Do the rendering for a glDrawElements or glDrawRangeElements call after * we've validated buffer bounds, etc. */ static void vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, GLboolean index_bounds_valid, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices, GLint basevertex, GLuint numInstances, GLuint baseInstance) { struct vbo_context *vbo = vbo_context(ctx); struct _mesa_index_buffer ib; struct _mesa_prim prim[1]; + if (skip_draw_elements(ctx, count, indices)) + return; + vbo_bind_arrays(ctx); ib.count = count; ib.type = type; ib.obj = ctx->Array.VAO->IndexBufferObj; ib.ptr = indices; prim[0].begin = 1; prim[0].end = 1; prim[0].weak = 0; @@ -1182,38 +1261,44 @@ static void GLAPIENTRY vbo_exec_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount) { GET_CURRENT_CONTEXT(ctx); if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices, primcount)) return; + if (skip_validated_draw(ctx)) + return; + vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount, NULL); } static void GLAPIENTRY vbo_exec_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount, const GLsizei *basevertex) { GET_CURRENT_CONTEXT(ctx); if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices, primcount)) return; + if (skip_validated_draw(ctx)) + return; + vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount, basevertex); } static void vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode, struct gl_transform_feedback_object *obj, GLuint stream, GLuint numInstances) { @@ -1227,20 +1312,23 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode, if (ctx->Driver.GetTransformFeedbackVertexCount && (ctx->Const.AlwaysUseGetTransformFeedbackVertexCount || !_mesa_all_varyings_in_vbos(ctx->Array.VAO))) { GLsizei n = ctx->Driver.GetTransformFeedbackVertexCount(ctx, obj, stream); vbo_draw_arrays(ctx, mode, 0, n, numInstances, 0); return; } + if (skip_validated_draw(ctx)) + return; + vbo_bind_arrays(ctx); /* init most fields to zero */ memset(prim, 0, sizeof(prim)); prim[0].begin = 1; prim[0].end = 1; prim[0].mode = mode; prim[0].num_instances = numInstances; prim[0].base_instance = 0; prim[0].is_indirect = 0; @@ -1434,37 +1522,43 @@ vbo_exec_DrawArraysIndirect(GLenum mode, const GLvoid *indirect) { GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_DRAW) _mesa_debug(ctx, "glDrawArraysIndirect(%s, %p)\n", _mesa_enum_to_string(mode), indirect); if (!_mesa_validate_DrawArraysIndirect(ctx, mode, indirect)) return; + if (skip_validated_draw(ctx)) + return; + vbo_validated_drawarraysindirect(ctx, mode, indirect); } static void GLAPIENTRY vbo_exec_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) { GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_DRAW) _mesa_debug(ctx, "glDrawElementsIndirect(%s, %s, %p)\n", _mesa_enum_to_string(mode), _mesa_enum_to_string(type), indirect); if (!_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect)) return; + if (skip_validated_draw(ctx)) + return; + vbo_validated_drawelementsindirect(ctx, mode, type, indirect); } static void GLAPIENTRY vbo_exec_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect, GLsizei primcount, GLsizei stride) { GET_CURRENT_CONTEXT(ctx); @@ -1473,20 +1567,23 @@ vbo_exec_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect, _mesa_enum_to_string(mode), indirect, primcount, stride); /* If <stride> is zero, the array elements are treated as tightly packed. */ if (stride == 0) stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */ if (!_mesa_validate_MultiDrawArraysIndirect(ctx, mode, indirect, primcount, stride)) return; + if (skip_validated_draw(ctx)) + return; + vbo_validated_multidrawarraysindirect(ctx, mode, indirect, primcount, stride); } static void GLAPIENTRY vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect, GLsizei primcount, GLsizei stride) { @@ -1498,20 +1595,23 @@ vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type, _mesa_enum_to_string(type), indirect, primcount, stride); /* If <stride> is zero, the array elements are treated as tightly packed. */ if (stride == 0) stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */ if (!_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type, indirect, primcount, stride)) return; + if (skip_validated_draw(ctx)) + return; + vbo_validated_multidrawelementsindirect(ctx, mode, type, indirect, primcount, stride); } static void vbo_validated_multidrawarraysindirectcount(struct gl_context *ctx, GLenum mode, GLintptr indirect, GLintptr drawcount, @@ -1586,20 +1686,23 @@ vbo_exec_MultiDrawArraysIndirectCount(GLenum mode, GLintptr indirect, /* If <stride> is zero, the array elements are treated as tightly packed. */ if (stride == 0) stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */ if (!_mesa_validate_MultiDrawArraysIndirectCount(ctx, mode, indirect, drawcount, maxdrawcount, stride)) return; + if (skip_validated_draw(ctx)) + return; + vbo_validated_multidrawarraysindirectcount(ctx, mode, indirect, drawcount, maxdrawcount, stride); } static void GLAPIENTRY vbo_exec_MultiDrawElementsIndirectCount(GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride) { @@ -1614,20 +1717,23 @@ vbo_exec_MultiDrawElementsIndirectCount(GLenum mode, GLenum type, /* If <stride> is zero, the array elements are treated as tightly packed. */ if (stride == 0) stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */ if (!_mesa_validate_MultiDrawElementsIndirectCount(ctx, mode, type, indirect, drawcount, maxdrawcount, stride)) return; + if (skip_validated_draw(ctx)) + return; + vbo_validated_multidrawelementsindirectcount(ctx, mode, type, indirect, drawcount, maxdrawcount, stride); } /** * Initialize the dispatch table with the VBO functions for drawing. */ void -- 2.9.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev