1 //
2 // Copyright 2022 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // CompiledShaderState.cpp:
7 // Implements CompiledShaderState, and helper functions for serializing and deserializing
8 // shader variables.
9 //
10
11 #include "common/CompiledShaderState.h"
12
13 #include "common/BinaryStream.h"
14 #include "common/utilities.h"
15
16 namespace gl
17 {
18 namespace
19 {
20 template <typename VarT>
GetActiveShaderVariables(const std::vector<VarT> * variableList)21 std::vector<VarT> GetActiveShaderVariables(const std::vector<VarT> *variableList)
22 {
23 ASSERT(variableList);
24 std::vector<VarT> result;
25 for (size_t varIndex = 0; varIndex < variableList->size(); varIndex++)
26 {
27 const VarT &var = variableList->at(varIndex);
28 if (var.active)
29 {
30 result.push_back(var);
31 }
32 }
33 return result;
34 }
35
36 template <typename VarT>
GetShaderVariables(const std::vector<VarT> * variableList)37 const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableList)
38 {
39 ASSERT(variableList);
40 return *variableList;
41 }
42 } // namespace
43
44 // true if varying x has a higher priority in packing than y
CompareShaderVar(const sh::ShaderVariable & x,const sh::ShaderVariable & y)45 bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
46 {
47 if (x.type == y.type)
48 {
49 return x.getArraySizeProduct() > y.getArraySizeProduct();
50 }
51
52 // Special case for handling structs: we sort these to the end of the list
53 if (x.type == GL_NONE)
54 {
55 return false;
56 }
57
58 if (y.type == GL_NONE)
59 {
60 return true;
61 }
62
63 return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
64 }
65
WriteShaderVar(gl::BinaryOutputStream * stream,const sh::ShaderVariable & var)66 void WriteShaderVar(gl::BinaryOutputStream *stream, const sh::ShaderVariable &var)
67 {
68 stream->writeInt(var.type);
69 stream->writeInt(var.precision);
70 stream->writeString(var.name);
71 stream->writeString(var.mappedName);
72 stream->writeIntVector(var.arraySizes);
73 stream->writeBool(var.staticUse);
74 stream->writeBool(var.active);
75 stream->writeInt<size_t>(var.fields.size());
76 for (const sh::ShaderVariable &shaderVariable : var.fields)
77 {
78 WriteShaderVar(stream, shaderVariable);
79 }
80 stream->writeString(var.structOrBlockName);
81 stream->writeString(var.mappedStructOrBlockName);
82 stream->writeBool(var.isRowMajorLayout);
83 stream->writeInt(var.location);
84 stream->writeBool(var.hasImplicitLocation);
85 stream->writeInt(var.binding);
86 stream->writeInt(var.imageUnitFormat);
87 stream->writeInt(var.offset);
88 stream->writeBool(var.rasterOrdered);
89 stream->writeBool(var.readonly);
90 stream->writeBool(var.writeonly);
91 stream->writeBool(var.isFragmentInOut);
92 stream->writeInt(var.index);
93 stream->writeBool(var.yuv);
94 stream->writeEnum(var.interpolation);
95 stream->writeBool(var.isInvariant);
96 stream->writeBool(var.isShaderIOBlock);
97 stream->writeBool(var.isPatch);
98 stream->writeBool(var.texelFetchStaticUse);
99 stream->writeInt(var.getFlattenedOffsetInParentArrays());
100 stream->writeInt(var.id);
101 }
102
LoadShaderVar(gl::BinaryInputStream * stream,sh::ShaderVariable * var)103 void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var)
104 {
105 var->type = stream->readInt<GLenum>();
106 var->precision = stream->readInt<GLenum>();
107 stream->readString(&var->name);
108 stream->readString(&var->mappedName);
109 stream->readIntVector<unsigned int>(&var->arraySizes);
110 var->staticUse = stream->readBool();
111 var->active = stream->readBool();
112 size_t elementCount = stream->readInt<size_t>();
113 var->fields.resize(elementCount);
114 for (sh::ShaderVariable &variable : var->fields)
115 {
116 LoadShaderVar(stream, &variable);
117 }
118 stream->readString(&var->structOrBlockName);
119 stream->readString(&var->mappedStructOrBlockName);
120 var->isRowMajorLayout = stream->readBool();
121 var->location = stream->readInt<int>();
122 var->hasImplicitLocation = stream->readBool();
123 var->binding = stream->readInt<int>();
124 var->imageUnitFormat = stream->readInt<GLenum>();
125 var->offset = stream->readInt<int>();
126 var->rasterOrdered = stream->readBool();
127 var->readonly = stream->readBool();
128 var->writeonly = stream->readBool();
129 var->isFragmentInOut = stream->readBool();
130 var->index = stream->readInt<int>();
131 var->yuv = stream->readBool();
132 var->interpolation = stream->readEnum<sh::InterpolationType>();
133 var->isInvariant = stream->readBool();
134 var->isShaderIOBlock = stream->readBool();
135 var->isPatch = stream->readBool();
136 var->texelFetchStaticUse = stream->readBool();
137 var->setParentArrayIndex(stream->readInt<int>());
138 var->id = stream->readInt<uint32_t>();
139 }
140
WriteShInterfaceBlock(gl::BinaryOutputStream * stream,const sh::InterfaceBlock & block)141 void WriteShInterfaceBlock(gl::BinaryOutputStream *stream, const sh::InterfaceBlock &block)
142 {
143 stream->writeString(block.name);
144 stream->writeString(block.mappedName);
145 stream->writeString(block.instanceName);
146 stream->writeInt(block.arraySize);
147 stream->writeEnum(block.layout);
148 stream->writeBool(block.isRowMajorLayout);
149 stream->writeInt(block.binding);
150 stream->writeBool(block.staticUse);
151 stream->writeBool(block.active);
152 stream->writeEnum(block.blockType);
153 stream->writeInt(block.id);
154
155 stream->writeInt<size_t>(block.fields.size());
156 for (const sh::ShaderVariable &shaderVariable : block.fields)
157 {
158 WriteShaderVar(stream, shaderVariable);
159 }
160 }
161
LoadShInterfaceBlock(gl::BinaryInputStream * stream,sh::InterfaceBlock * block)162 void LoadShInterfaceBlock(gl::BinaryInputStream *stream, sh::InterfaceBlock *block)
163 {
164 block->name = stream->readString();
165 block->mappedName = stream->readString();
166 block->instanceName = stream->readString();
167 block->arraySize = stream->readInt<unsigned int>();
168 block->layout = stream->readEnum<sh::BlockLayoutType>();
169 block->isRowMajorLayout = stream->readBool();
170 block->binding = stream->readInt<int>();
171 block->staticUse = stream->readBool();
172 block->active = stream->readBool();
173 block->blockType = stream->readEnum<sh::BlockType>();
174 block->id = stream->readInt<uint32_t>();
175
176 block->fields.resize(stream->readInt<size_t>());
177 for (sh::ShaderVariable &variable : block->fields)
178 {
179 LoadShaderVar(stream, &variable);
180 }
181 }
182
CompiledShaderState(gl::ShaderType type)183 CompiledShaderState::CompiledShaderState(gl::ShaderType type)
184 : shaderType(type), shaderVersion(100), numViews(-1), geometryShaderInvocations(1)
185 {
186 localSize.fill(-1);
187 }
188
~CompiledShaderState()189 CompiledShaderState::~CompiledShaderState() {}
190
buildCompiledShaderState(const ShHandle compilerHandle,const bool isBinaryOutput)191 void CompiledShaderState::buildCompiledShaderState(const ShHandle compilerHandle,
192 const bool isBinaryOutput)
193 {
194 if (isBinaryOutput)
195 {
196 compiledBinary = sh::GetObjectBinaryBlob(compilerHandle);
197 }
198 else
199 {
200 translatedSource = sh::GetObjectCode(compilerHandle);
201 }
202
203 // Gather the shader information
204 shaderVersion = sh::GetShaderVersion(compilerHandle);
205
206 uniforms = GetShaderVariables(sh::GetUniforms(compilerHandle));
207 uniformBlocks = GetShaderVariables(sh::GetUniformBlocks(compilerHandle));
208 shaderStorageBlocks = GetShaderVariables(sh::GetShaderStorageBlocks(compilerHandle));
209 specConstUsageBits = SpecConstUsageBits(sh::GetShaderSpecConstUsageBits(compilerHandle));
210
211 switch (shaderType)
212 {
213 case gl::ShaderType::Compute:
214 {
215 allAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
216 activeAttributes = GetActiveShaderVariables(&allAttributes);
217 localSize = sh::GetComputeShaderLocalGroupSize(compilerHandle);
218 break;
219 }
220 case gl::ShaderType::Vertex:
221 {
222 outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
223 allAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
224 activeAttributes = GetActiveShaderVariables(&allAttributes);
225 hasClipDistance = sh::HasClipDistanceInVertexShader(compilerHandle);
226 numViews = sh::GetVertexShaderNumViews(compilerHandle);
227 break;
228 }
229 case gl::ShaderType::Fragment:
230 {
231 allAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
232 activeAttributes = GetActiveShaderVariables(&allAttributes);
233 inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
234 // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
235 std::sort(inputVaryings.begin(), inputVaryings.end(), CompareShaderVar);
236 activeOutputVariables =
237 GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
238 hasDiscard = sh::HasDiscardInFragmentShader(compilerHandle);
239 enablesPerSampleShading = sh::EnablesPerSampleShading(compilerHandle);
240 advancedBlendEquations =
241 gl::BlendEquationBitSet(sh::GetAdvancedBlendEquations(compilerHandle));
242 break;
243 }
244 case gl::ShaderType::Geometry:
245 {
246 inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
247 outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
248
249 if (sh::HasValidGeometryShaderInputPrimitiveType(compilerHandle))
250 {
251 geometryShaderInputPrimitiveType = gl::FromGLenum<gl::PrimitiveMode>(
252 sh::GetGeometryShaderInputPrimitiveType(compilerHandle));
253 }
254 if (sh::HasValidGeometryShaderOutputPrimitiveType(compilerHandle))
255 {
256 geometryShaderOutputPrimitiveType = gl::FromGLenum<gl::PrimitiveMode>(
257 sh::GetGeometryShaderOutputPrimitiveType(compilerHandle));
258 }
259 if (sh::HasValidGeometryShaderMaxVertices(compilerHandle))
260 {
261 geometryShaderMaxVertices = sh::GetGeometryShaderMaxVertices(compilerHandle);
262 }
263 geometryShaderInvocations = sh::GetGeometryShaderInvocations(compilerHandle);
264 break;
265 }
266 case gl::ShaderType::TessControl:
267 {
268 inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
269 outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
270 tessControlShaderVertices = sh::GetTessControlShaderVertices(compilerHandle);
271 break;
272 }
273 case gl::ShaderType::TessEvaluation:
274 {
275 inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
276 outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
277 if (sh::HasValidTessGenMode(compilerHandle))
278 {
279 tessGenMode = sh::GetTessGenMode(compilerHandle);
280 }
281 if (sh::HasValidTessGenSpacing(compilerHandle))
282 {
283 tessGenSpacing = sh::GetTessGenSpacing(compilerHandle);
284 }
285 if (sh::HasValidTessGenVertexOrder(compilerHandle))
286 {
287 tessGenVertexOrder = sh::GetTessGenVertexOrder(compilerHandle);
288 }
289 if (sh::HasValidTessGenPointMode(compilerHandle))
290 {
291 tessGenPointMode = sh::GetTessGenPointMode(compilerHandle);
292 }
293 break;
294 }
295
296 default:
297 UNREACHABLE();
298 }
299 }
300
serialize(gl::BinaryOutputStream & stream) const301 void CompiledShaderState::serialize(gl::BinaryOutputStream &stream) const
302 {
303 stream.writeInt(shaderVersion);
304
305 stream.writeInt(uniforms.size());
306 for (const sh::ShaderVariable &shaderVariable : uniforms)
307 {
308 WriteShaderVar(&stream, shaderVariable);
309 }
310
311 stream.writeInt(uniformBlocks.size());
312 for (const sh::InterfaceBlock &interfaceBlock : uniformBlocks)
313 {
314 WriteShInterfaceBlock(&stream, interfaceBlock);
315 }
316
317 stream.writeInt(shaderStorageBlocks.size());
318 for (const sh::InterfaceBlock &interfaceBlock : shaderStorageBlocks)
319 {
320 WriteShInterfaceBlock(&stream, interfaceBlock);
321 }
322
323 stream.writeInt(specConstUsageBits.bits());
324
325 switch (shaderType)
326 {
327 case gl::ShaderType::Compute:
328 {
329 stream.writeInt(allAttributes.size());
330 for (const sh::ShaderVariable &shaderVariable : allAttributes)
331 {
332 WriteShaderVar(&stream, shaderVariable);
333 }
334 stream.writeInt(activeAttributes.size());
335 for (const sh::ShaderVariable &shaderVariable : activeAttributes)
336 {
337 WriteShaderVar(&stream, shaderVariable);
338 }
339 stream.writeInt(localSize[0]);
340 stream.writeInt(localSize[1]);
341 stream.writeInt(localSize[2]);
342 break;
343 }
344
345 case gl::ShaderType::Vertex:
346 {
347 stream.writeInt(outputVaryings.size());
348 for (const sh::ShaderVariable &shaderVariable : outputVaryings)
349 {
350 WriteShaderVar(&stream, shaderVariable);
351 }
352 stream.writeInt(allAttributes.size());
353 for (const sh::ShaderVariable &shaderVariable : allAttributes)
354 {
355 WriteShaderVar(&stream, shaderVariable);
356 }
357 stream.writeInt(activeAttributes.size());
358 for (const sh::ShaderVariable &shaderVariable : activeAttributes)
359 {
360 WriteShaderVar(&stream, shaderVariable);
361 }
362 stream.writeBool(hasClipDistance);
363 stream.writeInt(numViews);
364 break;
365 }
366 case gl::ShaderType::Fragment:
367 {
368 stream.writeInt(inputVaryings.size());
369 for (const sh::ShaderVariable &shaderVariable : inputVaryings)
370 {
371 WriteShaderVar(&stream, shaderVariable);
372 }
373 stream.writeInt(activeOutputVariables.size());
374 for (const sh::ShaderVariable &shaderVariable : activeOutputVariables)
375 {
376 WriteShaderVar(&stream, shaderVariable);
377 }
378 stream.writeBool(hasDiscard);
379 stream.writeBool(enablesPerSampleShading);
380 stream.writeInt(advancedBlendEquations.bits());
381 break;
382 }
383 case gl::ShaderType::Geometry:
384 {
385 bool valid;
386
387 stream.writeInt(inputVaryings.size());
388 for (const sh::ShaderVariable &shaderVariable : inputVaryings)
389 {
390 WriteShaderVar(&stream, shaderVariable);
391 }
392 stream.writeInt(outputVaryings.size());
393 for (const sh::ShaderVariable &shaderVariable : outputVaryings)
394 {
395 WriteShaderVar(&stream, shaderVariable);
396 }
397
398 valid = (bool)geometryShaderInputPrimitiveType.valid();
399 stream.writeBool(valid);
400 if (valid)
401 {
402 unsigned char value = (unsigned char)geometryShaderInputPrimitiveType.value();
403 stream.writeBytes(&value, 1);
404 }
405 valid = (bool)geometryShaderOutputPrimitiveType.valid();
406 stream.writeBool(valid);
407 if (valid)
408 {
409 unsigned char value = (unsigned char)geometryShaderOutputPrimitiveType.value();
410 stream.writeBytes(&value, 1);
411 }
412 valid = geometryShaderMaxVertices.valid();
413 stream.writeBool(valid);
414 if (valid)
415 {
416 int value = (int)geometryShaderMaxVertices.value();
417 stream.writeInt(value);
418 }
419
420 stream.writeInt(geometryShaderInvocations);
421 break;
422 }
423 case gl::ShaderType::TessControl:
424 {
425 stream.writeInt(inputVaryings.size());
426 for (const sh::ShaderVariable &shaderVariable : inputVaryings)
427 {
428 WriteShaderVar(&stream, shaderVariable);
429 }
430 stream.writeInt(outputVaryings.size());
431 for (const sh::ShaderVariable &shaderVariable : outputVaryings)
432 {
433 WriteShaderVar(&stream, shaderVariable);
434 }
435 stream.writeInt(tessControlShaderVertices);
436 break;
437 }
438 case gl::ShaderType::TessEvaluation:
439 {
440 unsigned int value;
441
442 stream.writeInt(inputVaryings.size());
443 for (const sh::ShaderVariable &shaderVariable : inputVaryings)
444 {
445 WriteShaderVar(&stream, shaderVariable);
446 }
447 stream.writeInt(outputVaryings.size());
448 for (const sh::ShaderVariable &shaderVariable : outputVaryings)
449 {
450 WriteShaderVar(&stream, shaderVariable);
451 }
452
453 value = (unsigned int)(tessGenMode);
454 stream.writeInt(value);
455
456 value = (unsigned int)tessGenSpacing;
457 stream.writeInt(value);
458
459 value = (unsigned int)tessGenVertexOrder;
460 stream.writeInt(value);
461
462 value = (unsigned int)tessGenPointMode;
463 stream.writeInt(value);
464 break;
465 }
466 default:
467 UNREACHABLE();
468 }
469
470 stream.writeIntVector(compiledBinary);
471 }
472
deserialize(gl::BinaryInputStream & stream)473 void CompiledShaderState::deserialize(gl::BinaryInputStream &stream)
474 {
475 stream.readInt(&shaderVersion);
476
477 size_t size;
478 size = stream.readInt<size_t>();
479 uniforms.resize(size);
480 for (sh::ShaderVariable &shaderVariable : uniforms)
481 {
482 LoadShaderVar(&stream, &shaderVariable);
483 }
484
485 size = stream.readInt<size_t>();
486 uniformBlocks.resize(size);
487 for (sh::InterfaceBlock &interfaceBlock : uniformBlocks)
488 {
489 LoadShInterfaceBlock(&stream, &interfaceBlock);
490 }
491
492 size = stream.readInt<size_t>();
493 shaderStorageBlocks.resize(size);
494 for (sh::InterfaceBlock &interfaceBlock : shaderStorageBlocks)
495 {
496 LoadShInterfaceBlock(&stream, &interfaceBlock);
497 }
498
499 specConstUsageBits = SpecConstUsageBits(stream.readInt<uint32_t>());
500
501 switch (shaderType)
502 {
503 case gl::ShaderType::Compute:
504 {
505 size = stream.readInt<size_t>();
506 allAttributes.resize(size);
507 for (sh::ShaderVariable &shaderVariable : allAttributes)
508 {
509 LoadShaderVar(&stream, &shaderVariable);
510 }
511 size = stream.readInt<size_t>();
512 activeAttributes.resize(size);
513 for (sh::ShaderVariable &shaderVariable : activeAttributes)
514 {
515 LoadShaderVar(&stream, &shaderVariable);
516 }
517 stream.readInt(&localSize[0]);
518 stream.readInt(&localSize[1]);
519 stream.readInt(&localSize[2]);
520 break;
521 }
522 case gl::ShaderType::Vertex:
523 {
524 size = stream.readInt<size_t>();
525 outputVaryings.resize(size);
526 for (sh::ShaderVariable &shaderVariable : outputVaryings)
527 {
528 LoadShaderVar(&stream, &shaderVariable);
529 }
530 size = stream.readInt<size_t>();
531 allAttributes.resize(size);
532 for (sh::ShaderVariable &shaderVariable : allAttributes)
533 {
534 LoadShaderVar(&stream, &shaderVariable);
535 }
536 size = stream.readInt<size_t>();
537 activeAttributes.resize(size);
538 for (sh::ShaderVariable &shaderVariable : activeAttributes)
539 {
540 LoadShaderVar(&stream, &shaderVariable);
541 }
542 stream.readBool(&hasClipDistance);
543 stream.readInt(&numViews);
544 break;
545 }
546 case gl::ShaderType::Fragment:
547 {
548 size = stream.readInt<size_t>();
549 inputVaryings.resize(size);
550 for (sh::ShaderVariable &shaderVariable : inputVaryings)
551 {
552 LoadShaderVar(&stream, &shaderVariable);
553 }
554 size = stream.readInt<size_t>();
555 activeOutputVariables.resize(size);
556 for (sh::ShaderVariable &shaderVariable : activeOutputVariables)
557 {
558 LoadShaderVar(&stream, &shaderVariable);
559 }
560 stream.readBool(&hasDiscard);
561 stream.readBool(&enablesPerSampleShading);
562 int advancedBlendEquationBits;
563 stream.readInt(&advancedBlendEquationBits);
564 advancedBlendEquations = gl::BlendEquationBitSet(advancedBlendEquationBits);
565 break;
566 }
567 case gl::ShaderType::Geometry:
568 {
569 bool valid;
570
571 size = stream.readInt<size_t>();
572 inputVaryings.resize(size);
573 for (sh::ShaderVariable &shaderVariable : inputVaryings)
574 {
575 LoadShaderVar(&stream, &shaderVariable);
576 }
577 size = stream.readInt<size_t>();
578 outputVaryings.resize(size);
579 for (sh::ShaderVariable &shaderVariable : outputVaryings)
580 {
581 LoadShaderVar(&stream, &shaderVariable);
582 }
583
584 stream.readBool(&valid);
585 if (valid)
586 {
587 unsigned char value;
588 stream.readBytes(&value, 1);
589 geometryShaderInputPrimitiveType = static_cast<gl::PrimitiveMode>(value);
590 }
591 else
592 {
593 geometryShaderInputPrimitiveType.reset();
594 }
595
596 stream.readBool(&valid);
597 if (valid)
598 {
599 unsigned char value;
600 stream.readBytes(&value, 1);
601 geometryShaderOutputPrimitiveType = static_cast<gl::PrimitiveMode>(value);
602 }
603 else
604 {
605 geometryShaderOutputPrimitiveType.reset();
606 }
607
608 stream.readBool(&valid);
609 if (valid)
610 {
611 int value;
612 stream.readInt(&value);
613 geometryShaderMaxVertices = static_cast<GLint>(value);
614 }
615 else
616 {
617 geometryShaderMaxVertices.reset();
618 }
619
620 stream.readInt(&geometryShaderInvocations);
621 break;
622 }
623 case gl::ShaderType::TessControl:
624 {
625 size = stream.readInt<size_t>();
626 inputVaryings.resize(size);
627 for (sh::ShaderVariable &shaderVariable : inputVaryings)
628 {
629 LoadShaderVar(&stream, &shaderVariable);
630 }
631 size = stream.readInt<size_t>();
632 outputVaryings.resize(size);
633 for (sh::ShaderVariable &shaderVariable : outputVaryings)
634 {
635 LoadShaderVar(&stream, &shaderVariable);
636 }
637 stream.readInt(&tessControlShaderVertices);
638 break;
639 }
640 case gl::ShaderType::TessEvaluation:
641 {
642 unsigned int value;
643
644 size = stream.readInt<size_t>();
645 inputVaryings.resize(size);
646 for (sh::ShaderVariable &shaderVariable : inputVaryings)
647 {
648 LoadShaderVar(&stream, &shaderVariable);
649 }
650 size = stream.readInt<size_t>();
651 outputVaryings.resize(size);
652 for (sh::ShaderVariable &shaderVariable : outputVaryings)
653 {
654 LoadShaderVar(&stream, &shaderVariable);
655 }
656
657 stream.readInt(&value);
658 tessGenMode = (GLenum)value;
659
660 stream.readInt(&value);
661 tessGenSpacing = (GLenum)value;
662
663 stream.readInt(&value);
664 tessGenVertexOrder = (GLenum)value;
665
666 stream.readInt(&value);
667 tessGenPointMode = (GLenum)value;
668 break;
669 }
670 default:
671 UNREACHABLE();
672 }
673
674 stream.readIntVector<unsigned int>(&compiledBinary);
675 }
676 } // namespace gl
677