xref: /aosp_15_r20/external/mesa3d/src/mesa/main/compute.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2014 Intel Corporation
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*61046927SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
25*61046927SAndroid Build Coastguard Worker #include "bufferobj.h"
26*61046927SAndroid Build Coastguard Worker #include "context.h"
27*61046927SAndroid Build Coastguard Worker #include "state.h"
28*61046927SAndroid Build Coastguard Worker #include "api_exec_decl.h"
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #include "pipe/p_state.h"
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_context.h"
33*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_cb_bitmap.h"
34*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_util.h"
35*61046927SAndroid Build Coastguard Worker 
36*61046927SAndroid Build Coastguard Worker static bool
check_valid_to_compute(struct gl_context * ctx,const char * function)37*61046927SAndroid Build Coastguard Worker check_valid_to_compute(struct gl_context *ctx, const char *function)
38*61046927SAndroid Build Coastguard Worker {
39*61046927SAndroid Build Coastguard Worker    if (!_mesa_has_compute_shaders(ctx)) {
40*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
41*61046927SAndroid Build Coastguard Worker                   "unsupported function (%s) called",
42*61046927SAndroid Build Coastguard Worker                   function);
43*61046927SAndroid Build Coastguard Worker       return false;
44*61046927SAndroid Build Coastguard Worker    }
45*61046927SAndroid Build Coastguard Worker 
46*61046927SAndroid Build Coastguard Worker    /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
47*61046927SAndroid Build Coastguard Worker     *
48*61046927SAndroid Build Coastguard Worker     * "An INVALID_OPERATION error is generated if there is no active program
49*61046927SAndroid Build Coastguard Worker     *  for the compute shader stage."
50*61046927SAndroid Build Coastguard Worker     */
51*61046927SAndroid Build Coastguard Worker    if (ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE] == NULL) {
52*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
53*61046927SAndroid Build Coastguard Worker                   "%s(no active compute shader)",
54*61046927SAndroid Build Coastguard Worker                   function);
55*61046927SAndroid Build Coastguard Worker       return false;
56*61046927SAndroid Build Coastguard Worker    }
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker    return true;
59*61046927SAndroid Build Coastguard Worker }
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker static bool
validate_DispatchCompute(struct gl_context * ctx,struct pipe_grid_info * info)62*61046927SAndroid Build Coastguard Worker validate_DispatchCompute(struct gl_context *ctx, struct pipe_grid_info *info)
63*61046927SAndroid Build Coastguard Worker {
64*61046927SAndroid Build Coastguard Worker    if (!check_valid_to_compute(ctx, "glDispatchCompute"))
65*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < 3; i++) {
68*61046927SAndroid Build Coastguard Worker       /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
69*61046927SAndroid Build Coastguard Worker        *
70*61046927SAndroid Build Coastguard Worker        * "An INVALID_VALUE error is generated if any of num_groups_x,
71*61046927SAndroid Build Coastguard Worker        *  num_groups_y and num_groups_z are greater than or equal to the
72*61046927SAndroid Build Coastguard Worker        *  maximum work group count for the corresponding dimension."
73*61046927SAndroid Build Coastguard Worker        *
74*61046927SAndroid Build Coastguard Worker        * However, the "or equal to" portions appears to be a specification
75*61046927SAndroid Build Coastguard Worker        * bug. In all other areas, the specification appears to indicate that
76*61046927SAndroid Build Coastguard Worker        * the number of workgroups can match the MAX_COMPUTE_WORK_GROUP_COUNT
77*61046927SAndroid Build Coastguard Worker        * value. For example, under DispatchComputeIndirect:
78*61046927SAndroid Build Coastguard Worker        *
79*61046927SAndroid Build Coastguard Worker        * "If any of num_groups_x, num_groups_y or num_groups_z is greater than
80*61046927SAndroid Build Coastguard Worker        *  the value of MAX_COMPUTE_WORK_GROUP_COUNT for the corresponding
81*61046927SAndroid Build Coastguard Worker        *  dimension then the results are undefined."
82*61046927SAndroid Build Coastguard Worker        *
83*61046927SAndroid Build Coastguard Worker        * Additionally, the OpenGLES 3.1 specification does not contain "or
84*61046927SAndroid Build Coastguard Worker        * equal to" as an error condition.
85*61046927SAndroid Build Coastguard Worker        */
86*61046927SAndroid Build Coastguard Worker       if (info->grid[i] > ctx->Const.MaxComputeWorkGroupCount[i]) {
87*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_VALUE,
88*61046927SAndroid Build Coastguard Worker                      "glDispatchCompute(num_groups_%c)", 'x' + i);
89*61046927SAndroid Build Coastguard Worker          return GL_FALSE;
90*61046927SAndroid Build Coastguard Worker       }
91*61046927SAndroid Build Coastguard Worker    }
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker    /* The ARB_compute_variable_group_size spec says:
94*61046927SAndroid Build Coastguard Worker     *
95*61046927SAndroid Build Coastguard Worker     * "An INVALID_OPERATION error is generated by DispatchCompute if the active
96*61046927SAndroid Build Coastguard Worker     *  program for the compute shader stage has a variable work group size."
97*61046927SAndroid Build Coastguard Worker     */
98*61046927SAndroid Build Coastguard Worker    struct gl_program *prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
99*61046927SAndroid Build Coastguard Worker    if (prog->info.workgroup_size_variable) {
100*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
101*61046927SAndroid Build Coastguard Worker                   "glDispatchCompute(variable work group size forbidden)");
102*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
103*61046927SAndroid Build Coastguard Worker    }
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
106*61046927SAndroid Build Coastguard Worker }
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker static bool
validate_DispatchComputeGroupSizeARB(struct gl_context * ctx,struct pipe_grid_info * info)109*61046927SAndroid Build Coastguard Worker validate_DispatchComputeGroupSizeARB(struct gl_context *ctx,
110*61046927SAndroid Build Coastguard Worker                                      struct pipe_grid_info *info)
111*61046927SAndroid Build Coastguard Worker {
112*61046927SAndroid Build Coastguard Worker    if (!check_valid_to_compute(ctx, "glDispatchComputeGroupSizeARB"))
113*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker    /* The ARB_compute_variable_group_size spec says:
116*61046927SAndroid Build Coastguard Worker     *
117*61046927SAndroid Build Coastguard Worker     * "An INVALID_OPERATION error is generated by
118*61046927SAndroid Build Coastguard Worker     *  DispatchComputeGroupSizeARB if the active program for the compute
119*61046927SAndroid Build Coastguard Worker     *  shader stage has a fixed work group size."
120*61046927SAndroid Build Coastguard Worker     */
121*61046927SAndroid Build Coastguard Worker    struct gl_program *prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
122*61046927SAndroid Build Coastguard Worker    if (!prog->info.workgroup_size_variable) {
123*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
124*61046927SAndroid Build Coastguard Worker                   "glDispatchComputeGroupSizeARB(fixed work group size "
125*61046927SAndroid Build Coastguard Worker                   "forbidden)");
126*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
127*61046927SAndroid Build Coastguard Worker    }
128*61046927SAndroid Build Coastguard Worker 
129*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < 3; i++) {
130*61046927SAndroid Build Coastguard Worker       /* The ARB_compute_variable_group_size spec says:
131*61046927SAndroid Build Coastguard Worker        *
132*61046927SAndroid Build Coastguard Worker        * "An INVALID_VALUE error is generated if any of num_groups_x,
133*61046927SAndroid Build Coastguard Worker        *  num_groups_y and num_groups_z are greater than or equal to the
134*61046927SAndroid Build Coastguard Worker        *  maximum work group count for the corresponding dimension."
135*61046927SAndroid Build Coastguard Worker        */
136*61046927SAndroid Build Coastguard Worker       if (info->grid[i] > ctx->Const.MaxComputeWorkGroupCount[i]) {
137*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_VALUE,
138*61046927SAndroid Build Coastguard Worker                      "glDispatchComputeGroupSizeARB(num_groups_%c)", 'x' + i);
139*61046927SAndroid Build Coastguard Worker          return GL_FALSE;
140*61046927SAndroid Build Coastguard Worker       }
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker       /* The ARB_compute_variable_group_size spec says:
143*61046927SAndroid Build Coastguard Worker        *
144*61046927SAndroid Build Coastguard Worker        * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if
145*61046927SAndroid Build Coastguard Worker        *  any of <group_size_x>, <group_size_y>, or <group_size_z> is less than
146*61046927SAndroid Build Coastguard Worker        *  or equal to zero or greater than the maximum local work group size
147*61046927SAndroid Build Coastguard Worker        *  for compute shaders with variable group size
148*61046927SAndroid Build Coastguard Worker        *  (MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB) in the corresponding
149*61046927SAndroid Build Coastguard Worker        *  dimension."
150*61046927SAndroid Build Coastguard Worker        *
151*61046927SAndroid Build Coastguard Worker        * However, the "less than" is a spec bug because they are declared as
152*61046927SAndroid Build Coastguard Worker        * unsigned integers.
153*61046927SAndroid Build Coastguard Worker        */
154*61046927SAndroid Build Coastguard Worker       if (info->block[i] == 0 ||
155*61046927SAndroid Build Coastguard Worker           info->block[i] > ctx->Const.MaxComputeVariableGroupSize[i]) {
156*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_VALUE,
157*61046927SAndroid Build Coastguard Worker                      "glDispatchComputeGroupSizeARB(group_size_%c)", 'x' + i);
158*61046927SAndroid Build Coastguard Worker          return GL_FALSE;
159*61046927SAndroid Build Coastguard Worker       }
160*61046927SAndroid Build Coastguard Worker    }
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker    /* The ARB_compute_variable_group_size spec says:
163*61046927SAndroid Build Coastguard Worker     *
164*61046927SAndroid Build Coastguard Worker     * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if
165*61046927SAndroid Build Coastguard Worker     *  the product of <group_size_x>, <group_size_y>, and <group_size_z> exceeds
166*61046927SAndroid Build Coastguard Worker     *  the implementation-dependent maximum local work group invocation count
167*61046927SAndroid Build Coastguard Worker     *  for compute shaders with variable group size
168*61046927SAndroid Build Coastguard Worker     *  (MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB)."
169*61046927SAndroid Build Coastguard Worker     */
170*61046927SAndroid Build Coastguard Worker    uint64_t total_invocations = info->block[0] * info->block[1];
171*61046927SAndroid Build Coastguard Worker    if (total_invocations <= UINT32_MAX) {
172*61046927SAndroid Build Coastguard Worker       /* Only bother multiplying the third value if total still fits in
173*61046927SAndroid Build Coastguard Worker        * 32-bit, since MaxComputeVariableGroupInvocations is also 32-bit.
174*61046927SAndroid Build Coastguard Worker        */
175*61046927SAndroid Build Coastguard Worker       total_invocations *= info->block[2];
176*61046927SAndroid Build Coastguard Worker    }
177*61046927SAndroid Build Coastguard Worker    if (total_invocations > ctx->Const.MaxComputeVariableGroupInvocations) {
178*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE,
179*61046927SAndroid Build Coastguard Worker                   "glDispatchComputeGroupSizeARB(product of local_sizes "
180*61046927SAndroid Build Coastguard Worker                   "exceeds MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB "
181*61046927SAndroid Build Coastguard Worker                   "(%u * %u * %u > %u))",
182*61046927SAndroid Build Coastguard Worker                   info->block[0], info->block[1], info->block[2],
183*61046927SAndroid Build Coastguard Worker                   ctx->Const.MaxComputeVariableGroupInvocations);
184*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
185*61046927SAndroid Build Coastguard Worker    }
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker    /* The NV_compute_shader_derivatives spec says:
188*61046927SAndroid Build Coastguard Worker     *
189*61046927SAndroid Build Coastguard Worker     * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if
190*61046927SAndroid Build Coastguard Worker     *  the active program for the compute shader stage has a compute shader
191*61046927SAndroid Build Coastguard Worker     *  using the "derivative_group_quadsNV" layout qualifier and
192*61046927SAndroid Build Coastguard Worker     *  <group_size_x> or <group_size_y> is not a multiple of two.
193*61046927SAndroid Build Coastguard Worker     *
194*61046927SAndroid Build Coastguard Worker     *  An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if
195*61046927SAndroid Build Coastguard Worker     *  the active program for the compute shader stage has a compute shader
196*61046927SAndroid Build Coastguard Worker     *  using the "derivative_group_linearNV" layout qualifier and the product
197*61046927SAndroid Build Coastguard Worker     *  of <group_size_x>, <group_size_y>, and <group_size_z> is not a multiple
198*61046927SAndroid Build Coastguard Worker     *  of four."
199*61046927SAndroid Build Coastguard Worker     */
200*61046927SAndroid Build Coastguard Worker    if (prog->info.derivative_group == DERIVATIVE_GROUP_QUADS &&
201*61046927SAndroid Build Coastguard Worker        ((info->block[0] & 1) || (info->block[1] & 1))) {
202*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE,
203*61046927SAndroid Build Coastguard Worker                   "glDispatchComputeGroupSizeARB(derivative_group_quadsNV "
204*61046927SAndroid Build Coastguard Worker                   "requires group_size_x (%d) and group_size_y (%d) to be "
205*61046927SAndroid Build Coastguard Worker                   "divisble by 2)", info->block[0], info->block[1]);
206*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
207*61046927SAndroid Build Coastguard Worker    }
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker    if (prog->info.derivative_group == DERIVATIVE_GROUP_LINEAR &&
210*61046927SAndroid Build Coastguard Worker        total_invocations & 3) {
211*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE,
212*61046927SAndroid Build Coastguard Worker                   "glDispatchComputeGroupSizeARB(derivative_group_linearNV "
213*61046927SAndroid Build Coastguard Worker                   "requires product of group sizes (%"PRIu64") to be divisible "
214*61046927SAndroid Build Coastguard Worker                   "by 4)", total_invocations);
215*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
216*61046927SAndroid Build Coastguard Worker    }
217*61046927SAndroid Build Coastguard Worker 
218*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
219*61046927SAndroid Build Coastguard Worker }
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker static bool
valid_dispatch_indirect(struct gl_context * ctx,GLintptr indirect)222*61046927SAndroid Build Coastguard Worker valid_dispatch_indirect(struct gl_context *ctx,  GLintptr indirect)
223*61046927SAndroid Build Coastguard Worker {
224*61046927SAndroid Build Coastguard Worker    GLsizei size = 3 * sizeof(GLuint);
225*61046927SAndroid Build Coastguard Worker    const uint64_t end = (uint64_t) indirect + size;
226*61046927SAndroid Build Coastguard Worker    const char *name = "glDispatchComputeIndirect";
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    if (!check_valid_to_compute(ctx, name))
229*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker    /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
232*61046927SAndroid Build Coastguard Worker     *
233*61046927SAndroid Build Coastguard Worker     * "An INVALID_VALUE error is generated if indirect is negative or is not a
234*61046927SAndroid Build Coastguard Worker     *  multiple of four."
235*61046927SAndroid Build Coastguard Worker     */
236*61046927SAndroid Build Coastguard Worker    if (indirect & (sizeof(GLuint) - 1)) {
237*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE,
238*61046927SAndroid Build Coastguard Worker                   "%s(indirect is not aligned)", name);
239*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
240*61046927SAndroid Build Coastguard Worker    }
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker    if (indirect < 0) {
243*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE,
244*61046927SAndroid Build Coastguard Worker                   "%s(indirect is less than zero)", name);
245*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
246*61046927SAndroid Build Coastguard Worker    }
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker    /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
249*61046927SAndroid Build Coastguard Worker     *
250*61046927SAndroid Build Coastguard Worker     * "An INVALID_OPERATION error is generated if no buffer is bound to the
251*61046927SAndroid Build Coastguard Worker     *  DRAW_INDIRECT_BUFFER binding, or if the command would source data
252*61046927SAndroid Build Coastguard Worker     *  beyond the end of the buffer object."
253*61046927SAndroid Build Coastguard Worker     */
254*61046927SAndroid Build Coastguard Worker    if (!ctx->DispatchIndirectBuffer) {
255*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
256*61046927SAndroid Build Coastguard Worker                   "%s: no buffer bound to DISPATCH_INDIRECT_BUFFER", name);
257*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
258*61046927SAndroid Build Coastguard Worker    }
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker    if (_mesa_check_disallowed_mapping(ctx->DispatchIndirectBuffer)) {
261*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
262*61046927SAndroid Build Coastguard Worker                   "%s(DISPATCH_INDIRECT_BUFFER is mapped)", name);
263*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
264*61046927SAndroid Build Coastguard Worker    }
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker    if (ctx->DispatchIndirectBuffer->Size < end) {
267*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
268*61046927SAndroid Build Coastguard Worker                   "%s(DISPATCH_INDIRECT_BUFFER too small)", name);
269*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
270*61046927SAndroid Build Coastguard Worker    }
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker    /* The ARB_compute_variable_group_size spec says:
273*61046927SAndroid Build Coastguard Worker     *
274*61046927SAndroid Build Coastguard Worker     * "An INVALID_OPERATION error is generated if the active program for the
275*61046927SAndroid Build Coastguard Worker     *  compute shader stage has a variable work group size."
276*61046927SAndroid Build Coastguard Worker     */
277*61046927SAndroid Build Coastguard Worker    struct gl_program *prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
278*61046927SAndroid Build Coastguard Worker    if (prog->info.workgroup_size_variable) {
279*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
280*61046927SAndroid Build Coastguard Worker                   "%s(variable work group size forbidden)", name);
281*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
282*61046927SAndroid Build Coastguard Worker    }
283*61046927SAndroid Build Coastguard Worker 
284*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
285*61046927SAndroid Build Coastguard Worker }
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker static void
prepare_compute(struct gl_context * ctx)288*61046927SAndroid Build Coastguard Worker prepare_compute(struct gl_context *ctx)
289*61046927SAndroid Build Coastguard Worker {
290*61046927SAndroid Build Coastguard Worker    struct st_context *st = st_context(ctx);
291*61046927SAndroid Build Coastguard Worker 
292*61046927SAndroid Build Coastguard Worker    st_flush_bitmap_cache(st);
293*61046927SAndroid Build Coastguard Worker    st_invalidate_readpix_cache(st);
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker    if (ctx->NewState)
296*61046927SAndroid Build Coastguard Worker       _mesa_update_state(ctx);
297*61046927SAndroid Build Coastguard Worker 
298*61046927SAndroid Build Coastguard Worker    st_validate_state(st, ST_PIPELINE_COMPUTE_STATE_MASK);
299*61046927SAndroid Build Coastguard Worker }
300*61046927SAndroid Build Coastguard Worker 
301*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
dispatch_compute(GLuint num_groups_x,GLuint num_groups_y,GLuint num_groups_z,bool no_error)302*61046927SAndroid Build Coastguard Worker dispatch_compute(GLuint num_groups_x, GLuint num_groups_y,
303*61046927SAndroid Build Coastguard Worker                  GLuint num_groups_z, bool no_error)
304*61046927SAndroid Build Coastguard Worker {
305*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
306*61046927SAndroid Build Coastguard Worker    struct pipe_grid_info info = { 0 };
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker    FLUSH_VERTICES(ctx, 0, 0);
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
311*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glDispatchCompute(%d, %d, %d)\n",
312*61046927SAndroid Build Coastguard Worker                   num_groups_x, num_groups_y, num_groups_z);
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker    info.grid[0] = num_groups_x;
315*61046927SAndroid Build Coastguard Worker    info.grid[1] = num_groups_y;
316*61046927SAndroid Build Coastguard Worker    info.grid[2] = num_groups_z;
317*61046927SAndroid Build Coastguard Worker 
318*61046927SAndroid Build Coastguard Worker    if (!no_error && !validate_DispatchCompute(ctx, &info))
319*61046927SAndroid Build Coastguard Worker       return;
320*61046927SAndroid Build Coastguard Worker 
321*61046927SAndroid Build Coastguard Worker    if (num_groups_x == 0u || num_groups_y == 0u || num_groups_z == 0u)
322*61046927SAndroid Build Coastguard Worker        return;
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker    struct gl_program *prog =
325*61046927SAndroid Build Coastguard Worker       ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
326*61046927SAndroid Build Coastguard Worker    info.block[0] = prog->info.workgroup_size[0];
327*61046927SAndroid Build Coastguard Worker    info.block[1] = prog->info.workgroup_size[1];
328*61046927SAndroid Build Coastguard Worker    info.block[2] = prog->info.workgroup_size[2];
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker    prepare_compute(ctx);
331*61046927SAndroid Build Coastguard Worker    ctx->pipe->launch_grid(ctx->pipe, &info);
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
334*61046927SAndroid Build Coastguard Worker       _mesa_flush(ctx);
335*61046927SAndroid Build Coastguard Worker }
336*61046927SAndroid Build Coastguard Worker 
337*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_DispatchCompute_no_error(GLuint num_groups_x,GLuint num_groups_y,GLuint num_groups_z)338*61046927SAndroid Build Coastguard Worker _mesa_DispatchCompute_no_error(GLuint num_groups_x, GLuint num_groups_y,
339*61046927SAndroid Build Coastguard Worker                                GLuint num_groups_z)
340*61046927SAndroid Build Coastguard Worker {
341*61046927SAndroid Build Coastguard Worker    dispatch_compute(num_groups_x, num_groups_y, num_groups_z, true);
342*61046927SAndroid Build Coastguard Worker }
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_DispatchCompute(GLuint num_groups_x,GLuint num_groups_y,GLuint num_groups_z)345*61046927SAndroid Build Coastguard Worker _mesa_DispatchCompute(GLuint num_groups_x,
346*61046927SAndroid Build Coastguard Worker                       GLuint num_groups_y,
347*61046927SAndroid Build Coastguard Worker                       GLuint num_groups_z)
348*61046927SAndroid Build Coastguard Worker {
349*61046927SAndroid Build Coastguard Worker    dispatch_compute(num_groups_x, num_groups_y, num_groups_z, false);
350*61046927SAndroid Build Coastguard Worker }
351*61046927SAndroid Build Coastguard Worker 
352*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
dispatch_compute_indirect(GLintptr indirect,bool no_error)353*61046927SAndroid Build Coastguard Worker dispatch_compute_indirect(GLintptr indirect, bool no_error)
354*61046927SAndroid Build Coastguard Worker {
355*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
356*61046927SAndroid Build Coastguard Worker 
357*61046927SAndroid Build Coastguard Worker    FLUSH_VERTICES(ctx, 0, 0);
358*61046927SAndroid Build Coastguard Worker 
359*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
360*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glDispatchComputeIndirect(%ld)\n", (long) indirect);
361*61046927SAndroid Build Coastguard Worker 
362*61046927SAndroid Build Coastguard Worker    if (!no_error && !valid_dispatch_indirect(ctx, indirect))
363*61046927SAndroid Build Coastguard Worker       return;
364*61046927SAndroid Build Coastguard Worker 
365*61046927SAndroid Build Coastguard Worker    struct pipe_grid_info info = { 0 };
366*61046927SAndroid Build Coastguard Worker    info.indirect_offset = indirect;
367*61046927SAndroid Build Coastguard Worker    info.indirect = ctx->DispatchIndirectBuffer->buffer;
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker    struct gl_program *prog =
370*61046927SAndroid Build Coastguard Worker       ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
371*61046927SAndroid Build Coastguard Worker    info.block[0] = prog->info.workgroup_size[0];
372*61046927SAndroid Build Coastguard Worker    info.block[1] = prog->info.workgroup_size[1];
373*61046927SAndroid Build Coastguard Worker    info.block[2] = prog->info.workgroup_size[2];
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker    prepare_compute(ctx);
376*61046927SAndroid Build Coastguard Worker    ctx->pipe->launch_grid(ctx->pipe, &info);
377*61046927SAndroid Build Coastguard Worker 
378*61046927SAndroid Build Coastguard Worker    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
379*61046927SAndroid Build Coastguard Worker       _mesa_flush(ctx);
380*61046927SAndroid Build Coastguard Worker }
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker extern void GLAPIENTRY
_mesa_DispatchComputeIndirect_no_error(GLintptr indirect)383*61046927SAndroid Build Coastguard Worker _mesa_DispatchComputeIndirect_no_error(GLintptr indirect)
384*61046927SAndroid Build Coastguard Worker {
385*61046927SAndroid Build Coastguard Worker    dispatch_compute_indirect(indirect, true);
386*61046927SAndroid Build Coastguard Worker }
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker extern void GLAPIENTRY
_mesa_DispatchComputeIndirect(GLintptr indirect)389*61046927SAndroid Build Coastguard Worker _mesa_DispatchComputeIndirect(GLintptr indirect)
390*61046927SAndroid Build Coastguard Worker {
391*61046927SAndroid Build Coastguard Worker    dispatch_compute_indirect(indirect, false);
392*61046927SAndroid Build Coastguard Worker }
393*61046927SAndroid Build Coastguard Worker 
394*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
dispatch_compute_group_size(GLuint num_groups_x,GLuint num_groups_y,GLuint num_groups_z,GLuint group_size_x,GLuint group_size_y,GLuint group_size_z,bool no_error)395*61046927SAndroid Build Coastguard Worker dispatch_compute_group_size(GLuint num_groups_x, GLuint num_groups_y,
396*61046927SAndroid Build Coastguard Worker                             GLuint num_groups_z, GLuint group_size_x,
397*61046927SAndroid Build Coastguard Worker                             GLuint group_size_y, GLuint group_size_z,
398*61046927SAndroid Build Coastguard Worker                             bool no_error)
399*61046927SAndroid Build Coastguard Worker {
400*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
401*61046927SAndroid Build Coastguard Worker    FLUSH_VERTICES(ctx, 0, 0);
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
404*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx,
405*61046927SAndroid Build Coastguard Worker                   "glDispatchComputeGroupSizeARB(%d, %d, %d, %d, %d, %d)\n",
406*61046927SAndroid Build Coastguard Worker                   num_groups_x, num_groups_y, num_groups_z,
407*61046927SAndroid Build Coastguard Worker                   group_size_x, group_size_y, group_size_z);
408*61046927SAndroid Build Coastguard Worker 
409*61046927SAndroid Build Coastguard Worker    struct pipe_grid_info info = { 0 };
410*61046927SAndroid Build Coastguard Worker    info.grid[0] = num_groups_x;
411*61046927SAndroid Build Coastguard Worker    info.grid[1] = num_groups_y;
412*61046927SAndroid Build Coastguard Worker    info.grid[2] = num_groups_z;
413*61046927SAndroid Build Coastguard Worker 
414*61046927SAndroid Build Coastguard Worker    info.block[0] = group_size_x;
415*61046927SAndroid Build Coastguard Worker    info.block[1] = group_size_y;
416*61046927SAndroid Build Coastguard Worker    info.block[2] = group_size_z;
417*61046927SAndroid Build Coastguard Worker 
418*61046927SAndroid Build Coastguard Worker    if (!no_error &&
419*61046927SAndroid Build Coastguard Worker        !validate_DispatchComputeGroupSizeARB(ctx, &info))
420*61046927SAndroid Build Coastguard Worker       return;
421*61046927SAndroid Build Coastguard Worker 
422*61046927SAndroid Build Coastguard Worker    if (num_groups_x == 0u || num_groups_y == 0u || num_groups_z == 0u)
423*61046927SAndroid Build Coastguard Worker        return;
424*61046927SAndroid Build Coastguard Worker 
425*61046927SAndroid Build Coastguard Worker    prepare_compute(ctx);
426*61046927SAndroid Build Coastguard Worker    ctx->pipe->launch_grid(ctx->pipe, &info);
427*61046927SAndroid Build Coastguard Worker 
428*61046927SAndroid Build Coastguard Worker    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
429*61046927SAndroid Build Coastguard Worker       _mesa_flush(ctx);
430*61046927SAndroid Build Coastguard Worker }
431*61046927SAndroid Build Coastguard Worker 
432*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_DispatchComputeGroupSizeARB_no_error(GLuint num_groups_x,GLuint num_groups_y,GLuint num_groups_z,GLuint group_size_x,GLuint group_size_y,GLuint group_size_z)433*61046927SAndroid Build Coastguard Worker _mesa_DispatchComputeGroupSizeARB_no_error(GLuint num_groups_x,
434*61046927SAndroid Build Coastguard Worker                                            GLuint num_groups_y,
435*61046927SAndroid Build Coastguard Worker                                            GLuint num_groups_z,
436*61046927SAndroid Build Coastguard Worker                                            GLuint group_size_x,
437*61046927SAndroid Build Coastguard Worker                                            GLuint group_size_y,
438*61046927SAndroid Build Coastguard Worker                                            GLuint group_size_z)
439*61046927SAndroid Build Coastguard Worker {
440*61046927SAndroid Build Coastguard Worker    dispatch_compute_group_size(num_groups_x, num_groups_y, num_groups_z,
441*61046927SAndroid Build Coastguard Worker                                group_size_x, group_size_y, group_size_z,
442*61046927SAndroid Build Coastguard Worker                                true);
443*61046927SAndroid Build Coastguard Worker }
444*61046927SAndroid Build Coastguard Worker 
445*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_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)446*61046927SAndroid Build Coastguard Worker _mesa_DispatchComputeGroupSizeARB(GLuint num_groups_x, GLuint num_groups_y,
447*61046927SAndroid Build Coastguard Worker                                   GLuint num_groups_z, GLuint group_size_x,
448*61046927SAndroid Build Coastguard Worker                                   GLuint group_size_y, GLuint group_size_z)
449*61046927SAndroid Build Coastguard Worker {
450*61046927SAndroid Build Coastguard Worker    dispatch_compute_group_size(num_groups_x, num_groups_y, num_groups_z,
451*61046927SAndroid Build Coastguard Worker                                group_size_x, group_size_y, group_size_z,
452*61046927SAndroid Build Coastguard Worker                                false);
453*61046927SAndroid Build Coastguard Worker }
454