2 * Copyright © 2014 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 #include "bufferobj.h"
30 check_valid_to_compute(struct gl_context
*ctx
, const char *function
)
32 if (!_mesa_has_compute_shaders(ctx
)) {
33 _mesa_error(ctx
, GL_INVALID_OPERATION
,
34 "unsupported function (%s) called",
39 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
41 * "An INVALID_OPERATION error is generated if there is no active program
42 * for the compute shader stage."
44 if (ctx
->_Shader
->CurrentProgram
[MESA_SHADER_COMPUTE
] == NULL
) {
45 _mesa_error(ctx
, GL_INVALID_OPERATION
,
46 "%s(no active compute shader)",
55 validate_DispatchCompute(struct gl_context
*ctx
, const GLuint
*num_groups
)
57 if (!check_valid_to_compute(ctx
, "glDispatchCompute"))
60 for (int i
= 0; i
< 3; i
++) {
61 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
63 * "An INVALID_VALUE error is generated if any of num_groups_x,
64 * num_groups_y and num_groups_z are greater than or equal to the
65 * maximum work group count for the corresponding dimension."
67 * However, the "or equal to" portions appears to be a specification
68 * bug. In all other areas, the specification appears to indicate that
69 * the number of workgroups can match the MAX_COMPUTE_WORK_GROUP_COUNT
70 * value. For example, under DispatchComputeIndirect:
72 * "If any of num_groups_x, num_groups_y or num_groups_z is greater than
73 * the value of MAX_COMPUTE_WORK_GROUP_COUNT for the corresponding
74 * dimension then the results are undefined."
76 * Additionally, the OpenGLES 3.1 specification does not contain "or
77 * equal to" as an error condition.
79 if (num_groups
[i
] > ctx
->Const
.MaxComputeWorkGroupCount
[i
]) {
80 _mesa_error(ctx
, GL_INVALID_VALUE
,
81 "glDispatchCompute(num_groups_%c)", 'x' + i
);
86 /* The ARB_compute_variable_group_size spec says:
88 * "An INVALID_OPERATION error is generated by DispatchCompute if the active
89 * program for the compute shader stage has a variable work group size."
91 struct gl_program
*prog
= ctx
->_Shader
->CurrentProgram
[MESA_SHADER_COMPUTE
];
92 if (prog
->info
.cs
.local_size_variable
) {
93 _mesa_error(ctx
, GL_INVALID_OPERATION
,
94 "glDispatchCompute(variable work group size forbidden)");
102 validate_DispatchComputeGroupSizeARB(struct gl_context
*ctx
,
103 const GLuint
*num_groups
,
104 const GLuint
*group_size
)
106 if (!check_valid_to_compute(ctx
, "glDispatchComputeGroupSizeARB"))
109 /* The ARB_compute_variable_group_size spec says:
111 * "An INVALID_OPERATION error is generated by
112 * DispatchComputeGroupSizeARB if the active program for the compute
113 * shader stage has a fixed work group size."
115 struct gl_program
*prog
= ctx
->_Shader
->CurrentProgram
[MESA_SHADER_COMPUTE
];
116 if (!prog
->info
.cs
.local_size_variable
) {
117 _mesa_error(ctx
, GL_INVALID_OPERATION
,
118 "glDispatchComputeGroupSizeARB(fixed work group size "
123 for (int i
= 0; i
< 3; i
++) {
124 /* The ARB_compute_variable_group_size spec says:
126 * "An INVALID_VALUE error is generated if any of num_groups_x,
127 * num_groups_y and num_groups_z are greater than or equal to the
128 * maximum work group count for the corresponding dimension."
130 if (num_groups
[i
] > ctx
->Const
.MaxComputeWorkGroupCount
[i
]) {
131 _mesa_error(ctx
, GL_INVALID_VALUE
,
132 "glDispatchComputeGroupSizeARB(num_groups_%c)", 'x' + i
);
136 /* The ARB_compute_variable_group_size spec says:
138 * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if
139 * any of <group_size_x>, <group_size_y>, or <group_size_z> is less than
140 * or equal to zero or greater than the maximum local work group size
141 * for compute shaders with variable group size
142 * (MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB) in the corresponding
145 * However, the "less than" is a spec bug because they are declared as
148 if (group_size
[i
] == 0 ||
149 group_size
[i
] > ctx
->Const
.MaxComputeVariableGroupSize
[i
]) {
150 _mesa_error(ctx
, GL_INVALID_VALUE
,
151 "glDispatchComputeGroupSizeARB(group_size_%c)", 'x' + i
);
156 /* The ARB_compute_variable_group_size spec says:
158 * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if
159 * the product of <group_size_x>, <group_size_y>, and <group_size_z> exceeds
160 * the implementation-dependent maximum local work group invocation count
161 * for compute shaders with variable group size
162 * (MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB)."
164 uint64_t total_invocations
= group_size
[0] * group_size
[1];
165 if (total_invocations
<= UINT32_MAX
) {
166 /* Only bother multiplying the third value if total still fits in
167 * 32-bit, since MaxComputeVariableGroupInvocations is also 32-bit.
169 total_invocations
*= group_size
[2];
171 if (total_invocations
> ctx
->Const
.MaxComputeVariableGroupInvocations
) {
172 _mesa_error(ctx
, GL_INVALID_VALUE
,
173 "glDispatchComputeGroupSizeARB(product of local_sizes "
174 "exceeds MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB "
175 "(%u * %u * %u > %u))",
176 group_size
[0], group_size
[1], group_size
[2],
177 ctx
->Const
.MaxComputeVariableGroupInvocations
);
181 /* The NV_compute_shader_derivatives spec says:
183 * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if
184 * the active program for the compute shader stage has a compute shader
185 * using the "derivative_group_quadsNV" layout qualifier and
186 * <group_size_x> or <group_size_y> is not a multiple of two.
188 * An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if
189 * the active program for the compute shader stage has a compute shader
190 * using the "derivative_group_linearNV" layout qualifier and the product
191 * of <group_size_x>, <group_size_y>, and <group_size_z> is not a multiple
194 if (prog
->info
.cs
.derivative_group
== DERIVATIVE_GROUP_QUADS
&&
195 ((group_size
[0] & 1) || (group_size
[1] & 1))) {
196 _mesa_error(ctx
, GL_INVALID_VALUE
,
197 "glDispatchComputeGroupSizeARB(derivative_group_quadsNV "
198 "requires group_size_x (%d) and group_size_y (%d) to be "
199 "divisble by 2)", group_size
[0], group_size
[1]);
203 if (prog
->info
.cs
.derivative_group
== DERIVATIVE_GROUP_LINEAR
&&
204 total_invocations
& 3) {
205 _mesa_error(ctx
, GL_INVALID_VALUE
,
206 "glDispatchComputeGroupSizeARB(derivative_group_linearNV "
207 "requires product of group sizes (%"PRIu64
") to be divisible "
208 "by 4)", total_invocations
);
216 valid_dispatch_indirect(struct gl_context
*ctx
, GLintptr indirect
)
218 GLsizei size
= 3 * sizeof(GLuint
);
219 const uint64_t end
= (uint64_t) indirect
+ size
;
220 const char *name
= "glDispatchComputeIndirect";
222 if (!check_valid_to_compute(ctx
, name
))
225 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
227 * "An INVALID_VALUE error is generated if indirect is negative or is not a
230 if (indirect
& (sizeof(GLuint
) - 1)) {
231 _mesa_error(ctx
, GL_INVALID_VALUE
,
232 "%s(indirect is not aligned)", name
);
237 _mesa_error(ctx
, GL_INVALID_VALUE
,
238 "%s(indirect is less than zero)", name
);
242 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
244 * "An INVALID_OPERATION error is generated if no buffer is bound to the
245 * DRAW_INDIRECT_BUFFER binding, or if the command would source data
246 * beyond the end of the buffer object."
248 if (!ctx
->DispatchIndirectBuffer
) {
249 _mesa_error(ctx
, GL_INVALID_OPERATION
,
250 "%s: no buffer bound to DISPATCH_INDIRECT_BUFFER", name
);
254 if (_mesa_check_disallowed_mapping(ctx
->DispatchIndirectBuffer
)) {
255 _mesa_error(ctx
, GL_INVALID_OPERATION
,
256 "%s(DISPATCH_INDIRECT_BUFFER is mapped)", name
);
260 if (ctx
->DispatchIndirectBuffer
->Size
< end
) {
261 _mesa_error(ctx
, GL_INVALID_OPERATION
,
262 "%s(DISPATCH_INDIRECT_BUFFER too small)", name
);
266 /* The ARB_compute_variable_group_size spec says:
268 * "An INVALID_OPERATION error is generated if the active program for the
269 * compute shader stage has a variable work group size."
271 struct gl_program
*prog
= ctx
->_Shader
->CurrentProgram
[MESA_SHADER_COMPUTE
];
272 if (prog
->info
.cs
.local_size_variable
) {
273 _mesa_error(ctx
, GL_INVALID_OPERATION
,
274 "%s(variable work group size forbidden)", name
);
281 static ALWAYS_INLINE
void
282 dispatch_compute(GLuint num_groups_x
, GLuint num_groups_y
,
283 GLuint num_groups_z
, bool no_error
)
285 GET_CURRENT_CONTEXT(ctx
);
286 const GLuint num_groups
[3] = { num_groups_x
, num_groups_y
, num_groups_z
};
288 FLUSH_VERTICES(ctx
, 0);
290 if (MESA_VERBOSE
& VERBOSE_API
)
291 _mesa_debug(ctx
, "glDispatchCompute(%d, %d, %d)\n",
292 num_groups_x
, num_groups_y
, num_groups_z
);
294 if (!no_error
&& !validate_DispatchCompute(ctx
, num_groups
))
297 if (num_groups_x
== 0u || num_groups_y
== 0u || num_groups_z
== 0u)
300 ctx
->Driver
.DispatchCompute(ctx
, num_groups
);
304 _mesa_DispatchCompute_no_error(GLuint num_groups_x
, GLuint num_groups_y
,
307 dispatch_compute(num_groups_x
, num_groups_y
, num_groups_z
, true);
311 _mesa_DispatchCompute(GLuint num_groups_x
,
315 dispatch_compute(num_groups_x
, num_groups_y
, num_groups_z
, false);
318 static ALWAYS_INLINE
void
319 dispatch_compute_indirect(GLintptr indirect
, bool no_error
)
321 GET_CURRENT_CONTEXT(ctx
);
323 FLUSH_VERTICES(ctx
, 0);
325 if (MESA_VERBOSE
& VERBOSE_API
)
326 _mesa_debug(ctx
, "glDispatchComputeIndirect(%ld)\n", (long) indirect
);
328 if (!no_error
&& !valid_dispatch_indirect(ctx
, indirect
))
331 ctx
->Driver
.DispatchComputeIndirect(ctx
, indirect
);
334 extern void GLAPIENTRY
335 _mesa_DispatchComputeIndirect_no_error(GLintptr indirect
)
337 dispatch_compute_indirect(indirect
, true);
340 extern void GLAPIENTRY
341 _mesa_DispatchComputeIndirect(GLintptr indirect
)
343 dispatch_compute_indirect(indirect
, false);
346 static ALWAYS_INLINE
void
347 dispatch_compute_group_size(GLuint num_groups_x
, GLuint num_groups_y
,
348 GLuint num_groups_z
, GLuint group_size_x
,
349 GLuint group_size_y
, GLuint group_size_z
,
352 GET_CURRENT_CONTEXT(ctx
);
353 const GLuint num_groups
[3] = { num_groups_x
, num_groups_y
, num_groups_z
};
354 const GLuint group_size
[3] = { group_size_x
, group_size_y
, group_size_z
};
356 FLUSH_VERTICES(ctx
, 0);
358 if (MESA_VERBOSE
& VERBOSE_API
)
360 "glDispatchComputeGroupSizeARB(%d, %d, %d, %d, %d, %d)\n",
361 num_groups_x
, num_groups_y
, num_groups_z
,
362 group_size_x
, group_size_y
, group_size_z
);
365 !validate_DispatchComputeGroupSizeARB(ctx
, num_groups
, group_size
))
368 if (num_groups_x
== 0u || num_groups_y
== 0u || num_groups_z
== 0u)
371 ctx
->Driver
.DispatchComputeGroupSize(ctx
, num_groups
, group_size
);
375 _mesa_DispatchComputeGroupSizeARB_no_error(GLuint num_groups_x
,
382 dispatch_compute_group_size(num_groups_x
, num_groups_y
, num_groups_z
,
383 group_size_x
, group_size_y
, group_size_z
,
388 _mesa_DispatchComputeGroupSizeARB(GLuint num_groups_x
, GLuint num_groups_y
,
389 GLuint num_groups_z
, GLuint group_size_x
,
390 GLuint group_size_y
, GLuint group_size_z
)
392 dispatch_compute_group_size(num_groups_x
, num_groups_y
, num_groups_z
,
393 group_size_x
, group_size_y
, group_size_z
,