glthread: rename marshal.h/c to glthread_marshal.h and glthread_shaderobj.c
[mesa.git] / src / mesa / main / compute.c
1 /*
2 * Copyright © 2014 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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.
22 */
23
24 #include "glheader.h"
25 #include "bufferobj.h"
26 #include "compute.h"
27 #include "context.h"
28
29 static bool
30 check_valid_to_compute(struct gl_context *ctx, const char *function)
31 {
32 if (!_mesa_has_compute_shaders(ctx)) {
33 _mesa_error(ctx, GL_INVALID_OPERATION,
34 "unsupported function (%s) called",
35 function);
36 return false;
37 }
38
39 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
40 *
41 * "An INVALID_OPERATION error is generated if there is no active program
42 * for the compute shader stage."
43 */
44 if (ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE] == NULL) {
45 _mesa_error(ctx, GL_INVALID_OPERATION,
46 "%s(no active compute shader)",
47 function);
48 return false;
49 }
50
51 return true;
52 }
53
54 static bool
55 validate_DispatchCompute(struct gl_context *ctx, const GLuint *num_groups)
56 {
57 if (!check_valid_to_compute(ctx, "glDispatchCompute"))
58 return GL_FALSE;
59
60 for (int i = 0; i < 3; i++) {
61 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
62 *
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."
66 *
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:
71 *
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."
75 *
76 * Additionally, the OpenGLES 3.1 specification does not contain "or
77 * equal to" as an error condition.
78 */
79 if (num_groups[i] > ctx->Const.MaxComputeWorkGroupCount[i]) {
80 _mesa_error(ctx, GL_INVALID_VALUE,
81 "glDispatchCompute(num_groups_%c)", 'x' + i);
82 return GL_FALSE;
83 }
84 }
85
86 /* The ARB_compute_variable_group_size spec says:
87 *
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."
90 */
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)");
95 return GL_FALSE;
96 }
97
98 return GL_TRUE;
99 }
100
101 static bool
102 validate_DispatchComputeGroupSizeARB(struct gl_context *ctx,
103 const GLuint *num_groups,
104 const GLuint *group_size)
105 {
106 if (!check_valid_to_compute(ctx, "glDispatchComputeGroupSizeARB"))
107 return GL_FALSE;
108
109 /* The ARB_compute_variable_group_size spec says:
110 *
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."
114 */
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 "
119 "forbidden)");
120 return GL_FALSE;
121 }
122
123 for (int i = 0; i < 3; i++) {
124 /* The ARB_compute_variable_group_size spec says:
125 *
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."
129 */
130 if (num_groups[i] > ctx->Const.MaxComputeWorkGroupCount[i]) {
131 _mesa_error(ctx, GL_INVALID_VALUE,
132 "glDispatchComputeGroupSizeARB(num_groups_%c)", 'x' + i);
133 return GL_FALSE;
134 }
135
136 /* The ARB_compute_variable_group_size spec says:
137 *
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
143 * dimension."
144 *
145 * However, the "less than" is a spec bug because they are declared as
146 * unsigned integers.
147 */
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);
152 return GL_FALSE;
153 }
154 }
155
156 /* The ARB_compute_variable_group_size spec says:
157 *
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)."
163 */
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.
168 */
169 total_invocations *= group_size[2];
170 }
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);
178 return GL_FALSE;
179 }
180
181 return GL_TRUE;
182 }
183
184 static bool
185 valid_dispatch_indirect(struct gl_context *ctx, GLintptr indirect)
186 {
187 GLsizei size = 3 * sizeof(GLuint);
188 const uint64_t end = (uint64_t) indirect + size;
189 const char *name = "glDispatchComputeIndirect";
190
191 if (!check_valid_to_compute(ctx, name))
192 return GL_FALSE;
193
194 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
195 *
196 * "An INVALID_VALUE error is generated if indirect is negative or is not a
197 * multiple of four."
198 */
199 if (indirect & (sizeof(GLuint) - 1)) {
200 _mesa_error(ctx, GL_INVALID_VALUE,
201 "%s(indirect is not aligned)", name);
202 return GL_FALSE;
203 }
204
205 if (indirect < 0) {
206 _mesa_error(ctx, GL_INVALID_VALUE,
207 "%s(indirect is less than zero)", name);
208 return GL_FALSE;
209 }
210
211 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
212 *
213 * "An INVALID_OPERATION error is generated if no buffer is bound to the
214 * DRAW_INDIRECT_BUFFER binding, or if the command would source data
215 * beyond the end of the buffer object."
216 */
217 if (!_mesa_is_bufferobj(ctx->DispatchIndirectBuffer)) {
218 _mesa_error(ctx, GL_INVALID_OPERATION,
219 "%s: no buffer bound to DISPATCH_INDIRECT_BUFFER", name);
220 return GL_FALSE;
221 }
222
223 if (_mesa_check_disallowed_mapping(ctx->DispatchIndirectBuffer)) {
224 _mesa_error(ctx, GL_INVALID_OPERATION,
225 "%s(DISPATCH_INDIRECT_BUFFER is mapped)", name);
226 return GL_FALSE;
227 }
228
229 if (ctx->DispatchIndirectBuffer->Size < end) {
230 _mesa_error(ctx, GL_INVALID_OPERATION,
231 "%s(DISPATCH_INDIRECT_BUFFER too small)", name);
232 return GL_FALSE;
233 }
234
235 /* The ARB_compute_variable_group_size spec says:
236 *
237 * "An INVALID_OPERATION error is generated if the active program for the
238 * compute shader stage has a variable work group size."
239 */
240 struct gl_program *prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
241 if (prog->info.cs.local_size_variable) {
242 _mesa_error(ctx, GL_INVALID_OPERATION,
243 "%s(variable work group size forbidden)", name);
244 return GL_FALSE;
245 }
246
247 return GL_TRUE;
248 }
249
250 static ALWAYS_INLINE void
251 dispatch_compute(GLuint num_groups_x, GLuint num_groups_y,
252 GLuint num_groups_z, bool no_error)
253 {
254 GET_CURRENT_CONTEXT(ctx);
255 const GLuint num_groups[3] = { num_groups_x, num_groups_y, num_groups_z };
256
257 FLUSH_VERTICES(ctx, 0);
258
259 if (MESA_VERBOSE & VERBOSE_API)
260 _mesa_debug(ctx, "glDispatchCompute(%d, %d, %d)\n",
261 num_groups_x, num_groups_y, num_groups_z);
262
263 if (!no_error && !validate_DispatchCompute(ctx, num_groups))
264 return;
265
266 if (num_groups_x == 0u || num_groups_y == 0u || num_groups_z == 0u)
267 return;
268
269 ctx->Driver.DispatchCompute(ctx, num_groups);
270 }
271
272 void GLAPIENTRY
273 _mesa_DispatchCompute_no_error(GLuint num_groups_x, GLuint num_groups_y,
274 GLuint num_groups_z)
275 {
276 dispatch_compute(num_groups_x, num_groups_y, num_groups_z, true);
277 }
278
279 void GLAPIENTRY
280 _mesa_DispatchCompute(GLuint num_groups_x,
281 GLuint num_groups_y,
282 GLuint num_groups_z)
283 {
284 dispatch_compute(num_groups_x, num_groups_y, num_groups_z, false);
285 }
286
287 static ALWAYS_INLINE void
288 dispatch_compute_indirect(GLintptr indirect, bool no_error)
289 {
290 GET_CURRENT_CONTEXT(ctx);
291
292 FLUSH_VERTICES(ctx, 0);
293
294 if (MESA_VERBOSE & VERBOSE_API)
295 _mesa_debug(ctx, "glDispatchComputeIndirect(%ld)\n", (long) indirect);
296
297 if (!no_error && !valid_dispatch_indirect(ctx, indirect))
298 return;
299
300 ctx->Driver.DispatchComputeIndirect(ctx, indirect);
301 }
302
303 extern void GLAPIENTRY
304 _mesa_DispatchComputeIndirect_no_error(GLintptr indirect)
305 {
306 dispatch_compute_indirect(indirect, true);
307 }
308
309 extern void GLAPIENTRY
310 _mesa_DispatchComputeIndirect(GLintptr indirect)
311 {
312 dispatch_compute_indirect(indirect, false);
313 }
314
315 static ALWAYS_INLINE void
316 dispatch_compute_group_size(GLuint num_groups_x, GLuint num_groups_y,
317 GLuint num_groups_z, GLuint group_size_x,
318 GLuint group_size_y, GLuint group_size_z,
319 bool no_error)
320 {
321 GET_CURRENT_CONTEXT(ctx);
322 const GLuint num_groups[3] = { num_groups_x, num_groups_y, num_groups_z };
323 const GLuint group_size[3] = { group_size_x, group_size_y, group_size_z };
324
325 FLUSH_VERTICES(ctx, 0);
326
327 if (MESA_VERBOSE & VERBOSE_API)
328 _mesa_debug(ctx,
329 "glDispatchComputeGroupSizeARB(%d, %d, %d, %d, %d, %d)\n",
330 num_groups_x, num_groups_y, num_groups_z,
331 group_size_x, group_size_y, group_size_z);
332
333 if (!no_error &&
334 !validate_DispatchComputeGroupSizeARB(ctx, num_groups, group_size))
335 return;
336
337 if (num_groups_x == 0u || num_groups_y == 0u || num_groups_z == 0u)
338 return;
339
340 ctx->Driver.DispatchComputeGroupSize(ctx, num_groups, group_size);
341 }
342
343 void GLAPIENTRY
344 _mesa_DispatchComputeGroupSizeARB_no_error(GLuint num_groups_x,
345 GLuint num_groups_y,
346 GLuint num_groups_z,
347 GLuint group_size_x,
348 GLuint group_size_y,
349 GLuint group_size_z)
350 {
351 dispatch_compute_group_size(num_groups_x, num_groups_y, num_groups_z,
352 group_size_x, group_size_y, group_size_z,
353 true);
354 }
355
356 void GLAPIENTRY
357 _mesa_DispatchComputeGroupSizeARB(GLuint num_groups_x, GLuint num_groups_y,
358 GLuint num_groups_z, GLuint group_size_x,
359 GLuint group_size_y, GLuint group_size_z)
360 {
361 dispatch_compute_group_size(num_groups_x, num_groups_y, num_groups_z,
362 group_size_x, group_size_y, group_size_z,
363 false);
364 }