summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Arceri <tarceri@itsqueeze.com>2017-05-15 11:08:13 +1000
committerTimothy Arceri <tarceri@itsqueeze.com>2017-05-17 10:12:04 +1000
commit64757e73de4355353e15706d9d25269f181eb775 (patch)
tree3c97f87dc0c22501b7ca305e50b80d61c143be16
parent25591adc286a217ee344d17d277c81ba9e6d353b (diff)
mesa: move DispatchCompute() validation to compute.c
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 <nicolai.haehnle@amd.com>
-rw-r--r--src/mesa/main/api_validate.c234
-rw-r--r--src/mesa/main/api_validate.h13
-rw-r--r--src/mesa/main/compute.c234
3 files changed, 229 insertions, 252 deletions
diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
index cbb2361552..850dedae7a 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 <group_size_x>, <group_size_y>, or <group_size_z> 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 <group_size_x>, <group_size_y>, and <group_size_z> 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 88c51bf913..7a181153fb 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 bb6253906b..5c84516688 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 <group_size_x>, <group_size_y>, or <group_size_z> 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 <group_size_x>, <group_size_y>, and <group_size_z> 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)