1/* 2 * Copyright © 2018 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 DEALINGS 21 * IN THE SOFTWARE. 22 * 23 */ 24#include "main/mtypes.h" 25#include "glsl_types.h" 26#include "linker_util.h" 27#include "util/bitscan.h" 28#include "util/set.h" 29#include "ir_uniform.h" /* for gl_uniform_storage */ 30 31/* Utility methods shared between the GLSL IR and the NIR */ 32 33/* From the OpenGL 4.6 specification, 7.3.1.1 Naming Active Resources: 34 * 35 * "For an active shader storage block member declared as an array of an 36 * aggregate type, an entry will be generated only for the first array 37 * element, regardless of its type. Such block members are referred to as 38 * top-level arrays. If the block member is an aggregate type, the 39 * enumeration rules are then applied recursively." 40 */ 41bool 42link_util_should_add_buffer_variable(struct gl_shader_program *prog, 43 struct gl_uniform_storage *uniform, 44 int top_level_array_base_offset, 45 int top_level_array_size_in_bytes, 46 int second_element_offset, 47 int block_index) 48{ 49 /* If the uniform is not a shader storage buffer or is not an array return 50 * true. 51 */ 52 if (!uniform->is_shader_storage || top_level_array_size_in_bytes == 0) 53 return true; 54 55 int after_top_level_array = top_level_array_base_offset + 56 top_level_array_size_in_bytes; 57 58 /* Check for a new block, or that we are not dealing with array elements of 59 * a top member array other than the first element. 60 */ 61 if (block_index != uniform->block_index || 62 uniform->offset >= after_top_level_array || 63 uniform->offset < second_element_offset) { 64 return true; 65 } 66 67 return false; 68} 69 70bool 71link_util_add_program_resource(struct gl_shader_program *prog, 72 struct set *resource_set, 73 GLenum type, const void *data, uint8_t stages) 74{ 75 assert(data); 76 77 /* If resource already exists, do not add it again. */ 78 if (_mesa_set_search(resource_set, data)) 79 return true; 80 81 prog->data->ProgramResourceList = 82 reralloc(prog->data, 83 prog->data->ProgramResourceList, 84 gl_program_resource, 85 prog->data->NumProgramResourceList + 1); 86 87 if (!prog->data->ProgramResourceList) { 88 linker_error(prog, "Out of memory during linking.\n"); 89 return false; 90 } 91 92 struct gl_program_resource *res = 93 &prog->data->ProgramResourceList[prog->data->NumProgramResourceList]; 94 95 res->Type = type; 96 res->Data = data; 97 res->StageReferences = stages; 98 99 prog->data->NumProgramResourceList++; 100 101 _mesa_set_add(resource_set, data); 102 103 return true; 104} 105 106/** 107 * Search through the list of empty blocks to find one that fits the current 108 * uniform. 109 */ 110int 111link_util_find_empty_block(struct gl_shader_program *prog, 112 struct gl_uniform_storage *uniform) 113{ 114 const unsigned entries = MAX2(1, uniform->array_elements); 115 116 foreach_list_typed(struct empty_uniform_block, block, link, 117 &prog->EmptyUniformLocations) { 118 /* Found a block with enough slots to fit the uniform */ 119 if (block->slots == entries) { 120 unsigned start = block->start; 121 exec_node_remove(&block->link); 122 ralloc_free(block); 123 124 return start; 125 /* Found a block with more slots than needed. It can still be used. */ 126 } else if (block->slots > entries) { 127 unsigned start = block->start; 128 block->start += entries; 129 block->slots -= entries; 130 131 return start; 132 } 133 } 134 135 return -1; 136} 137 138void 139link_util_update_empty_uniform_locations(struct gl_shader_program *prog) 140{ 141 struct empty_uniform_block *current_block = NULL; 142 143 for (unsigned i = 0; i < prog->NumUniformRemapTable; i++) { 144 /* We found empty space in UniformRemapTable. */ 145 if (prog->UniformRemapTable[i] == NULL) { 146 /* We've found the beginning of a new continous block of empty slots */ 147 if (!current_block || current_block->start + current_block->slots != i) { 148 current_block = rzalloc(prog, struct empty_uniform_block); 149 current_block->start = i; 150 exec_list_push_tail(&prog->EmptyUniformLocations, 151 ¤t_block->link); 152 } 153 154 /* The current block continues, so we simply increment its slots */ 155 current_block->slots++; 156 } 157 } 158} 159 160void 161link_util_check_subroutine_resources(struct gl_shader_program *prog) 162{ 163 unsigned mask = prog->data->linked_stages; 164 while (mask) { 165 const int i = u_bit_scan(&mask); 166 struct gl_program *p = prog->_LinkedShaders[i]->Program; 167 168 if (p->sh.NumSubroutineUniformRemapTable > MAX_SUBROUTINE_UNIFORM_LOCATIONS) { 169 linker_error(prog, "Too many %s shader subroutine uniforms\n", 170 _mesa_shader_stage_to_string(i)); 171 } 172 } 173} 174 175/** 176 * Validate uniform resources used by a program versus the implementation limits 177 */ 178void 179link_util_check_uniform_resources(struct gl_context *ctx, 180 struct gl_shader_program *prog) 181{ 182 unsigned total_uniform_blocks = 0; 183 unsigned total_shader_storage_blocks = 0; 184 185 for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { 186 struct gl_linked_shader *sh = prog->_LinkedShaders[i]; 187 188 if (sh == NULL) 189 continue; 190 191 if (sh->num_uniform_components > 192 ctx->Const.Program[i].MaxUniformComponents) { 193 if (ctx->Const.GLSLSkipStrictMaxUniformLimitCheck) { 194 linker_warning(prog, "Too many %s shader default uniform block " 195 "components, but the driver will try to optimize " 196 "them out; this is non-portable out-of-spec " 197 "behavior\n", 198 _mesa_shader_stage_to_string(i)); 199 } else { 200 linker_error(prog, "Too many %s shader default uniform block " 201 "components\n", 202 _mesa_shader_stage_to_string(i)); 203 } 204 } 205 206 if (sh->num_combined_uniform_components > 207 ctx->Const.Program[i].MaxCombinedUniformComponents) { 208 if (ctx->Const.GLSLSkipStrictMaxUniformLimitCheck) { 209 linker_warning(prog, "Too many %s shader uniform components, " 210 "but the driver will try to optimize them out; " 211 "this is non-portable out-of-spec behavior\n", 212 _mesa_shader_stage_to_string(i)); 213 } else { 214 linker_error(prog, "Too many %s shader uniform components\n", 215 _mesa_shader_stage_to_string(i)); 216 } 217 } 218 219 total_shader_storage_blocks += sh->Program->info.num_ssbos; 220 total_uniform_blocks += sh->Program->info.num_ubos; 221 } 222 223 if (total_uniform_blocks > ctx->Const.MaxCombinedUniformBlocks) { 224 linker_error(prog, "Too many combined uniform blocks (%d/%d)\n", 225 total_uniform_blocks, ctx->Const.MaxCombinedUniformBlocks); 226 } 227 228 if (total_shader_storage_blocks > ctx->Const.MaxCombinedShaderStorageBlocks) { 229 linker_error(prog, "Too many combined shader storage blocks (%d/%d)\n", 230 total_shader_storage_blocks, 231 ctx->Const.MaxCombinedShaderStorageBlocks); 232 } 233 234 for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) { 235 if (prog->data->UniformBlocks[i].UniformBufferSize > 236 ctx->Const.MaxUniformBlockSize) { 237 linker_error(prog, "Uniform block %s too big (%d/%d)\n", 238 prog->data->UniformBlocks[i].Name, 239 prog->data->UniformBlocks[i].UniformBufferSize, 240 ctx->Const.MaxUniformBlockSize); 241 } 242 } 243 244 for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) { 245 if (prog->data->ShaderStorageBlocks[i].UniformBufferSize > 246 ctx->Const.MaxShaderStorageBlockSize) { 247 linker_error(prog, "Shader storage block %s too big (%d/%d)\n", 248 prog->data->ShaderStorageBlocks[i].Name, 249 prog->data->ShaderStorageBlocks[i].UniformBufferSize, 250 ctx->Const.MaxShaderStorageBlockSize); 251 } 252 } 253} 254 255void 256link_util_calculate_subroutine_compat(struct gl_shader_program *prog) 257{ 258 unsigned mask = prog->data->linked_stages; 259 while (mask) { 260 const int i = u_bit_scan(&mask); 261 struct gl_program *p = prog->_LinkedShaders[i]->Program; 262 263 for (unsigned j = 0; j < p->sh.NumSubroutineUniformRemapTable; j++) { 264 if (p->sh.SubroutineUniformRemapTable[j] == INACTIVE_UNIFORM_EXPLICIT_LOCATION) 265 continue; 266 267 struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[j]; 268 269 if (!uni) 270 continue; 271 272 int count = 0; 273 if (p->sh.NumSubroutineFunctions == 0) { 274 linker_error(prog, "subroutine uniform %s defined but no valid functions found\n", uni->type->name); 275 continue; 276 } 277 for (unsigned f = 0; f < p->sh.NumSubroutineFunctions; f++) { 278 struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[f]; 279 for (int k = 0; k < fn->num_compat_types; k++) { 280 if (fn->types[k] == uni->type) { 281 count++; 282 break; 283 } 284 } 285 } 286 uni->num_compatible_subroutines = count; 287 } 288 } 289} 290 291/** 292 * Recursive part of the public mark_array_elements_referenced function. 293 * 294 * The recursion occurs when an entire array-of- is accessed. See the 295 * implementation for more details. 296 * 297 * \param dr List of array_deref_range elements to be 298 * processed. 299 * \param count Number of array_deref_range elements to be 300 * processed. 301 * \param scale Current offset scale. 302 * \param linearized_index Current accumulated linearized array index. 303 */ 304void 305_mark_array_elements_referenced(const struct array_deref_range *dr, 306 unsigned count, unsigned scale, 307 unsigned linearized_index, 308 BITSET_WORD *bits) 309{ 310 /* Walk through the list of array dereferences in least- to 311 * most-significant order. Along the way, accumulate the current 312 * linearized offset and the scale factor for each array-of-. 313 */ 314 for (unsigned i = 0; i < count; i++) { 315 if (dr[i].index < dr[i].size) { 316 linearized_index += dr[i].index * scale; 317 scale *= dr[i].size; 318 } else { 319 /* For each element in the current array, update the count and 320 * offset, then recurse to process the remaining arrays. 321 * 322 * There is some inefficency here if the last eBITSET_WORD *bitslement in the 323 * array_deref_range list specifies the entire array. In that case, 324 * the loop will make recursive calls with count == 0. In the call, 325 * all that will happen is the bit will be set. 326 */ 327 for (unsigned j = 0; j < dr[i].size; j++) { 328 _mark_array_elements_referenced(&dr[i + 1], 329 count - (i + 1), 330 scale * dr[i].size, 331 linearized_index + (j * scale), 332 bits); 333 } 334 335 return; 336 } 337 } 338 339 BITSET_SET(bits, linearized_index); 340} 341 342/** 343 * Mark a set of array elements as accessed. 344 * 345 * If every \c array_deref_range is for a single index, only a single 346 * element will be marked. If any \c array_deref_range is for an entire 347 * array-of-, then multiple elements will be marked. 348 * 349 * Items in the \c array_deref_range list appear in least- to 350 * most-significant order. This is the \b opposite order the indices 351 * appear in the GLSL shader text. An array access like 352 * 353 * x = y[1][i][3]; 354 * 355 * would appear as 356 * 357 * { { 3, n }, { m, m }, { 1, p } } 358 * 359 * where n, m, and p are the sizes of the arrays-of-arrays. 360 * 361 * The set of marked array elements can later be queried by 362 * \c ::is_linearized_index_referenced. 363 * 364 * \param dr List of array_deref_range elements to be processed. 365 * \param count Number of array_deref_range elements to be processed. 366 */ 367void 368link_util_mark_array_elements_referenced(const struct array_deref_range *dr, 369 unsigned count, unsigned array_depth, 370 BITSET_WORD *bits) 371{ 372 if (count != array_depth) 373 return; 374 375 _mark_array_elements_referenced(dr, count, 1, 0, bits); 376} 377