From 45ab63c0cb274b20a7ae1f390b123e13a5b46c98 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Wed, 7 Sep 2016 21:52:08 +0200 Subject: [PATCH] mesa/main: add support for ARB_compute_variable_groups_size MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit v5: - replace fixed_local_size by !LocalSizeVariable (Nicolai) v4: - slightly indent spec quotes (Nicolai) - drop useless _mesa_has_compute_shaders() check (Nicolai) - move the fixed local size outside of the loop (Nicolai) - add missing check for invalid use of work group count v2: - update formatting spec quotations (Ian) - move the total_invocations check outside of the loop (Ian) Signed-off-by: Samuel Pitoiset Reviewed-by: Nicolai Hähnle --- src/mesa/main/api_validate.c | 109 +++++++++++++++++++++++++++++++ src/mesa/main/api_validate.h | 4 ++ src/mesa/main/compute.c | 17 +++++ src/mesa/main/context.c | 6 ++ src/mesa/main/dd.h | 9 +++ src/mesa/main/extensions_table.h | 1 + src/mesa/main/get.c | 10 +++ src/mesa/main/get_hash_params.py | 3 + src/mesa/main/mtypes.h | 24 ++++++- src/mesa/main/shaderapi.c | 1 + src/mesa/main/shaderobj.c | 2 + 11 files changed, 185 insertions(+), 1 deletion(-) diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c index 05691d25da0..c3c5a696928 100644 --- a/src/mesa/main/api_validate.c +++ b/src/mesa/main/api_validate.c @@ -1285,6 +1285,7 @@ GLboolean _mesa_validate_DispatchCompute(struct gl_context *ctx, const GLuint *num_groups) { + struct gl_shader_program *prog; int i; FLUSH_CURRENT(ctx, 0); @@ -1317,6 +1318,101 @@ _mesa_validate_DispatchCompute(struct gl_context *ctx, } } + /* 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." + */ + prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; + if (prog->Comp.LocalSizeVariable) { + _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) +{ + struct gl_shader_program *prog; + 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." + */ + prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; + if (!prog->Comp.LocalSizeVariable) { + _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; } @@ -1326,6 +1422,7 @@ valid_dispatch_indirect(struct gl_context *ctx, GLsizei size, const char *name) { const uint64_t end = (uint64_t) indirect + size; + struct gl_shader_program *prog; if (!check_valid_to_compute(ctx, name)) return GL_FALSE; @@ -1371,6 +1468,18 @@ valid_dispatch_indirect(struct gl_context *ctx, 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." + */ + prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; + if (prog->Comp.LocalSizeVariable) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(variable work group size forbidden)", name); + return GL_FALSE; + } + return GL_TRUE; } diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h index 2eba834c50d..e94f02e4ba5 100644 --- a/src/mesa/main/api_validate.h +++ b/src/mesa/main/api_validate.h @@ -132,5 +132,9 @@ 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 b052bae7e91..bb6253906bc 100644 --- a/src/mesa/main/compute.c +++ b/src/mesa/main/compute.c @@ -66,5 +66,22 @@ _mesa_DispatchComputeGroupSizeARB(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z) { + GET_CURRENT_CONTEXT(ctx); + const GLuint num_groups[3] = { num_groups_x, num_groups_y, num_groups_z }; + const GLuint group_size[3] = { group_size_x, group_size_y, group_size_z }; + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glDispatchComputeGroupSizeARB(%d, %d, %d, %d, %d, %d)\n", + 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)) + return; + + if (num_groups_x == 0u || num_groups_y == 0u || num_groups_z == 0u) + return; + ctx->Driver.DispatchComputeGroupSize(ctx, num_groups, group_size); } diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 697b5186fb8..47fd4a0919f 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -721,6 +721,12 @@ _mesa_init_constants(struct gl_constants *consts, gl_api api) consts->MaxTessPatchComponents = MAX_TESS_PATCH_COMPONENTS; consts->MaxTessControlTotalOutputComponents = MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS; consts->PrimitiveRestartForPatches = false; + + /** GL_ARB_compute_variable_group_size */ + consts->MaxComputeVariableGroupSize[0] = 512; + consts->MaxComputeVariableGroupSize[1] = 512; + consts->MaxComputeVariableGroupSize[2] = 64; + consts->MaxComputeVariableGroupInvocations = 512; } diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 257dc103817..7f5327186ff 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -977,6 +977,15 @@ struct dd_function_table { void (*DispatchComputeIndirect)(struct gl_context *ctx, GLintptr indirect); /*@}*/ + /** + * \name GL_ARB_compute_variable_group_size interface + */ + /*@{*/ + void (*DispatchComputeGroupSize)(struct gl_context *ctx, + const GLuint *num_groups, + const GLuint *group_size); + /*@}*/ + /** * Query information about memory. Device memory is e.g. VRAM. Staging * memory is e.g. GART. All sizes are in kilobytes. diff --git a/src/mesa/main/extensions_table.h b/src/mesa/main/extensions_table.h index e7669bbd0fc..b6286fc6d59 100644 --- a/src/mesa/main/extensions_table.h +++ b/src/mesa/main/extensions_table.h @@ -42,6 +42,7 @@ EXT(ARB_clip_control , ARB_clip_control EXT(ARB_color_buffer_float , ARB_color_buffer_float , GLL, GLC, x , x , 2004) EXT(ARB_compressed_texture_pixel_storage , dummy_true , GLL, GLC, x , x , 2011) EXT(ARB_compute_shader , ARB_compute_shader , GLL, GLC, x , x , 2012) +EXT(ARB_compute_variable_group_size , ARB_compute_variable_group_size , GLL, GLC, x , x , 2013) EXT(ARB_conditional_render_inverted , ARB_conditional_render_inverted , GLL, GLC, x , x , 2014) EXT(ARB_conservative_depth , ARB_conservative_depth , GLL, GLC, x , x , 2011) EXT(ARB_copy_buffer , dummy_true , GLL, GLC, x , x , 2008) diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index 64a4b0e6ccf..bd85befa125 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -490,6 +490,7 @@ EXTRA_EXT(ARB_cull_distance); EXTRA_EXT(EXT_window_rectangles); EXTRA_EXT(KHR_blend_equation_advanced_coherent); EXTRA_EXT(OES_primitive_bounding_box); +EXTRA_EXT(ARB_compute_variable_group_size); static const int extra_ARB_color_buffer_float_or_glcore[] = { @@ -2293,6 +2294,15 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) goto invalid_value; v->value_int = ctx->Const.MaxComputeWorkGroupSize[index]; return TYPE_INT; + + /* ARB_compute_variable_group_size */ + case GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB: + if (!ctx->Extensions.ARB_compute_variable_group_size) + goto invalid_enum; + if (index >= 3) + goto invalid_value; + v->value_int = ctx->Const.MaxComputeVariableGroupSize[index]; + return TYPE_INT; } invalid_enum: diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py index 7520a39b09a..6849b5b7d58 100644 --- a/src/mesa/main/get_hash_params.py +++ b/src/mesa/main/get_hash_params.py @@ -942,6 +942,9 @@ descriptor=[ # GL_ARB_cull_distance [ "MAX_CULL_DISTANCES", "CONTEXT_INT(Const.MaxClipPlanes), extra_ARB_cull_distance" ], [ "MAX_COMBINED_CLIP_AND_CULL_DISTANCES", "CONTEXT_INT(Const.MaxClipPlanes), extra_ARB_cull_distance" ], + +# GL_ARB_compute_variable_group_size + [ "MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB", "CONTEXT_INT(Const.MaxComputeVariableGroupInvocations), extra_ARB_compute_variable_group_size" ], ]}, # Enums restricted to OpenGL Core profile diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index d494872eef9..ab9839c7516 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2078,6 +2078,11 @@ struct gl_compute_program * Size of shared variables accessed by the compute shader. */ unsigned SharedSize; + + /** + * Whether a variable work group size has been specified. + */ + bool LocalSizeVariable; }; @@ -2340,7 +2345,8 @@ struct gl_shader_info GLbitfield BlendSupport; /** - * Compute shader state from ARB_compute_shader layout qualifiers. + * Compute shader state from ARB_compute_shader and + * ARB_compute_variable_group_size layout qualifiers. */ struct { /** @@ -2348,6 +2354,12 @@ struct gl_shader_info * it's not set in this shader. */ unsigned LocalSize[3]; + + /** + * Whether a variable work group size has been specified as defined by + * ARB_compute_variable_group_size. + */ + bool LocalSizeVariable; } Comp; }; @@ -2826,6 +2838,11 @@ struct gl_shader_program * Size of shared variables accessed by the compute shader. */ unsigned SharedSize; + + /** + * Whether a variable work group size has been specified. + */ + bool LocalSizeVariable; } Comp; /* post-link info: */ @@ -3783,6 +3800,10 @@ struct gl_constants GLuint MaxComputeWorkGroupInvocations; GLuint MaxComputeSharedMemorySize; + /** GL_ARB_compute_variable_group_size */ + GLuint MaxComputeVariableGroupSize[3]; /* Array of x, y, z dimensions */ + GLuint MaxComputeVariableGroupInvocations; + /** GL_ARB_gpu_shader5 */ GLfloat MinFragmentInterpolationOffset; GLfloat MaxFragmentInterpolationOffset; @@ -3834,6 +3855,7 @@ struct gl_extensions GLboolean ARB_clip_control; GLboolean ARB_color_buffer_float; GLboolean ARB_compute_shader; + GLboolean ARB_compute_variable_group_size; GLboolean ARB_conditional_render_inverted; GLboolean ARB_conservative_depth; GLboolean ARB_copy_image; diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 1af1c3f5794..c40bb2d69a7 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -2212,6 +2212,7 @@ _mesa_copy_linked_program_data(gl_shader_stage type, for (i = 0; i < 3; i++) dst_cp->LocalSize[i] = src->Comp.LocalSize[i]; dst_cp->SharedSize = src->Comp.SharedSize; + dst_cp->LocalSizeVariable = src->Comp.LocalSizeVariable; break; } default: diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c index 350b677911e..136ac7b46a6 100644 --- a/src/mesa/main/shaderobj.c +++ b/src/mesa/main/shaderobj.c @@ -262,6 +262,8 @@ init_shader_program(struct gl_shader_program *prog) prog->Geom.UsesEndPrimitive = false; prog->Geom.UsesStreams = false; + prog->Comp.LocalSizeVariable = false; + prog->TransformFeedback.BufferMode = GL_INTERLEAVED_ATTRIBS; exec_list_make_empty(&prog->EmptyUniformLocations); -- 2.30.2