blob: 907e38889bc982194146bf73667a6cb6789b347b [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +00002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
alokp@chromium.org774d7062010-07-21 18:55:45 +00008// Implement the top-level of interface to the compiler,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00009// as defined in ShaderLang.h
10//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000012#include "GLSLANG/ShaderLang.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000013
Geoff Lang17732822013-08-29 13:46:49 -040014#include "compiler/translator/InitializeDll.h"
kbr@chromium.org22152112011-10-26 01:18:28 +000015#include "compiler/preprocessor/length_limits.h"
Geoff Lang17732822013-08-29 13:46:49 -040016#include "compiler/translator/ShHandle.h"
17#include "compiler/translator/TranslatorHLSL.h"
18#include "compiler/translator/VariablePacker.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000019
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000020//
21// This is the platform independent interface between an OGL driver
alokp@chromium.org774d7062010-07-21 18:55:45 +000022// and the shading language compiler.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000023//
24
Zhenyao Mo74da9f22013-09-23 14:57:01 -040025static bool checkVariableMaxLengths(const ShHandle handle,
26 size_t expectedValue)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000027{
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +000028 size_t activeUniformLimit = 0;
kbr@chromium.org22152112011-10-26 01:18:28 +000029 ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +000030 size_t activeAttribLimit = 0;
kbr@chromium.org22152112011-10-26 01:18:28 +000031 ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
Zhenyao Mo74da9f22013-09-23 14:57:01 -040032 size_t varyingLimit = 0;
33 ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit);
34 return (expectedValue == activeUniformLimit &&
35 expectedValue == activeAttribLimit &&
36 expectedValue == varyingLimit);
kbr@chromium.org22152112011-10-26 01:18:28 +000037}
38
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +000039static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
kbr@chromium.org22152112011-10-26 01:18:28 +000040{
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +000041 size_t mappedNameMaxLength = 0;
kbr@chromium.org22152112011-10-26 01:18:28 +000042 ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
43 return (expectedValue == mappedNameMaxLength);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000044}
45
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000046//
Alok Priyadarshib11713f2013-08-01 16:02:39 -070047// Driver must call this first, once, before doing any other compiler operations.
48// Subsequent calls to this function are no-op.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000049//
50int ShInitialize()
51{
Alok Priyadarshib11713f2013-08-01 16:02:39 -070052 static const bool kInitialized = InitProcess();
53 return kInitialized ? 1 : 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000054}
55
56//
alokp@chromium.org94a86ad2010-08-25 20:02:11 +000057// Cleanup symbol tables
58//
59int ShFinalize()
60{
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -040061 DetachProcess();
alokp@chromium.org94a86ad2010-08-25 20:02:11 +000062 return 1;
63}
64
65//
66// Initialize built-in resources with minimum expected values.
67//
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000068void ShInitBuiltInResources(ShBuiltInResources* resources)
alokp@chromium.org94a86ad2010-08-25 20:02:11 +000069{
70 // Constants.
71 resources->MaxVertexAttribs = 8;
72 resources->MaxVertexUniformVectors = 128;
73 resources->MaxVaryingVectors = 8;
74 resources->MaxVertexTextureImageUnits = 0;
75 resources->MaxCombinedTextureImageUnits = 8;
76 resources->MaxTextureImageUnits = 8;
77 resources->MaxFragmentUniformVectors = 16;
78 resources->MaxDrawBuffers = 1;
79
80 // Extensions.
81 resources->OES_standard_derivatives = 0;
zmo@google.com09c323a2011-08-12 18:22:25 +000082 resources->OES_EGL_image_external = 0;
kbr@chromium.org205fef32011-11-22 20:50:02 +000083 resources->ARB_texture_rectangle = 0;
shannon.woods@transgaming.com550cd092013-02-28 23:19:54 +000084 resources->EXT_draw_buffers = 0;
Jamie Madill2aeb26a2013-07-08 14:02:55 -040085 resources->EXT_frag_depth = 0;
daniel@transgaming.comc23f4612012-11-28 19:42:57 +000086
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +000087 // Disable highp precision in fragment shader by default.
88 resources->FragmentPrecisionHigh = 0;
89
shannonwoods@chromium.org74b86cf2013-05-30 00:02:58 +000090 // GLSL ES 3.0 constants.
91 resources->MaxVertexOutputVectors = 16;
92 resources->MaxFragmentInputVectors = 15;
93 resources->MinProgramTexelOffset = -8;
94 resources->MaxProgramTexelOffset = 7;
95
daniel@transgaming.comc23f4612012-11-28 19:42:57 +000096 // Disable name hashing by default.
97 resources->HashFunction = NULL;
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +000098
99 resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
alokp@chromium.org94a86ad2010-08-25 20:02:11 +0000100}
101
102//
alokp@chromium.org774d7062010-07-21 18:55:45 +0000103// Driver calls these to create and destroy compiler objects.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104//
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000105ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
zmo@google.com5601ea02011-06-10 18:23:25 +0000106 ShShaderOutput output,
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000107 const ShBuiltInResources* resources)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000108{
zmo@google.com5601ea02011-06-10 18:23:25 +0000109 TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
alokp@chromium.orge4249f02010-07-26 18:13:52 +0000110 TCompiler* compiler = base->getAsCompiler();
111 if (compiler == 0)
112 return 0;
113
114 // Generate built-in symbol table.
alokp@chromium.org07620a52010-09-23 17:53:56 +0000115 if (!compiler->Init(*resources)) {
alokp@chromium.orge4249f02010-07-26 18:13:52 +0000116 ShDestruct(base);
117 return 0;
118 }
119
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120 return reinterpret_cast<void*>(base);
121}
122
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123void ShDestruct(ShHandle handle)
124{
125 if (handle == 0)
126 return;
127
128 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
129
130 if (base->getAsCompiler())
131 DeleteCompiler(base->getAsCompiler());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132}
133
134//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135// Do an actual compile on the given strings. The result is left
136// in the given compile object.
137//
138// Return: The return value of ShCompile is really boolean, indicating
139// success or failure.
140//
141int ShCompile(
142 const ShHandle handle,
143 const char* const shaderStrings[],
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000144 size_t numStrings,
alokp@chromium.org7beea402010-09-15 21:18:34 +0000145 int compileOptions)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000146{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147 if (handle == 0)
148 return 0;
149
150 TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
151 TCompiler* compiler = base->getAsCompiler();
152 if (compiler == 0)
153 return 0;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000154
alokp@chromium.org07620a52010-09-23 17:53:56 +0000155 bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156 return success ? 1 : 0;
157}
158
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000159void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
alokp@chromium.org7beea402010-09-15 21:18:34 +0000160{
161 if (!handle || !params)
162 return;
163
164 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
165 TCompiler* compiler = base->getAsCompiler();
166 if (!compiler) return;
167
168 switch(pname)
169 {
170 case SH_INFO_LOG_LENGTH:
171 *params = compiler->getInfoSink().info.size() + 1;
172 break;
173 case SH_OBJECT_CODE_LENGTH:
174 *params = compiler->getInfoSink().obj.size() + 1;
175 break;
176 case SH_ACTIVE_UNIFORMS:
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000177 *params = compiler->getUniforms().size();
alokp@chromium.org7beea402010-09-15 21:18:34 +0000178 break;
179 case SH_ACTIVE_UNIFORM_MAX_LENGTH:
kbr@chromium.org22152112011-10-26 01:18:28 +0000180 *params = 1 + MAX_SYMBOL_NAME_LEN;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000181 break;
182 case SH_ACTIVE_ATTRIBUTES:
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000183 *params = compiler->getAttribs().size();
alokp@chromium.org7beea402010-09-15 21:18:34 +0000184 break;
185 case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
kbr@chromium.org22152112011-10-26 01:18:28 +0000186 *params = 1 + MAX_SYMBOL_NAME_LEN;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000187 break;
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400188 case SH_VARYINGS:
189 *params = compiler->getVaryings().size();
190 break;
191 case SH_VARYING_MAX_LENGTH:
192 *params = 1 + MAX_SYMBOL_NAME_LEN;
193 break;
zmo@google.comfd747b82011-04-23 01:30:07 +0000194 case SH_MAPPED_NAME_MAX_LENGTH:
kbr@chromium.org22152112011-10-26 01:18:28 +0000195 // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
196 // handle array and struct dereferences.
197 *params = 1 + MAX_SYMBOL_NAME_LEN;
zmo@google.comfd747b82011-04-23 01:30:07 +0000198 break;
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000199 case SH_NAME_MAX_LENGTH:
200 *params = 1 + MAX_SYMBOL_NAME_LEN;
201 break;
202 case SH_HASHED_NAME_MAX_LENGTH:
203 if (compiler->getHashFunction() == NULL) {
204 *params = 0;
205 } else {
206 // 64 bits hashing output requires 16 bytes for hex
207 // representation.
208 const char HashedNamePrefix[] = HASHED_NAME_PREFIX;
209 *params = 16 + sizeof(HashedNamePrefix);
210 }
211 break;
212 case SH_HASHED_NAMES_COUNT:
213 *params = compiler->getNameMap().size();
214 break;
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000215 case SH_SHADER_VERSION:
216 *params = compiler->getShaderVersion();
217 break;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000218 default: UNREACHABLE();
219 }
220}
221
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222//
alokp@chromium.org774d7062010-07-21 18:55:45 +0000223// Return any compiler log of messages for the application.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224//
alokp@chromium.org7beea402010-09-15 21:18:34 +0000225void ShGetInfoLog(const ShHandle handle, char* infoLog)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226{
alokp@chromium.org7beea402010-09-15 21:18:34 +0000227 if (!handle || !infoLog)
228 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229
230 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000231 TCompiler* compiler = base->getAsCompiler();
232 if (!compiler) return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233
alokp@chromium.org7beea402010-09-15 21:18:34 +0000234 TInfoSink& infoSink = compiler->getInfoSink();
235 strcpy(infoLog, infoSink.info.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000236}
237
238//
alokp@chromium.org774d7062010-07-21 18:55:45 +0000239// Return any object code.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240//
alokp@chromium.org7beea402010-09-15 21:18:34 +0000241void ShGetObjectCode(const ShHandle handle, char* objCode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242{
alokp@chromium.org7beea402010-09-15 21:18:34 +0000243 if (!handle || !objCode)
244 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245
246 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000247 TCompiler* compiler = base->getAsCompiler();
248 if (!compiler) return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
alokp@chromium.org7beea402010-09-15 21:18:34 +0000250 TInfoSink& infoSink = compiler->getInfoSink();
251 strcpy(objCode, infoSink.obj.c_str());
252}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400254void ShGetVariableInfo(const ShHandle handle,
255 ShShaderInfo varType,
alokp@chromium.org7beea402010-09-15 21:18:34 +0000256 int index,
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000257 size_t* length,
alokp@chromium.org7beea402010-09-15 21:18:34 +0000258 int* size,
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000259 ShDataType* type,
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400260 ShPrecisionType* precision,
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400261 int* staticUse,
zmo@google.comfd747b82011-04-23 01:30:07 +0000262 char* name,
263 char* mappedName)
alokp@chromium.org7beea402010-09-15 21:18:34 +0000264{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400265 if (!handle || !size || !type || !precision || !staticUse || !name)
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400266 return;
267 ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
268 (varType == SH_ACTIVE_UNIFORMS) ||
269 (varType == SH_VARYINGS));
alokp@chromium.org7beea402010-09-15 21:18:34 +0000270
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400271 TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
272 TCompiler* compiler = base->getAsCompiler();
273 if (compiler == 0)
274 return;
275
276 const TVariableInfoList& varList =
277 varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() :
278 (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() :
279 compiler->getVaryings());
280 if (index < 0 || index >= static_cast<int>(varList.size()))
281 return;
282
283 const TVariableInfo& varInfo = varList[index];
284 if (length) *length = varInfo.name.size();
285 *size = varInfo.size;
286 *type = varInfo.type;
287 switch (varInfo.precision) {
288 case EbpLow:
289 *precision = SH_PRECISION_LOWP;
290 break;
291 case EbpMedium:
292 *precision = SH_PRECISION_MEDIUMP;
293 break;
294 case EbpHigh:
295 *precision = SH_PRECISION_HIGHP;
296 break;
297 default:
Zhenyao Mofa3c3462013-09-23 14:57:04 -0400298 // Some types does not support precision, for example, boolean.
299 *precision = SH_PRECISION_UNDEFINED;
300 break;
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400301 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400302 *staticUse = varInfo.staticUse ? 1 : 0;
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400303
304 // This size must match that queried by
305 // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH
306 // in ShGetInfo, below.
307 size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN;
308 ASSERT(checkVariableMaxLengths(handle, variableLength));
309 strncpy(name, varInfo.name.c_str(), variableLength);
310 name[variableLength - 1] = 0;
311 if (mappedName) {
312 // This size must match that queried by
313 // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
314 size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
315 ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
316 strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
317 mappedName[maxMappedNameLength - 1] = 0;
318 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000319}
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000320
321void ShGetNameHashingEntry(const ShHandle handle,
322 int index,
323 char* name,
324 char* hashedName)
325{
326 if (!handle || !name || !hashedName || index < 0)
327 return;
328
329 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
330 TCompiler* compiler = base->getAsCompiler();
331 if (!compiler) return;
332
333 const NameMap& nameMap = compiler->getNameMap();
334 if (index >= static_cast<int>(nameMap.size()))
335 return;
336
337 NameMap::const_iterator it = nameMap.begin();
338 for (int i = 0; i < index; ++i)
339 ++it;
340
341 size_t len = it->first.length() + 1;
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000342 size_t max_len = 0;
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000343 ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len);
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000344 if (len > max_len) {
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000345 ASSERT(false);
346 len = max_len;
347 }
348 strncpy(name, it->first.c_str(), len);
349 // To be on the safe side in case the source is longer than expected.
daniel@transgaming.com75cb6892013-02-01 03:20:26 +0000350 name[len - 1] = '\0';
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000351
352 len = it->second.length() + 1;
353 max_len = 0;
354 ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len);
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000355 if (len > max_len) {
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000356 ASSERT(false);
357 len = max_len;
358 }
359 strncpy(hashedName, it->second.c_str(), len);
360 // To be on the safe side in case the source is longer than expected.
daniel@transgaming.com75cb6892013-02-01 03:20:26 +0000361 hashedName[len - 1] = '\0';
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000362}
daniel@transgaming.com043da132012-12-20 21:12:22 +0000363
364void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
365{
366 if (!handle || !params)
367 return;
368
369 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
370 TranslatorHLSL* translator = base->getAsTranslatorHLSL();
371 if (!translator) return;
372
373 switch(pname)
374 {
375 case SH_ACTIVE_UNIFORMS_ARRAY:
376 *params = (void*)&translator->getUniforms();
377 break;
shannonwoods@chromium.org3f68bf02013-05-30 00:12:43 +0000378 case SH_ACTIVE_INTERFACE_BLOCKS_ARRAY:
379 *params = (void*)&translator->getInterfaceBlocks();
380 break;
Jamie Madill46131a32013-06-20 11:55:50 -0400381 case SH_ACTIVE_OUTPUT_VARIABLES_ARRAY:
382 *params = (void*)&translator->getOutputVariables();
383 break;
Jamie Madilldefb6742013-06-20 11:55:51 -0400384 case SH_ACTIVE_ATTRIBUTES_ARRAY:
385 *params = (void*)&translator->getAttributes();
386 break;
Jamie Madill47fdd132013-08-30 13:21:04 -0400387 case SH_ACTIVE_VARYINGS_ARRAY:
388 *params = (void*)&translator->getVaryings();
389 break;
daniel@transgaming.com043da132012-12-20 21:12:22 +0000390 default: UNREACHABLE();
391 }
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000392}
Zhenyao Moa15f3e82013-09-23 14:57:08 -0400393
394int ShCheckVariablesWithinPackingLimits(
395 int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize)
396{
397 if (varInfoArraySize == 0)
398 return 1;
399 ASSERT(varInfoArray);
400 TVariableInfoList variables;
401 for (size_t ii = 0; ii < varInfoArraySize; ++ii)
402 {
403 TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size);
404 variables.push_back(var);
405 }
406 VariablePacker packer;
407 return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0;
408}