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 GLuint total_invocations
= 1;
108 if (!check_valid_to_compute(ctx
, "glDispatchComputeGroupSizeARB"))
111 /* The ARB_compute_variable_group_size spec says:
113 * "An INVALID_OPERATION error is generated by
114 * DispatchComputeGroupSizeARB if the active program for the compute
115 * shader stage has a fixed work group size."
117 struct gl_program
*prog
= ctx
->_Shader
->CurrentProgram
[MESA_SHADER_COMPUTE
];
118 if (!prog
->info
.cs
.local_size_variable
) {
119 _mesa_error(ctx
, GL_INVALID_OPERATION
,
120 "glDispatchComputeGroupSizeARB(fixed work group size "
125 for (int i
= 0; i
< 3; i
++) {
126 /* The ARB_compute_variable_group_size spec says:
128 * "An INVALID_VALUE error is generated if any of num_groups_x,
129 * num_groups_y and num_groups_z are greater than or equal to the
130 * maximum work group count for the corresponding dimension."
132 if (num_groups
[i
] > ctx
->Const
.MaxComputeWorkGroupCount
[i
]) {
133 _mesa_error(ctx
, GL_INVALID_VALUE
,
134 "glDispatchComputeGroupSizeARB(num_groups_%c)", 'x' + i
);
138 /* The ARB_compute_variable_group_size spec says:
140 * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if
141 * any of <group_size_x>, <group_size_y>, or <group_size_z> is less than
142 * or equal to zero or greater than the maximum local work group size
143 * for compute shaders with variable group size
144 * (MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB) in the corresponding
147 * However, the "less than" is a spec bug because they are declared as
150 if (group_size
[i
] == 0 ||
151 group_size
[i
] > ctx
->Const
.MaxComputeVariableGroupSize
[i
]) {
152 _mesa_error(ctx
, GL_INVALID_VALUE
,
153 "glDispatchComputeGroupSizeARB(group_size_%c)", 'x' + i
);
157 total_invocations
*= group_size
[i
];
160 /* The ARB_compute_variable_group_size spec says:
162 * "An INVALID_VALUE error is generated by DispatchComputeGroupSizeARB if
163 * the product of <group_size_x>, <group_size_y>, and <group_size_z> exceeds
164 * the implementation-dependent maximum local work group invocation count
165 * for compute shaders with variable group size
166 * (MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB)."
168 if (total_invocations
> ctx
->Const
.MaxComputeVariableGroupInvocations
) {
169 _mesa_error(ctx
, GL_INVALID_VALUE
,
170 "glDispatchComputeGroupSizeARB(product of local_sizes "
171 "exceeds MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB "
172 "(%d > %d))", total_invocations
,
173 ctx
->Const
.MaxComputeVariableGroupInvocations
);
181 valid_dispatch_indirect(struct gl_context
*ctx
, GLintptr indirect
)
183 GLsizei size
= 3 * sizeof(GLuint
);
184 const uint64_t end
= (uint64_t) indirect
+ size
;
185 const char *name
= "glDispatchComputeIndirect";
187 if (!check_valid_to_compute(ctx
, name
))
190 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
192 * "An INVALID_VALUE error is generated if indirect is negative or is not a
195 if (indirect
& (sizeof(GLuint
) - 1)) {
196 _mesa_error(ctx
, GL_INVALID_VALUE
,
197 "%s(indirect is not aligned)", name
);
202 _mesa_error(ctx
, GL_INVALID_VALUE
,
203 "%s(indirect is less than zero)", name
);
207 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
209 * "An INVALID_OPERATION error is generated if no buffer is bound to the
210 * DRAW_INDIRECT_BUFFER binding, or if the command would source data
211 * beyond the end of the buffer object."
213 if (!_mesa_is_bufferobj(ctx
->DispatchIndirectBuffer
)) {
214 _mesa_error(ctx
, GL_INVALID_OPERATION
,
215 "%s: no buffer bound to DISPATCH_INDIRECT_BUFFER", name
);
219 if (_mesa_check_disallowed_mapping(ctx
->DispatchIndirectBuffer
)) {
220 _mesa_error(ctx
, GL_INVALID_OPERATION
,
221 "%s(DISPATCH_INDIRECT_BUFFER is mapped)", name
);
225 if (ctx
->DispatchIndirectBuffer
->Size
< end
) {
226 _mesa_error(ctx
, GL_INVALID_OPERATION
,
227 "%s(DISPATCH_INDIRECT_BUFFER too small)", name
);
231 /* The ARB_compute_variable_group_size spec says:
233 * "An INVALID_OPERATION error is generated if the active program for the
234 * compute shader stage has a variable work group size."
236 struct gl_program
*prog
= ctx
->_Shader
->CurrentProgram
[MESA_SHADER_COMPUTE
];
237 if (prog
->info
.cs
.local_size_variable
) {
238 _mesa_error(ctx
, GL_INVALID_OPERATION
,
239 "%s(variable work group size forbidden)", name
);
246 static ALWAYS_INLINE
void
247 dispatch_compute(GLuint num_groups_x
, GLuint num_groups_y
,
248 GLuint num_groups_z
, bool no_error
)
250 GET_CURRENT_CONTEXT(ctx
);
251 const GLuint num_groups
[3] = { num_groups_x
, num_groups_y
, num_groups_z
};
253 FLUSH_CURRENT(ctx
, 0);
255 if (MESA_VERBOSE
& VERBOSE_API
)
256 _mesa_debug(ctx
, "glDispatchCompute(%d, %d, %d)\n",
257 num_groups_x
, num_groups_y
, num_groups_z
);
259 if (!no_error
&& !validate_DispatchCompute(ctx
, num_groups
))
262 if (num_groups_x
== 0u || num_groups_y
== 0u || num_groups_z
== 0u)
265 ctx
->Driver
.DispatchCompute(ctx
, num_groups
);
269 _mesa_DispatchCompute_no_error(GLuint num_groups_x
, GLuint num_groups_y
,
272 dispatch_compute(num_groups_x
, num_groups_y
, num_groups_z
, true);
276 _mesa_DispatchCompute(GLuint num_groups_x
,
280 dispatch_compute(num_groups_x
, num_groups_y
, num_groups_z
, false);
283 static ALWAYS_INLINE
void
284 dispatch_compute_indirect(GLintptr indirect
, bool no_error
)
286 GET_CURRENT_CONTEXT(ctx
);
288 FLUSH_CURRENT(ctx
, 0);
290 if (MESA_VERBOSE
& VERBOSE_API
)
291 _mesa_debug(ctx
, "glDispatchComputeIndirect(%ld)\n", (long) indirect
);
293 if (!no_error
&& !valid_dispatch_indirect(ctx
, indirect
))
296 ctx
->Driver
.DispatchComputeIndirect(ctx
, indirect
);
299 extern void GLAPIENTRY
300 _mesa_DispatchComputeIndirect_no_error(GLintptr indirect
)
302 dispatch_compute_indirect(indirect
, true);
305 extern void GLAPIENTRY
306 _mesa_DispatchComputeIndirect(GLintptr indirect
)
308 dispatch_compute_indirect(indirect
, false);
311 static ALWAYS_INLINE
void
312 dispatch_compute_group_size(GLuint num_groups_x
, GLuint num_groups_y
,
313 GLuint num_groups_z
, GLuint group_size_x
,
314 GLuint group_size_y
, GLuint group_size_z
,
317 GET_CURRENT_CONTEXT(ctx
);
318 const GLuint num_groups
[3] = { num_groups_x
, num_groups_y
, num_groups_z
};
319 const GLuint group_size
[3] = { group_size_x
, group_size_y
, group_size_z
};
321 FLUSH_CURRENT(ctx
, 0);
323 if (MESA_VERBOSE
& VERBOSE_API
)
325 "glDispatchComputeGroupSizeARB(%d, %d, %d, %d, %d, %d)\n",
326 num_groups_x
, num_groups_y
, num_groups_z
,
327 group_size_x
, group_size_y
, group_size_z
);
330 !validate_DispatchComputeGroupSizeARB(ctx
, num_groups
, group_size
))
333 if (num_groups_x
== 0u || num_groups_y
== 0u || num_groups_z
== 0u)
336 ctx
->Driver
.DispatchComputeGroupSize(ctx
, num_groups
, group_size
);
340 _mesa_DispatchComputeGroupSizeARB_no_error(GLuint num_groups_x
,
347 dispatch_compute_group_size(num_groups_x
, num_groups_y
, num_groups_z
,
348 group_size_x
, group_size_y
, group_size_z
,
353 _mesa_DispatchComputeGroupSizeARB(GLuint num_groups_x
, GLuint num_groups_y
,
354 GLuint num_groups_z
, GLuint group_size_x
,
355 GLuint group_size_y
, GLuint group_size_z
)
357 dispatch_compute_group_size(num_groups_x
, num_groups_y
, num_groups_z
,
358 group_size_x
, group_size_y
, group_size_z
,