1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2018 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "nir.h" 25bf215546Sopenharmony_ci#include "GL/gl.h" 26bf215546Sopenharmony_ci#include "linker_util.h" 27bf215546Sopenharmony_ci#include "gl_nir_linker.h" 28bf215546Sopenharmony_ci#include "compiler/glsl/ir_uniform.h" /* for gl_uniform_storage */ 29bf215546Sopenharmony_ci#include "main/consts_exts.h" 30bf215546Sopenharmony_ci#include "main/shader_types.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci/** 33bf215546Sopenharmony_ci * This file do the common link for GLSL atomic counter uniforms, using NIR, 34bf215546Sopenharmony_ci * instead of IR as the counter-part glsl/link_uniforms.cpp 35bf215546Sopenharmony_ci */ 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cistruct active_atomic_counter_uniform { 38bf215546Sopenharmony_ci unsigned loc; 39bf215546Sopenharmony_ci nir_variable *var; 40bf215546Sopenharmony_ci}; 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_cistruct active_atomic_buffer { 43bf215546Sopenharmony_ci struct active_atomic_counter_uniform *uniforms; 44bf215546Sopenharmony_ci unsigned num_uniforms; 45bf215546Sopenharmony_ci unsigned uniform_buffer_size; 46bf215546Sopenharmony_ci unsigned stage_counter_references[MESA_SHADER_STAGES]; 47bf215546Sopenharmony_ci unsigned size; 48bf215546Sopenharmony_ci}; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_cistatic void 51bf215546Sopenharmony_ciadd_atomic_counter(const void *ctx, 52bf215546Sopenharmony_ci struct active_atomic_buffer *buffer, 53bf215546Sopenharmony_ci unsigned uniform_loc, 54bf215546Sopenharmony_ci nir_variable *var) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci if (buffer->num_uniforms >= buffer->uniform_buffer_size) { 57bf215546Sopenharmony_ci if (buffer->uniform_buffer_size == 0) 58bf215546Sopenharmony_ci buffer->uniform_buffer_size = 1; 59bf215546Sopenharmony_ci else 60bf215546Sopenharmony_ci buffer->uniform_buffer_size *= 2; 61bf215546Sopenharmony_ci buffer->uniforms = reralloc(ctx, 62bf215546Sopenharmony_ci buffer->uniforms, 63bf215546Sopenharmony_ci struct active_atomic_counter_uniform, 64bf215546Sopenharmony_ci buffer->uniform_buffer_size); 65bf215546Sopenharmony_ci } 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci struct active_atomic_counter_uniform *uniform = 68bf215546Sopenharmony_ci buffer->uniforms + buffer->num_uniforms; 69bf215546Sopenharmony_ci uniform->loc = uniform_loc; 70bf215546Sopenharmony_ci uniform->var = var; 71bf215546Sopenharmony_ci buffer->num_uniforms++; 72bf215546Sopenharmony_ci} 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_cistatic void 75bf215546Sopenharmony_ciprocess_atomic_variable(const struct glsl_type *t, 76bf215546Sopenharmony_ci struct gl_shader_program *prog, 77bf215546Sopenharmony_ci unsigned *uniform_loc, 78bf215546Sopenharmony_ci nir_variable *var, 79bf215546Sopenharmony_ci struct active_atomic_buffer *buffers, 80bf215546Sopenharmony_ci unsigned *num_buffers, 81bf215546Sopenharmony_ci int *offset, 82bf215546Sopenharmony_ci unsigned shader_stage) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci /* FIXME: Arrays of arrays get counted separately. For example: 85bf215546Sopenharmony_ci * x1[3][3][2] = 9 uniforms, 18 atomic counters 86bf215546Sopenharmony_ci * x2[3][2] = 3 uniforms, 6 atomic counters 87bf215546Sopenharmony_ci * x3[2] = 1 uniform, 2 atomic counters 88bf215546Sopenharmony_ci * 89bf215546Sopenharmony_ci * However this code marks all the counters as active even when they 90bf215546Sopenharmony_ci * might not be used. 91bf215546Sopenharmony_ci */ 92bf215546Sopenharmony_ci if (glsl_type_is_array(t) && 93bf215546Sopenharmony_ci glsl_type_is_array(glsl_get_array_element(t))) { 94bf215546Sopenharmony_ci for (unsigned i = 0; i < glsl_get_length(t); i++) { 95bf215546Sopenharmony_ci process_atomic_variable(glsl_get_array_element(t), 96bf215546Sopenharmony_ci prog, 97bf215546Sopenharmony_ci uniform_loc, 98bf215546Sopenharmony_ci var, 99bf215546Sopenharmony_ci buffers, num_buffers, 100bf215546Sopenharmony_ci offset, 101bf215546Sopenharmony_ci shader_stage); 102bf215546Sopenharmony_ci } 103bf215546Sopenharmony_ci } else { 104bf215546Sopenharmony_ci struct active_atomic_buffer *buf = buffers + var->data.binding; 105bf215546Sopenharmony_ci struct gl_uniform_storage *const storage = 106bf215546Sopenharmony_ci &prog->data->UniformStorage[*uniform_loc]; 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci /* If this is the first time the buffer is used, increment 109bf215546Sopenharmony_ci * the counter of buffers used. 110bf215546Sopenharmony_ci */ 111bf215546Sopenharmony_ci if (buf->size == 0) 112bf215546Sopenharmony_ci (*num_buffers)++; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci add_atomic_counter(buffers, /* ctx */ 115bf215546Sopenharmony_ci buf, 116bf215546Sopenharmony_ci *uniform_loc, 117bf215546Sopenharmony_ci var); 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci /* When checking for atomic counters we should count every member in 120bf215546Sopenharmony_ci * an array as an atomic counter reference. 121bf215546Sopenharmony_ci */ 122bf215546Sopenharmony_ci if (glsl_type_is_array(t)) 123bf215546Sopenharmony_ci buf->stage_counter_references[shader_stage] += glsl_get_length(t); 124bf215546Sopenharmony_ci else 125bf215546Sopenharmony_ci buf->stage_counter_references[shader_stage]++; 126bf215546Sopenharmony_ci buf->size = MAX2(buf->size, *offset + glsl_atomic_size(t)); 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci storage->offset = *offset; 129bf215546Sopenharmony_ci *offset += glsl_atomic_size(t); 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci (*uniform_loc)++; 132bf215546Sopenharmony_ci } 133bf215546Sopenharmony_ci} 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_cistatic struct active_atomic_buffer * 136bf215546Sopenharmony_cifind_active_atomic_counters(const struct gl_constants *consts, 137bf215546Sopenharmony_ci struct gl_shader_program *prog, 138bf215546Sopenharmony_ci unsigned *num_buffers) 139bf215546Sopenharmony_ci{ 140bf215546Sopenharmony_ci struct active_atomic_buffer *buffers = 141bf215546Sopenharmony_ci rzalloc_array(NULL, /* ctx */ 142bf215546Sopenharmony_ci struct active_atomic_buffer, 143bf215546Sopenharmony_ci consts->MaxAtomicBufferBindings); 144bf215546Sopenharmony_ci *num_buffers = 0; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci for (unsigned i = 0; i < MESA_SHADER_STAGES; ++i) { 147bf215546Sopenharmony_ci struct gl_linked_shader *sh = prog->_LinkedShaders[i]; 148bf215546Sopenharmony_ci if (sh == NULL) 149bf215546Sopenharmony_ci continue; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci nir_shader *nir = sh->Program->nir; 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci nir_foreach_uniform_variable(var, nir) { 154bf215546Sopenharmony_ci if (!glsl_contains_atomic(var->type)) 155bf215546Sopenharmony_ci continue; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci int offset = var->data.offset; 158bf215546Sopenharmony_ci unsigned uniform_loc = var->data.location; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci process_atomic_variable(var->type, 161bf215546Sopenharmony_ci prog, 162bf215546Sopenharmony_ci &uniform_loc, 163bf215546Sopenharmony_ci var, 164bf215546Sopenharmony_ci buffers, 165bf215546Sopenharmony_ci num_buffers, 166bf215546Sopenharmony_ci &offset, 167bf215546Sopenharmony_ci i); 168bf215546Sopenharmony_ci } 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci return buffers; 172bf215546Sopenharmony_ci} 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_cistatic bool 175bf215546Sopenharmony_cicheck_atomic_counters_overlap(const nir_variable *x, const nir_variable *y) 176bf215546Sopenharmony_ci{ 177bf215546Sopenharmony_ci return ((x->data.offset >= y->data.offset && 178bf215546Sopenharmony_ci x->data.offset < y->data.offset + glsl_atomic_size(y->type)) || 179bf215546Sopenharmony_ci (y->data.offset >= x->data.offset && 180bf215546Sopenharmony_ci y->data.offset < x->data.offset + glsl_atomic_size(x->type))); 181bf215546Sopenharmony_ci} 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_cistatic int 184bf215546Sopenharmony_cicmp_active_counter_offsets(const void *a, const void *b) 185bf215546Sopenharmony_ci{ 186bf215546Sopenharmony_ci const struct active_atomic_counter_uniform *const first = 187bf215546Sopenharmony_ci (struct active_atomic_counter_uniform *) a; 188bf215546Sopenharmony_ci const struct active_atomic_counter_uniform *const second = 189bf215546Sopenharmony_ci (struct active_atomic_counter_uniform *) b; 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci return first->var->data.offset - second->var->data.offset; 192bf215546Sopenharmony_ci} 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_civoid 195bf215546Sopenharmony_cigl_nir_link_assign_atomic_counter_resources(const struct gl_constants *consts, 196bf215546Sopenharmony_ci struct gl_shader_program *prog) 197bf215546Sopenharmony_ci{ 198bf215546Sopenharmony_ci unsigned num_buffers; 199bf215546Sopenharmony_ci unsigned num_atomic_buffers[MESA_SHADER_STAGES] = {0}; 200bf215546Sopenharmony_ci struct active_atomic_buffer *abs = 201bf215546Sopenharmony_ci find_active_atomic_counters(consts, prog, &num_buffers); 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci prog->data->AtomicBuffers = 204bf215546Sopenharmony_ci rzalloc_array(prog->data, struct gl_active_atomic_buffer, num_buffers); 205bf215546Sopenharmony_ci prog->data->NumAtomicBuffers = num_buffers; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci unsigned buffer_idx = 0; 208bf215546Sopenharmony_ci for (unsigned binding = 0; 209bf215546Sopenharmony_ci binding < consts->MaxAtomicBufferBindings; 210bf215546Sopenharmony_ci binding++) { 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci /* If the binding was not used, skip. 213bf215546Sopenharmony_ci */ 214bf215546Sopenharmony_ci if (abs[binding].size == 0) 215bf215546Sopenharmony_ci continue; 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci struct active_atomic_buffer *ab = abs + binding; 218bf215546Sopenharmony_ci struct gl_active_atomic_buffer *mab = 219bf215546Sopenharmony_ci prog->data->AtomicBuffers + buffer_idx; 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci /* Assign buffer-specific fields. */ 222bf215546Sopenharmony_ci mab->Binding = binding; 223bf215546Sopenharmony_ci mab->MinimumSize = ab->size; 224bf215546Sopenharmony_ci mab->Uniforms = rzalloc_array(prog->data->AtomicBuffers, GLuint, 225bf215546Sopenharmony_ci ab->num_uniforms); 226bf215546Sopenharmony_ci mab->NumUniforms = ab->num_uniforms; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci /* Assign counter-specific fields. */ 229bf215546Sopenharmony_ci for (unsigned j = 0; j < ab->num_uniforms; j++) { 230bf215546Sopenharmony_ci nir_variable *var = ab->uniforms[j].var; 231bf215546Sopenharmony_ci struct gl_uniform_storage *storage = 232bf215546Sopenharmony_ci &prog->data->UniformStorage[ab->uniforms[j].loc]; 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci mab->Uniforms[j] = ab->uniforms[j].loc; 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci storage->atomic_buffer_index = buffer_idx; 237bf215546Sopenharmony_ci storage->offset = var->data.offset; 238bf215546Sopenharmony_ci if (glsl_type_is_array(var->type)) { 239bf215546Sopenharmony_ci const struct glsl_type *without_array = 240bf215546Sopenharmony_ci glsl_without_array(var->type); 241bf215546Sopenharmony_ci storage->array_stride = glsl_atomic_size(without_array); 242bf215546Sopenharmony_ci } else { 243bf215546Sopenharmony_ci storage->array_stride = 0; 244bf215546Sopenharmony_ci } 245bf215546Sopenharmony_ci if (!glsl_type_is_matrix(var->type)) 246bf215546Sopenharmony_ci storage->matrix_stride = 0; 247bf215546Sopenharmony_ci } 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci /* Assign stage-specific fields. */ 250bf215546Sopenharmony_ci for (unsigned stage = 0; stage < MESA_SHADER_STAGES; ++stage) { 251bf215546Sopenharmony_ci if (ab->stage_counter_references[stage]) { 252bf215546Sopenharmony_ci mab->StageReferences[stage] = GL_TRUE; 253bf215546Sopenharmony_ci num_atomic_buffers[stage]++; 254bf215546Sopenharmony_ci } else { 255bf215546Sopenharmony_ci mab->StageReferences[stage] = GL_FALSE; 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci } 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci buffer_idx++; 260bf215546Sopenharmony_ci } 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci /* Store a list pointers to atomic buffers per stage and store the index 263bf215546Sopenharmony_ci * to the intra-stage buffer list in uniform storage. 264bf215546Sopenharmony_ci */ 265bf215546Sopenharmony_ci for (unsigned stage = 0; stage < MESA_SHADER_STAGES; ++stage) { 266bf215546Sopenharmony_ci if (prog->_LinkedShaders[stage] == NULL || 267bf215546Sopenharmony_ci num_atomic_buffers[stage] <= 0) 268bf215546Sopenharmony_ci continue; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci struct gl_program *gl_prog = prog->_LinkedShaders[stage]->Program; 271bf215546Sopenharmony_ci gl_prog->info.num_abos = num_atomic_buffers[stage]; 272bf215546Sopenharmony_ci gl_prog->sh.AtomicBuffers = 273bf215546Sopenharmony_ci rzalloc_array(gl_prog, 274bf215546Sopenharmony_ci struct gl_active_atomic_buffer *, 275bf215546Sopenharmony_ci num_atomic_buffers[stage]); 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci gl_prog->nir->info.num_abos = num_atomic_buffers[stage]; 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci unsigned intra_stage_idx = 0; 280bf215546Sopenharmony_ci for (unsigned i = 0; i < num_buffers; i++) { 281bf215546Sopenharmony_ci struct gl_active_atomic_buffer *atomic_buffer = 282bf215546Sopenharmony_ci &prog->data->AtomicBuffers[i]; 283bf215546Sopenharmony_ci if (!atomic_buffer->StageReferences[stage]) 284bf215546Sopenharmony_ci continue; 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci gl_prog->sh.AtomicBuffers[intra_stage_idx] = atomic_buffer; 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci for (unsigned u = 0; u < atomic_buffer->NumUniforms; u++) { 289bf215546Sopenharmony_ci GLuint uniform_loc = atomic_buffer->Uniforms[u]; 290bf215546Sopenharmony_ci struct gl_opaque_uniform_index *opaque = 291bf215546Sopenharmony_ci prog->data->UniformStorage[uniform_loc].opaque + stage; 292bf215546Sopenharmony_ci opaque->index = intra_stage_idx; 293bf215546Sopenharmony_ci opaque->active = true; 294bf215546Sopenharmony_ci } 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci intra_stage_idx++; 297bf215546Sopenharmony_ci } 298bf215546Sopenharmony_ci } 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci assert(buffer_idx == num_buffers); 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci ralloc_free(abs); 303bf215546Sopenharmony_ci} 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_civoid 306bf215546Sopenharmony_cigl_nir_link_check_atomic_counter_resources(const struct gl_constants *consts, 307bf215546Sopenharmony_ci struct gl_shader_program *prog) 308bf215546Sopenharmony_ci{ 309bf215546Sopenharmony_ci unsigned num_buffers; 310bf215546Sopenharmony_ci struct active_atomic_buffer *abs = 311bf215546Sopenharmony_ci find_active_atomic_counters(consts, prog, &num_buffers); 312bf215546Sopenharmony_ci unsigned atomic_counters[MESA_SHADER_STAGES] = {0}; 313bf215546Sopenharmony_ci unsigned atomic_buffers[MESA_SHADER_STAGES] = {0}; 314bf215546Sopenharmony_ci unsigned total_atomic_counters = 0; 315bf215546Sopenharmony_ci unsigned total_atomic_buffers = 0; 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci /* Sum the required resources. Note that this counts buffers and 318bf215546Sopenharmony_ci * counters referenced by several shader stages multiple times 319bf215546Sopenharmony_ci * against the combined limit -- That's the behavior the spec 320bf215546Sopenharmony_ci * requires. 321bf215546Sopenharmony_ci */ 322bf215546Sopenharmony_ci for (unsigned i = 0; i < consts->MaxAtomicBufferBindings; i++) { 323bf215546Sopenharmony_ci if (abs[i].size == 0) 324bf215546Sopenharmony_ci continue; 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci qsort(abs[i].uniforms, abs[i].num_uniforms, 327bf215546Sopenharmony_ci sizeof(struct active_atomic_counter_uniform), 328bf215546Sopenharmony_ci cmp_active_counter_offsets); 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci for (unsigned j = 1; j < abs[i].num_uniforms; j++) { 331bf215546Sopenharmony_ci /* If an overlapping counter found, it must be a reference to the 332bf215546Sopenharmony_ci * same counter from a different shader stage. 333bf215546Sopenharmony_ci */ 334bf215546Sopenharmony_ci if (check_atomic_counters_overlap(abs[i].uniforms[j-1].var, 335bf215546Sopenharmony_ci abs[i].uniforms[j].var) 336bf215546Sopenharmony_ci && strcmp(abs[i].uniforms[j-1].var->name, 337bf215546Sopenharmony_ci abs[i].uniforms[j].var->name) != 0) { 338bf215546Sopenharmony_ci linker_error(prog, "Atomic counter %s declared at offset %d " 339bf215546Sopenharmony_ci "which is already in use.", 340bf215546Sopenharmony_ci abs[i].uniforms[j].var->name, 341bf215546Sopenharmony_ci abs[i].uniforms[j].var->data.offset); 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci } 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) { 346bf215546Sopenharmony_ci const unsigned n = abs[i].stage_counter_references[j]; 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci if (n) { 349bf215546Sopenharmony_ci atomic_counters[j] += n; 350bf215546Sopenharmony_ci total_atomic_counters += n; 351bf215546Sopenharmony_ci atomic_buffers[j]++; 352bf215546Sopenharmony_ci total_atomic_buffers++; 353bf215546Sopenharmony_ci } 354bf215546Sopenharmony_ci } 355bf215546Sopenharmony_ci } 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci /* Check that they are within the supported limits. */ 358bf215546Sopenharmony_ci for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { 359bf215546Sopenharmony_ci if (atomic_counters[i] > consts->Program[i].MaxAtomicCounters) 360bf215546Sopenharmony_ci linker_error(prog, "Too many %s shader atomic counters", 361bf215546Sopenharmony_ci _mesa_shader_stage_to_string(i)); 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci if (atomic_buffers[i] > consts->Program[i].MaxAtomicBuffers) 364bf215546Sopenharmony_ci linker_error(prog, "Too many %s shader atomic counter buffers", 365bf215546Sopenharmony_ci _mesa_shader_stage_to_string(i)); 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci if (total_atomic_counters > consts->MaxCombinedAtomicCounters) 369bf215546Sopenharmony_ci linker_error(prog, "Too many combined atomic counters"); 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci if (total_atomic_buffers > consts->MaxCombinedAtomicBuffers) 372bf215546Sopenharmony_ci linker_error(prog, "Too many combined atomic buffers"); 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci ralloc_free(abs); 375bf215546Sopenharmony_ci} 376