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