From 64757e73de4355353e15706d9d25269f181eb775 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Mon, 15 May 2017 11:08:13 +1000 Subject: [PATCH] mesa: move DispatchCompute() validation to compute.c MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This is the only place it is used so there is no reason for it to be in api_validate.c Reviewed-by: Nicolai Hähnle --- src/mesa/main/api_validate.c | 234 ----------------------------------- src/mesa/main/api_validate.h | 13 -- src/mesa/main/compute.c | 234 ++++++++++++++++++++++++++++++++++- 3 files changed, 229 insertions(+), 252 deletions(-) diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c index cbb2361552e..850dedae7a4 100644 --- a/src/mesa/main/api_validate.c +++ b/src/mesa/main/api_validate.c @@ -1363,237 +1363,3 @@ _mesa_validate_MultiDrawElementsIndirectCount(struct gl_context *ctx, return valid_draw_indirect_parameters( ctx, "glMultiDrawElementsIndirectCountARB", drawcount); } - -static bool -check_valid_to_compute(struct gl_context *ctx, const char *function) -{ - if (!_mesa_has_compute_shaders(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "unsupported function (%s) called", - function); - return false; - } - - /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: - * - * "An INVALID_OPERATION error is generated if there is no active program - * for the compute shader stage." - */ - if (ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE] == NULL) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(no active compute shader)", - function); - return false; - } - - return true; -} - -GLboolean -_mesa_validate_DispatchCompute(struct gl_context *ctx, - const GLuint *num_groups) -{ - int i; - FLUSH_CURRENT(ctx, 0); - - if (!check_valid_to_compute(ctx, "glDispatchCompute")) - return GL_FALSE; - - for (i = 0; i < 3; i++) { - /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: - * - * "An INVALID_VALUE error is generated if any of num_groups_x, - * num_groups_y and num_groups_z are greater than or equal to the - * maximum work group count for the corresponding dimension." - * - * However, the "or equal to" portions appears to be a specification - * bug. In all other areas, the specification appears to indicate that - * the number of workgroups can match the MAX_COMPUTE_WORK_GROUP_COUNT - * value. For example, under DispatchComputeIndirect: - * - * "If any of num_groups_x, num_groups_y or num_groups_z is greater than - * the value of MAX_COMPUTE_WORK_GROUP_COUNT for the corresponding - * dimension then the results are undefined." - * - * Additionally, the OpenGLES 3.1 specification does not contain "or - * equal to" as an error condition. - */ - if (num_groups[i] > ctx->Const.MaxComputeWorkGroupCount[i]) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glDispatchCompute(num_groups_%c)", 'x' + i); - return GL_FALSE; - } - } - - /* The ARB_compute_variable_group_size spec says: - * - * "An INVALID_OPERATION error is generated by DispatchCompute if the active - * program for the compute shader stage has a variable work group size." - */ - struct gl_program *prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; - if (prog->info.cs.local_size_variable) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glDispatchCompute(variable work group size forbidden)"); - return GL_FALSE; - } - - return GL_TRUE; -} - -GLboolean -_mesa_validate_DispatchComputeGroupSizeARB(struct gl_context *ctx, - const GLuint *num_groups, - const GLuint *group_size) -{ - GLuint total_invocations = 1; - int i; - - FLUSH_CURRENT(ctx, 0); - - if (!check_valid_to_compute(ctx, "glDispatchComputeGroupSizeARB")) - return GL_FALSE; - - /* The ARB_compute_variable_group_size spec says: - * - * "An INVALID_OPERATION error is generated by - * DispatchComputeGroupSizeARB if the active program for the compute - * shader stage has a fixed work group size." - */ - struct gl_program *prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; - if (!prog->info.cs.local_size_variable) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glDispatchComputeGroupSizeARB(fixed work group size " - "forbidden)"); - return GL_FALSE; - } - - for (i = 0; i < 3; i++) { - /* The ARB_compute_variable_group_size spec says: - * - * "An INVALID_VALUE error is generated if any of num_groups_x, - * num_groups_y and num_groups_z are greater than or equal to the - * maximum work group count for the corresponding dimension." - */ - if (num_groups[i] > ctx->Const.MaxComputeWorkGroupCount[i]) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glDispatchComputeGroupSizeARB(num_groups_%c)", 'x' + i); - return GL_FALSE; - } - - /* The ARB_compute_variable_group_size spec says: - * - * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if - * any of , , or is less than - * or equal to zero or greater than the maximum local work group size - * for compute shaders with variable group size - * (MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB) in the corresponding - * dimension." - * - * However, the "less than" is a spec bug because they are declared as - * unsigned integers. - */ - if (group_size[i] == 0 || - group_size[i] > ctx->Const.MaxComputeVariableGroupSize[i]) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glDispatchComputeGroupSizeARB(group_size_%c)", 'x' + i); - return GL_FALSE; - } - - total_invocations *= group_size[i]; - } - - /* The ARB_compute_variable_group_size spec says: - * - * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if - * the product of , , and exceeds - * the implementation-dependent maximum local work group invocation count - * for compute shaders with variable group size - * (MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB)." - */ - if (total_invocations > ctx->Const.MaxComputeVariableGroupInvocations) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glDispatchComputeGroupSizeARB(product of local_sizes " - "exceeds MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB " - "(%d > %d))", total_invocations, - ctx->Const.MaxComputeVariableGroupInvocations); - return GL_FALSE; - } - - return GL_TRUE; -} - -static GLboolean -valid_dispatch_indirect(struct gl_context *ctx, - GLintptr indirect, - GLsizei size, const char *name) -{ - const uint64_t end = (uint64_t) indirect + size; - - if (!check_valid_to_compute(ctx, name)) - return GL_FALSE; - - /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: - * - * "An INVALID_VALUE error is generated if indirect is negative or is not a - * multiple of four." - */ - if (indirect & (sizeof(GLuint) - 1)) { - _mesa_error(ctx, GL_INVALID_VALUE, - "%s(indirect is not aligned)", name); - return GL_FALSE; - } - - if (indirect < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, - "%s(indirect is less than zero)", name); - return GL_FALSE; - } - - /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: - * - * "An INVALID_OPERATION error is generated if no buffer is bound to the - * DRAW_INDIRECT_BUFFER binding, or if the command would source data - * beyond the end of the buffer object." - */ - if (!_mesa_is_bufferobj(ctx->DispatchIndirectBuffer)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s: no buffer bound to DISPATCH_INDIRECT_BUFFER", name); - return GL_FALSE; - } - - if (_mesa_check_disallowed_mapping(ctx->DispatchIndirectBuffer)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(DISPATCH_INDIRECT_BUFFER is mapped)", name); - return GL_FALSE; - } - - if (ctx->DispatchIndirectBuffer->Size < end) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(DISPATCH_INDIRECT_BUFFER too small)", name); - return GL_FALSE; - } - - /* The ARB_compute_variable_group_size spec says: - * - * "An INVALID_OPERATION error is generated if the active program for the - * compute shader stage has a variable work group size." - */ - struct gl_program *prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; - if (prog->info.cs.local_size_variable) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(variable work group size forbidden)", name); - return GL_FALSE; - } - - return GL_TRUE; -} - -GLboolean -_mesa_validate_DispatchComputeIndirect(struct gl_context *ctx, - GLintptr indirect) -{ - FLUSH_CURRENT(ctx, 0); - - return valid_dispatch_indirect(ctx, indirect, 3 * sizeof(GLuint), - "glDispatchComputeIndirect"); -} diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h index 88c51bf9137..7a181153fb7 100644 --- a/src/mesa/main/api_validate.h +++ b/src/mesa/main/api_validate.h @@ -128,17 +128,4 @@ _mesa_validate_MultiDrawElementsIndirectCount(struct gl_context *ctx, GLsizei maxdrawcount, GLsizei stride); -extern GLboolean -_mesa_validate_DispatchCompute(struct gl_context *ctx, - const GLuint *num_groups); - -extern GLboolean -_mesa_validate_DispatchComputeIndirect(struct gl_context *ctx, - GLintptr indirect); - -extern GLboolean -_mesa_validate_DispatchComputeGroupSizeARB(struct gl_context *ctx, - const GLuint *num_groups, - const GLuint *group_size); - #endif diff --git a/src/mesa/main/compute.c b/src/mesa/main/compute.c index bb6253906bc..5c845166884 100644 --- a/src/mesa/main/compute.c +++ b/src/mesa/main/compute.c @@ -22,9 +22,234 @@ */ #include "glheader.h" +#include "bufferobj.h" #include "compute.h" #include "context.h" -#include "api_validate.h" + +static bool +check_valid_to_compute(struct gl_context *ctx, const char *function) +{ + if (!_mesa_has_compute_shaders(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "unsupported function (%s) called", + function); + return false; + } + + /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: + * + * "An INVALID_OPERATION error is generated if there is no active program + * for the compute shader stage." + */ + if (ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE] == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(no active compute shader)", + function); + return false; + } + + return true; +} + +static bool +validate_DispatchCompute(struct gl_context *ctx, const GLuint *num_groups) +{ + int i; + FLUSH_CURRENT(ctx, 0); + + if (!check_valid_to_compute(ctx, "glDispatchCompute")) + return GL_FALSE; + + for (i = 0; i < 3; i++) { + /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: + * + * "An INVALID_VALUE error is generated if any of num_groups_x, + * num_groups_y and num_groups_z are greater than or equal to the + * maximum work group count for the corresponding dimension." + * + * However, the "or equal to" portions appears to be a specification + * bug. In all other areas, the specification appears to indicate that + * the number of workgroups can match the MAX_COMPUTE_WORK_GROUP_COUNT + * value. For example, under DispatchComputeIndirect: + * + * "If any of num_groups_x, num_groups_y or num_groups_z is greater than + * the value of MAX_COMPUTE_WORK_GROUP_COUNT for the corresponding + * dimension then the results are undefined." + * + * Additionally, the OpenGLES 3.1 specification does not contain "or + * equal to" as an error condition. + */ + if (num_groups[i] > ctx->Const.MaxComputeWorkGroupCount[i]) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glDispatchCompute(num_groups_%c)", 'x' + i); + return GL_FALSE; + } + } + + /* The ARB_compute_variable_group_size spec says: + * + * "An INVALID_OPERATION error is generated by DispatchCompute if the active + * program for the compute shader stage has a variable work group size." + */ + struct gl_program *prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; + if (prog->info.cs.local_size_variable) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDispatchCompute(variable work group size forbidden)"); + return GL_FALSE; + } + + return GL_TRUE; +} + +static bool +validate_DispatchComputeGroupSizeARB(struct gl_context *ctx, + const GLuint *num_groups, + const GLuint *group_size) +{ + GLuint total_invocations = 1; + int i; + + FLUSH_CURRENT(ctx, 0); + + if (!check_valid_to_compute(ctx, "glDispatchComputeGroupSizeARB")) + return GL_FALSE; + + /* The ARB_compute_variable_group_size spec says: + * + * "An INVALID_OPERATION error is generated by + * DispatchComputeGroupSizeARB if the active program for the compute + * shader stage has a fixed work group size." + */ + struct gl_program *prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; + if (!prog->info.cs.local_size_variable) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDispatchComputeGroupSizeARB(fixed work group size " + "forbidden)"); + return GL_FALSE; + } + + for (i = 0; i < 3; i++) { + /* The ARB_compute_variable_group_size spec says: + * + * "An INVALID_VALUE error is generated if any of num_groups_x, + * num_groups_y and num_groups_z are greater than or equal to the + * maximum work group count for the corresponding dimension." + */ + if (num_groups[i] > ctx->Const.MaxComputeWorkGroupCount[i]) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glDispatchComputeGroupSizeARB(num_groups_%c)", 'x' + i); + return GL_FALSE; + } + + /* The ARB_compute_variable_group_size spec says: + * + * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if + * any of , , or is less than + * or equal to zero or greater than the maximum local work group size + * for compute shaders with variable group size + * (MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB) in the corresponding + * dimension." + * + * However, the "less than" is a spec bug because they are declared as + * unsigned integers. + */ + if (group_size[i] == 0 || + group_size[i] > ctx->Const.MaxComputeVariableGroupSize[i]) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glDispatchComputeGroupSizeARB(group_size_%c)", 'x' + i); + return GL_FALSE; + } + + total_invocations *= group_size[i]; + } + + /* The ARB_compute_variable_group_size spec says: + * + * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if + * the product of , , and exceeds + * the implementation-dependent maximum local work group invocation count + * for compute shaders with variable group size + * (MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB)." + */ + if (total_invocations > ctx->Const.MaxComputeVariableGroupInvocations) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glDispatchComputeGroupSizeARB(product of local_sizes " + "exceeds MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB " + "(%d > %d))", total_invocations, + ctx->Const.MaxComputeVariableGroupInvocations); + return GL_FALSE; + } + + return GL_TRUE; +} + +static bool +valid_dispatch_indirect(struct gl_context *ctx, GLintptr indirect) +{ + FLUSH_CURRENT(ctx, 0); + + GLsizei size = 3 * sizeof(GLuint); + const uint64_t end = (uint64_t) indirect + size; + const char *name = "glDispatchComputeIndirect"; + + if (!check_valid_to_compute(ctx, name)) + return GL_FALSE; + + /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: + * + * "An INVALID_VALUE error is generated if indirect is negative or is not a + * multiple of four." + */ + if (indirect & (sizeof(GLuint) - 1)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(indirect is not aligned)", name); + return GL_FALSE; + } + + if (indirect < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(indirect is less than zero)", name); + return GL_FALSE; + } + + /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: + * + * "An INVALID_OPERATION error is generated if no buffer is bound to the + * DRAW_INDIRECT_BUFFER binding, or if the command would source data + * beyond the end of the buffer object." + */ + if (!_mesa_is_bufferobj(ctx->DispatchIndirectBuffer)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s: no buffer bound to DISPATCH_INDIRECT_BUFFER", name); + return GL_FALSE; + } + + if (_mesa_check_disallowed_mapping(ctx->DispatchIndirectBuffer)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(DISPATCH_INDIRECT_BUFFER is mapped)", name); + return GL_FALSE; + } + + if (ctx->DispatchIndirectBuffer->Size < end) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(DISPATCH_INDIRECT_BUFFER too small)", name); + return GL_FALSE; + } + + /* The ARB_compute_variable_group_size spec says: + * + * "An INVALID_OPERATION error is generated if the active program for the + * compute shader stage has a variable work group size." + */ + struct gl_program *prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; + if (prog->info.cs.local_size_variable) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(variable work group size forbidden)", name); + return GL_FALSE; + } + + return GL_TRUE; +} void GLAPIENTRY _mesa_DispatchCompute(GLuint num_groups_x, @@ -38,7 +263,7 @@ _mesa_DispatchCompute(GLuint num_groups_x, _mesa_debug(ctx, "glDispatchCompute(%d, %d, %d)\n", num_groups_x, num_groups_y, num_groups_z); - if (!_mesa_validate_DispatchCompute(ctx, num_groups)) + if (!validate_DispatchCompute(ctx, num_groups)) return; if (num_groups_x == 0u || num_groups_y == 0u || num_groups_z == 0u) @@ -55,7 +280,7 @@ _mesa_DispatchComputeIndirect(GLintptr indirect) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glDispatchComputeIndirect(%ld)\n", (long) indirect); - if (!_mesa_validate_DispatchComputeIndirect(ctx, indirect)) + if (!valid_dispatch_indirect(ctx, indirect)) return; ctx->Driver.DispatchComputeIndirect(ctx, indirect); @@ -76,8 +301,7 @@ _mesa_DispatchComputeGroupSizeARB(GLuint num_groups_x, GLuint num_groups_y, num_groups_x, num_groups_y, num_groups_z, group_size_x, group_size_y, group_size_z); - if (!_mesa_validate_DispatchComputeGroupSizeARB(ctx, num_groups, - group_size)) + if (!validate_DispatchComputeGroupSizeARB(ctx, num_groups, group_size)) return; if (num_groups_x == 0u || num_groups_y == 0u || num_groups_z == 0u) -- 2.30.2