void link_assign_atomic_counter_resources(struct gl_context *ctx, struct gl_shader_program *prog) { unsigned num_buffers; active_atomic_buffer *abs = find_active_atomic_counters(ctx, prog, &num_buffers); prog->AtomicBuffers = rzalloc_array(prog, gl_active_atomic_buffer, num_buffers); prog->NumAtomicBuffers = num_buffers; unsigned i = 0; for (unsigned binding = 0; binding < ctx->Const.MaxAtomicBufferBindings; binding++) { /* If the binding was not used, skip. */ if (abs[binding].size == 0) continue; active_atomic_buffer &ab = abs[binding]; gl_active_atomic_buffer &mab = prog->AtomicBuffers[i]; /* Assign buffer-specific fields. */ mab.Binding = binding; mab.MinimumSize = ab.size; mab.Uniforms = rzalloc_array(prog->AtomicBuffers, GLuint, ab.num_counters); mab.NumUniforms = ab.num_counters; /* Assign counter-specific fields. */ for (unsigned j = 0; j < ab.num_counters; j++) { ir_variable *const var = ab.counters[j].var; const unsigned id = ab.counters[j].id; gl_uniform_storage *const storage = &prog->UniformStorage[id]; mab.Uniforms[j] = id; if (!var->data.explicit_binding) var->data.binding = i; storage->atomic_buffer_index = i; storage->offset = var->data.atomic.offset; storage->array_stride = (var->type->is_array() ? var->type->element_type()->atomic_size() : 0); } /* Assign stage-specific fields. */ for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) mab.StageReferences[j] = (ab.stage_references[j] ? GL_TRUE : GL_FALSE); i++; } delete [] abs; assert(i == num_buffers); }
void link_check_atomic_counter_resources(struct gl_context *ctx, struct gl_shader_program *prog) { unsigned num_buffers; active_atomic_buffer *const abs = find_active_atomic_counters(ctx, prog, &num_buffers); unsigned atomic_counters[MESA_SHADER_STAGES] = {}; unsigned atomic_buffers[MESA_SHADER_STAGES] = {}; unsigned total_atomic_counters = 0; unsigned total_atomic_buffers = 0; /* Sum the required resources. Note that this counts buffers and * counters referenced by several shader stages multiple times * against the combined limit -- That's the behavior the spec * requires. */ for (unsigned i = 0; i < ctx->Const.MaxAtomicBufferBindings; i++) { if (abs[i].size == 0) continue; for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) { const unsigned n = abs[i].stage_references[j]; if (n) { atomic_counters[j] += n; total_atomic_counters += n; atomic_buffers[j]++; total_atomic_buffers++; } } } /* Check that they are within the supported limits. */ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { if (atomic_counters[i] > ctx->Const.Program[i].MaxAtomicCounters) linker_error(prog, "Too many %s shader atomic counters", _mesa_shader_stage_to_string(i)); if (atomic_buffers[i] > ctx->Const.Program[i].MaxAtomicBuffers) linker_error(prog, "Too many %s shader atomic counter buffers", _mesa_shader_stage_to_string(i)); } if (total_atomic_counters > ctx->Const.MaxCombinedAtomicCounters) linker_error(prog, "Too many combined atomic counters"); if (total_atomic_buffers > ctx->Const.MaxCombinedAtomicBuffers) linker_error(prog, "Too many combined atomic buffers"); delete [] abs; }
void link_assign_atomic_counter_resources(struct gl_context *ctx, struct gl_shader_program *prog) { unsigned num_buffers; unsigned num_atomic_buffers[MESA_SHADER_STAGES] = {}; active_atomic_buffer *abs = find_active_atomic_counters(ctx, prog, &num_buffers); prog->AtomicBuffers = rzalloc_array(prog, gl_active_atomic_buffer, num_buffers); prog->NumAtomicBuffers = num_buffers; unsigned i = 0; for (unsigned binding = 0; binding < ctx->Const.MaxAtomicBufferBindings; binding++) { /* If the binding was not used, skip. */ if (abs[binding].size == 0) continue; active_atomic_buffer &ab = abs[binding]; gl_active_atomic_buffer &mab = prog->AtomicBuffers[i]; /* Assign buffer-specific fields. */ mab.Binding = binding; mab.MinimumSize = ab.size; mab.Uniforms = rzalloc_array(prog->AtomicBuffers, GLuint, ab.num_uniforms); mab.NumUniforms = ab.num_uniforms; /* Assign counter-specific fields. */ for (unsigned j = 0; j < ab.num_uniforms; j++) { ir_variable *const var = ab.uniforms[j].var; gl_uniform_storage *const storage = &prog->UniformStorage[ab.uniforms[j].uniform_loc]; mab.Uniforms[j] = ab.uniforms[j].uniform_loc; if (!var->data.explicit_binding) var->data.binding = i; storage->atomic_buffer_index = i; storage->offset = var->data.offset; storage->array_stride = (var->type->is_array() ? var->type->without_array()->atomic_size() : 0); if (!var->type->is_matrix()) storage->matrix_stride = 0; } /* Assign stage-specific fields. */ for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) { if (ab.stage_counter_references[j]) { mab.StageReferences[j] = GL_TRUE; num_atomic_buffers[j]++; } else { mab.StageReferences[j] = GL_FALSE; } } i++; } /* Store a list pointers to atomic buffers per stage and store the index * to the intra-stage buffer list in uniform storage. */ for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) { if (prog->_LinkedShaders[j] && num_atomic_buffers[j] > 0) { prog->_LinkedShaders[j]->NumAtomicBuffers = num_atomic_buffers[j]; prog->_LinkedShaders[j]->AtomicBuffers = rzalloc_array(prog, gl_active_atomic_buffer *, num_atomic_buffers[j]); unsigned intra_stage_idx = 0; for (unsigned i = 0; i < num_buffers; i++) { struct gl_active_atomic_buffer *atomic_buffer = &prog->AtomicBuffers[i]; if (atomic_buffer->StageReferences[j]) { prog->_LinkedShaders[j]->AtomicBuffers[intra_stage_idx] = atomic_buffer; for (unsigned u = 0; u < atomic_buffer->NumUniforms; u++) { prog->UniformStorage[atomic_buffer->Uniforms[u]].opaque[j].index = intra_stage_idx; prog->UniformStorage[atomic_buffer->Uniforms[u]].opaque[j].active = true; } intra_stage_idx++; } } } }