glsl: Put `sample`-qualified varyings in their own packing classes
[mesa.git] / src / glsl / link_atomics.cpp
1 /*
2 * Copyright © 2013 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 "ir.h"
25 #include "ir_uniform.h"
26 #include "linker.h"
27 #include "program/hash_table.h"
28 #include "main/macros.h"
29
30 namespace {
31 /*
32 * Atomic counter as seen by the program.
33 */
34 struct active_atomic_counter {
35 unsigned id;
36 ir_variable *var;
37 };
38
39 /*
40 * Atomic counter buffer referenced by the program. There is a one
41 * to one correspondence between these and the objects that can be
42 * queried using glGetActiveAtomicCounterBufferiv().
43 */
44 struct active_atomic_buffer {
45 active_atomic_buffer()
46 : counters(0), num_counters(0), stage_references(), size(0)
47 {}
48
49 ~active_atomic_buffer()
50 {
51 free(counters);
52 }
53
54 void push_back(unsigned id, ir_variable *var)
55 {
56 counters = (active_atomic_counter *)
57 realloc(counters, sizeof(active_atomic_counter) * (num_counters + 1));
58
59 counters[num_counters].id = id;
60 counters[num_counters].var = var;
61 num_counters++;
62 }
63
64 active_atomic_counter *counters;
65 unsigned num_counters;
66 unsigned stage_references[MESA_SHADER_TYPES];
67 unsigned size;
68 };
69
70 int
71 cmp_actives(const void *a, const void *b)
72 {
73 const active_atomic_counter *const first = (active_atomic_counter *) a;
74 const active_atomic_counter *const second = (active_atomic_counter *) b;
75
76 return int(first->var->atomic.offset) - int(second->var->atomic.offset);
77 }
78
79 bool
80 check_atomic_counters_overlap(const ir_variable *x, const ir_variable *y)
81 {
82 return ((x->atomic.offset >= y->atomic.offset &&
83 x->atomic.offset < y->atomic.offset + y->type->atomic_size()) ||
84 (y->atomic.offset >= x->atomic.offset &&
85 y->atomic.offset < x->atomic.offset + x->type->atomic_size()));
86 }
87
88 active_atomic_buffer *
89 find_active_atomic_counters(struct gl_context *ctx,
90 struct gl_shader_program *prog,
91 unsigned *num_buffers)
92 {
93 active_atomic_buffer *const buffers =
94 new active_atomic_buffer[ctx->Const.MaxAtomicBufferBindings];
95
96 *num_buffers = 0;
97
98 for (unsigned i = 0; i < MESA_SHADER_TYPES; ++i) {
99 struct gl_shader *sh = prog->_LinkedShaders[i];
100 if (sh == NULL)
101 continue;
102
103 foreach_list(node, sh->ir) {
104 ir_variable *var = ((ir_instruction *)node)->as_variable();
105
106 if (var && var->type->contains_atomic()) {
107 unsigned id;
108 bool found = prog->UniformHash->get(id, var->name);
109 assert(found);
110 active_atomic_buffer *buf = &buffers[var->binding];
111
112 /* If this is the first time the buffer is used, increment
113 * the counter of buffers used.
114 */
115 if (buf->size == 0)
116 (*num_buffers)++;
117
118 buf->push_back(id, var);
119
120 buf->stage_references[i]++;
121 buf->size = MAX2(buf->size, var->atomic.offset +
122 var->type->atomic_size());
123 }
124 }
125 }
126
127 for (unsigned i = 0; i < ctx->Const.MaxAtomicBufferBindings; i++) {
128 if (buffers[i].size == 0)
129 continue;
130
131 qsort(buffers[i].counters, buffers[i].num_counters,
132 sizeof(active_atomic_counter),
133 cmp_actives);
134
135 for (unsigned j = 1; j < buffers[i].num_counters; j++) {
136 /* If an overlapping counter found, it must be a reference to the
137 * same counter from a different shader stage.
138 */
139 if (check_atomic_counters_overlap(buffers[i].counters[j-1].var,
140 buffers[i].counters[j].var)
141 && strcmp(buffers[i].counters[j-1].var->name,
142 buffers[i].counters[j].var->name) != 0) {
143 linker_error(prog, "Atomic counter %s declared at offset %d "
144 "which is already in use.",
145 buffers[i].counters[j].var->name,
146 buffers[i].counters[j].var->atomic.offset);
147 }
148 }
149 }
150 return buffers;
151 }
152 }
153
154 void
155 link_assign_atomic_counter_resources(struct gl_context *ctx,
156 struct gl_shader_program *prog)
157 {
158 unsigned num_buffers;
159 active_atomic_buffer *abs =
160 find_active_atomic_counters(ctx, prog, &num_buffers);
161
162 prog->AtomicBuffers = rzalloc_array(prog, gl_active_atomic_buffer,
163 num_buffers);
164 prog->NumAtomicBuffers = num_buffers;
165
166 unsigned i = 0;
167 for (unsigned binding = 0;
168 binding < ctx->Const.MaxAtomicBufferBindings;
169 binding++) {
170
171 /* If the binding was not used, skip.
172 */
173 if (abs[binding].size == 0)
174 continue;
175
176 active_atomic_buffer &ab = abs[binding];
177 gl_active_atomic_buffer &mab = prog->AtomicBuffers[i];
178
179 /* Assign buffer-specific fields. */
180 mab.Binding = binding;
181 mab.MinimumSize = ab.size;
182 mab.Uniforms = rzalloc_array(prog->AtomicBuffers, GLuint,
183 ab.num_counters);
184 mab.NumUniforms = ab.num_counters;
185
186 /* Assign counter-specific fields. */
187 for (unsigned j = 0; j < ab.num_counters; j++) {
188 ir_variable *const var = ab.counters[j].var;
189 const unsigned id = ab.counters[j].id;
190 gl_uniform_storage *const storage = &prog->UniformStorage[id];
191
192 mab.Uniforms[j] = id;
193 var->atomic.buffer_index = i;
194 storage->atomic_buffer_index = i;
195 storage->offset = var->atomic.offset;
196 storage->array_stride = (var->type->is_array() ?
197 var->type->element_type()->atomic_size() : 0);
198 }
199
200 /* Assign stage-specific fields. */
201 for (unsigned j = 0; j < MESA_SHADER_TYPES; ++j)
202 mab.StageReferences[j] =
203 (ab.stage_references[j] ? GL_TRUE : GL_FALSE);
204
205 i++;
206 }
207
208 delete [] abs;
209 assert(i == num_buffers);
210 }
211
212 void
213 link_check_atomic_counter_resources(struct gl_context *ctx,
214 struct gl_shader_program *prog)
215 {
216 STATIC_ASSERT(MESA_SHADER_TYPES == 3);
217 static const char *shader_names[MESA_SHADER_TYPES] = {
218 "vertex", "geometry", "fragment"
219 };
220 const unsigned max_atomic_counters[MESA_SHADER_TYPES] = {
221 ctx->Const.VertexProgram.MaxAtomicCounters,
222 ctx->Const.GeometryProgram.MaxAtomicCounters,
223 ctx->Const.FragmentProgram.MaxAtomicCounters
224 };
225 const unsigned max_atomic_buffers[MESA_SHADER_TYPES] = {
226 ctx->Const.VertexProgram.MaxAtomicBuffers,
227 ctx->Const.GeometryProgram.MaxAtomicBuffers,
228 ctx->Const.FragmentProgram.MaxAtomicBuffers
229 };
230 unsigned num_buffers;
231 active_atomic_buffer *const abs =
232 find_active_atomic_counters(ctx, prog, &num_buffers);
233 unsigned atomic_counters[MESA_SHADER_TYPES] = {};
234 unsigned atomic_buffers[MESA_SHADER_TYPES] = {};
235 unsigned total_atomic_counters = 0;
236 unsigned total_atomic_buffers = 0;
237
238 /* Sum the required resources. Note that this counts buffers and
239 * counters referenced by several shader stages multiple times
240 * against the combined limit -- That's the behavior the spec
241 * requires.
242 */
243 for (unsigned i = 0; i < ctx->Const.MaxAtomicBufferBindings; i++) {
244 if (abs[i].size == 0)
245 continue;
246
247 for (unsigned j = 0; j < MESA_SHADER_TYPES; ++j) {
248 const unsigned n = abs[i].stage_references[j];
249
250 if (n) {
251 atomic_counters[j] += n;
252 total_atomic_counters += n;
253 atomic_buffers[j]++;
254 total_atomic_buffers++;
255 }
256 }
257 }
258
259 /* Check that they are within the supported limits. */
260 for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
261 if (atomic_counters[i] > max_atomic_counters[i])
262 linker_error(prog, "Too many %s shader atomic counters",
263 shader_names[i]);
264
265 if (atomic_buffers[i] > max_atomic_buffers[i])
266 linker_error(prog, "Too many %s shader atomic counter buffers",
267 shader_names[i]);
268 }
269
270 if (total_atomic_counters > ctx->Const.MaxCombinedAtomicCounters)
271 linker_error(prog, "Too many combined atomic counters");
272
273 if (total_atomic_buffers > ctx->Const.MaxCombinedAtomicBuffers)
274 linker_error(prog, "Too many combined atomic buffers");
275
276 delete [] abs;
277 }