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
);
185 valid_dispatch_indirect(struct gl_context
*ctx
, GLintptr indirect
)
187 GLsizei size
= 3 * sizeof(GLuint
);
188 const uint64_t end
= (uint64_t) indirect
+ size
;
189 const char *name
= "glDispatchComputeIndirect";
191 if (!check_valid_to_compute(ctx
, name
))
194 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
196 * "An INVALID_VALUE error is generated if indirect is negative or is not a
199 if (indirect
& (sizeof(GLuint
) - 1)) {
200 _mesa_error(ctx
, GL_INVALID_VALUE
,
201 "%s(indirect is not aligned)", name
);
206 _mesa_error(ctx
, GL_INVALID_VALUE
,
207 "%s(indirect is less than zero)", name
);
211 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders:
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."
217 if (!_mesa_is_bufferobj(ctx
->DispatchIndirectBuffer
)) {
218 _mesa_error(ctx
, GL_INVALID_OPERATION
,
219 "%s: no buffer bound to DISPATCH_INDIRECT_BUFFER", name
);
223 if (_mesa_check_disallowed_mapping(ctx
->DispatchIndirectBuffer
)) {
224 _mesa_error(ctx
, GL_INVALID_OPERATION
,
225 "%s(DISPATCH_INDIRECT_BUFFER is mapped)", name
);
229 if (ctx
->DispatchIndirectBuffer
->Size
< end
) {
230 _mesa_error(ctx
, GL_INVALID_OPERATION
,
231 "%s(DISPATCH_INDIRECT_BUFFER too small)", name
);
235 /* The ARB_compute_variable_group_size spec says:
237 * "An INVALID_OPERATION error is generated if the active program for the
238 * compute shader stage has a variable work group size."
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
);
250 static ALWAYS_INLINE
void
251 dispatch_compute(GLuint num_groups_x
, GLuint num_groups_y
,
252 GLuint num_groups_z
, bool no_error
)
254 GET_CURRENT_CONTEXT(ctx
);
255 const GLuint num_groups
[3] = { num_groups_x
, num_groups_y
, num_groups_z
};
257 FLUSH_VERTICES(ctx
, 0);
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
);
263 if (!no_error
&& !validate_DispatchCompute(ctx
, num_groups
))
266 if (num_groups_x
== 0u || num_groups_y
== 0u || num_groups_z
== 0u)
269 ctx
->Driver
.DispatchCompute(ctx
, num_groups
);
273 _mesa_DispatchCompute_no_error(GLuint num_groups_x
, GLuint num_groups_y
,
276 dispatch_compute(num_groups_x
, num_groups_y
, num_groups_z
, true);
280 _mesa_DispatchCompute(GLuint num_groups_x
,
284 dispatch_compute(num_groups_x
, num_groups_y
, num_groups_z
, false);
287 static ALWAYS_INLINE
void
288 dispatch_compute_indirect(GLintptr indirect
, bool no_error
)
290 GET_CURRENT_CONTEXT(ctx
);
292 FLUSH_VERTICES(ctx
, 0);
294 if (MESA_VERBOSE
& VERBOSE_API
)
295 _mesa_debug(ctx
, "glDispatchComputeIndirect(%ld)\n", (long) indirect
);
297 if (!no_error
&& !valid_dispatch_indirect(ctx
, indirect
))
300 ctx
->Driver
.DispatchComputeIndirect(ctx
, indirect
);
303 extern void GLAPIENTRY
304 _mesa_DispatchComputeIndirect_no_error(GLintptr indirect
)
306 dispatch_compute_indirect(indirect
, true);
309 extern void GLAPIENTRY
310 _mesa_DispatchComputeIndirect(GLintptr indirect
)
312 dispatch_compute_indirect(indirect
, false);
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
,
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
};
325 FLUSH_VERTICES(ctx
, 0);
327 if (MESA_VERBOSE
& VERBOSE_API
)
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
);
334 !validate_DispatchComputeGroupSizeARB(ctx
, num_groups
, group_size
))
337 if (num_groups_x
== 0u || num_groups_y
== 0u || num_groups_z
== 0u)
340 ctx
->Driver
.DispatchComputeGroupSize(ctx
, num_groups
, group_size
);
344 _mesa_DispatchComputeGroupSizeARB_no_error(GLuint num_groups_x
,
351 dispatch_compute_group_size(num_groups_x
, num_groups_y
, num_groups_z
,
352 group_size_x
, group_size_y
, group_size_z
,
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
)
361 dispatch_compute_group_size(num_groups_x
, num_groups_y
, num_groups_z
,
362 group_size_x
, group_size_y
, group_size_z
,