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->writeVector(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->readVector(&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),
185 shaderVersion(100),
186 numViews(-1),
187 geometryShaderInputPrimitiveType(gl::PrimitiveMode::Triangles),
188 geometryShaderOutputPrimitiveType(gl::PrimitiveMode::Triangles),
189 geometryShaderMaxVertices(0),
190 geometryShaderInvocations(1),
191 tessControlShaderVertices(0),
192 tessGenMode(0),
193 tessGenSpacing(0),
194 tessGenVertexOrder(0),
195 tessGenPointMode(0)
196 {
197 localSize.fill(-1);
198 }
199
~CompiledShaderState()200 CompiledShaderState::~CompiledShaderState() {}
201
buildCompiledShaderState(const ShHandle compilerHandle,const bool isBinaryOutput)202 void CompiledShaderState::buildCompiledShaderState(const ShHandle compilerHandle,
203 const bool isBinaryOutput)
204 {
205 if (isBinaryOutput)
206 {
207 compiledBinary = sh::GetObjectBinaryBlob(compilerHandle);
208 }
209 else
210 {
211 translatedSource = sh::GetObjectCode(compilerHandle);
212 }
213
214 // Gather the shader information
215 shaderVersion = sh::GetShaderVersion(compilerHandle);
216
217 uniforms = GetShaderVariables(sh::GetUniforms(compilerHandle));
218 uniformBlocks = GetShaderVariables(sh::GetUniformBlocks(compilerHandle));
219 shaderStorageBlocks = GetShaderVariables(sh::GetShaderStorageBlocks(compilerHandle));
220 metadataFlags = sh::CompilerMetadataFlags(sh::GetMetadataFlags(compilerHandle));
221 specConstUsageBits = SpecConstUsageBits(sh::GetShaderSpecConstUsageBits(compilerHandle));
222
223 switch (shaderType)
224 {
225 case gl::ShaderType::Compute:
226 {
227 allAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
228 activeAttributes = GetActiveShaderVariables(&allAttributes);
229 localSize = sh::GetComputeShaderLocalGroupSize(compilerHandle);
230 break;
231 }
232 case gl::ShaderType::Vertex:
233 {
234 outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
235 allAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
236 activeAttributes = GetActiveShaderVariables(&allAttributes);
237 numViews = sh::GetVertexShaderNumViews(compilerHandle);
238 break;
239 }
240 case gl::ShaderType::Fragment:
241 {
242 allAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
243 activeAttributes = GetActiveShaderVariables(&allAttributes);
244 inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
245 // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
246 std::sort(inputVaryings.begin(), inputVaryings.end(), CompareShaderVar);
247 activeOutputVariables =
248 GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
249 advancedBlendEquations =
250 gl::BlendEquationBitSet(sh::GetAdvancedBlendEquations(compilerHandle));
251 pixelLocalStorageFormats = *sh::GetPixelLocalStorageFormats(compilerHandle);
252 break;
253 }
254 case gl::ShaderType::Geometry:
255 {
256 inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
257 outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
258
259 if (metadataFlags[sh::MetadataFlags::HasValidGeometryShaderInputPrimitiveType])
260 {
261 geometryShaderInputPrimitiveType = gl::FromGLenum<gl::PrimitiveMode>(
262 sh::GetGeometryShaderInputPrimitiveType(compilerHandle));
263 }
264 if (metadataFlags[sh::MetadataFlags::HasValidGeometryShaderOutputPrimitiveType])
265 {
266 geometryShaderOutputPrimitiveType = gl::FromGLenum<gl::PrimitiveMode>(
267 sh::GetGeometryShaderOutputPrimitiveType(compilerHandle));
268 }
269 if (metadataFlags[sh::MetadataFlags::HasValidGeometryShaderMaxVertices])
270 {
271 geometryShaderMaxVertices = sh::GetGeometryShaderMaxVertices(compilerHandle);
272 }
273 geometryShaderInvocations = sh::GetGeometryShaderInvocations(compilerHandle);
274 break;
275 }
276 case gl::ShaderType::TessControl:
277 {
278 inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
279 outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
280 tessControlShaderVertices = sh::GetTessControlShaderVertices(compilerHandle);
281 break;
282 }
283 case gl::ShaderType::TessEvaluation:
284 {
285 inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
286 outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
287 if (metadataFlags[sh::MetadataFlags::HasValidTessGenMode])
288 {
289 tessGenMode = sh::GetTessGenMode(compilerHandle);
290 }
291 if (metadataFlags[sh::MetadataFlags::HasValidTessGenSpacing])
292 {
293 tessGenSpacing = sh::GetTessGenSpacing(compilerHandle);
294 }
295 if (metadataFlags[sh::MetadataFlags::HasValidTessGenVertexOrder])
296 {
297 tessGenVertexOrder = sh::GetTessGenVertexOrder(compilerHandle);
298 }
299 if (metadataFlags[sh::MetadataFlags::HasValidTessGenPointMode])
300 {
301 tessGenPointMode = sh::GetTessGenPointMode(compilerHandle);
302 }
303 break;
304 }
305
306 default:
307 UNREACHABLE();
308 }
309 }
310
serialize(gl::BinaryOutputStream & stream) const311 void CompiledShaderState::serialize(gl::BinaryOutputStream &stream) const
312 {
313 stream.writeInt(shaderVersion);
314
315 stream.writeInt(uniforms.size());
316 for (const sh::ShaderVariable &shaderVariable : uniforms)
317 {
318 WriteShaderVar(&stream, shaderVariable);
319 }
320
321 stream.writeInt(uniformBlocks.size());
322 for (const sh::InterfaceBlock &interfaceBlock : uniformBlocks)
323 {
324 WriteShInterfaceBlock(&stream, interfaceBlock);
325 }
326
327 stream.writeInt(shaderStorageBlocks.size());
328 for (const sh::InterfaceBlock &interfaceBlock : shaderStorageBlocks)
329 {
330 WriteShInterfaceBlock(&stream, interfaceBlock);
331 }
332
333 stream.writeInt(metadataFlags.bits());
334 stream.writeInt(specConstUsageBits.bits());
335
336 switch (shaderType)
337 {
338 case gl::ShaderType::Compute:
339 {
340 stream.writeInt(allAttributes.size());
341 for (const sh::ShaderVariable &shaderVariable : allAttributes)
342 {
343 WriteShaderVar(&stream, shaderVariable);
344 }
345 stream.writeInt(activeAttributes.size());
346 for (const sh::ShaderVariable &shaderVariable : activeAttributes)
347 {
348 WriteShaderVar(&stream, shaderVariable);
349 }
350 stream.writeInt(localSize[0]);
351 stream.writeInt(localSize[1]);
352 stream.writeInt(localSize[2]);
353 break;
354 }
355
356 case gl::ShaderType::Vertex:
357 {
358 stream.writeInt(outputVaryings.size());
359 for (const sh::ShaderVariable &shaderVariable : outputVaryings)
360 {
361 WriteShaderVar(&stream, shaderVariable);
362 }
363 stream.writeInt(allAttributes.size());
364 for (const sh::ShaderVariable &shaderVariable : allAttributes)
365 {
366 WriteShaderVar(&stream, shaderVariable);
367 }
368 stream.writeInt(activeAttributes.size());
369 for (const sh::ShaderVariable &shaderVariable : activeAttributes)
370 {
371 WriteShaderVar(&stream, shaderVariable);
372 }
373 stream.writeInt(numViews);
374 break;
375 }
376 case gl::ShaderType::Fragment:
377 {
378 stream.writeInt(inputVaryings.size());
379 for (const sh::ShaderVariable &shaderVariable : inputVaryings)
380 {
381 WriteShaderVar(&stream, shaderVariable);
382 }
383 stream.writeInt(activeOutputVariables.size());
384 for (const sh::ShaderVariable &shaderVariable : activeOutputVariables)
385 {
386 WriteShaderVar(&stream, shaderVariable);
387 }
388 stream.writeInt(advancedBlendEquations.bits());
389 stream.writeInt<size_t>(pixelLocalStorageFormats.size());
390 stream.writeBytes(reinterpret_cast<const uint8_t *>(pixelLocalStorageFormats.data()),
391 pixelLocalStorageFormats.size());
392 break;
393 }
394 case gl::ShaderType::Geometry:
395 {
396 stream.writeInt(inputVaryings.size());
397 for (const sh::ShaderVariable &shaderVariable : inputVaryings)
398 {
399 WriteShaderVar(&stream, shaderVariable);
400 }
401 stream.writeInt(outputVaryings.size());
402 for (const sh::ShaderVariable &shaderVariable : outputVaryings)
403 {
404 WriteShaderVar(&stream, shaderVariable);
405 }
406
407 {
408 unsigned char value = static_cast<unsigned char>(geometryShaderInputPrimitiveType);
409 stream.writeBytes(&value, 1);
410 }
411 {
412 unsigned char value = static_cast<unsigned char>(geometryShaderOutputPrimitiveType);
413 stream.writeBytes(&value, 1);
414 }
415 {
416 int value = static_cast<int>(geometryShaderMaxVertices);
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.writeString(translatedSource);
471 stream.writeVector(compiledBinary);
472 }
473
deserialize(gl::BinaryInputStream & stream)474 void CompiledShaderState::deserialize(gl::BinaryInputStream &stream)
475 {
476 stream.readInt(&shaderVersion);
477
478 size_t size;
479 size = stream.readInt<size_t>();
480 uniforms.resize(size);
481 for (sh::ShaderVariable &shaderVariable : uniforms)
482 {
483 LoadShaderVar(&stream, &shaderVariable);
484 }
485
486 size = stream.readInt<size_t>();
487 uniformBlocks.resize(size);
488 for (sh::InterfaceBlock &interfaceBlock : uniformBlocks)
489 {
490 LoadShInterfaceBlock(&stream, &interfaceBlock);
491 }
492
493 size = stream.readInt<size_t>();
494 shaderStorageBlocks.resize(size);
495 for (sh::InterfaceBlock &interfaceBlock : shaderStorageBlocks)
496 {
497 LoadShInterfaceBlock(&stream, &interfaceBlock);
498 }
499
500 metadataFlags = sh::CompilerMetadataFlags(stream.readInt<uint32_t>());
501 specConstUsageBits = SpecConstUsageBits(stream.readInt<uint32_t>());
502
503 switch (shaderType)
504 {
505 case gl::ShaderType::Compute:
506 {
507 size = stream.readInt<size_t>();
508 allAttributes.resize(size);
509 for (sh::ShaderVariable &shaderVariable : allAttributes)
510 {
511 LoadShaderVar(&stream, &shaderVariable);
512 }
513 size = stream.readInt<size_t>();
514 activeAttributes.resize(size);
515 for (sh::ShaderVariable &shaderVariable : activeAttributes)
516 {
517 LoadShaderVar(&stream, &shaderVariable);
518 }
519 stream.readInt(&localSize[0]);
520 stream.readInt(&localSize[1]);
521 stream.readInt(&localSize[2]);
522 break;
523 }
524 case gl::ShaderType::Vertex:
525 {
526 size = stream.readInt<size_t>();
527 outputVaryings.resize(size);
528 for (sh::ShaderVariable &shaderVariable : outputVaryings)
529 {
530 LoadShaderVar(&stream, &shaderVariable);
531 }
532 size = stream.readInt<size_t>();
533 allAttributes.resize(size);
534 for (sh::ShaderVariable &shaderVariable : allAttributes)
535 {
536 LoadShaderVar(&stream, &shaderVariable);
537 }
538 size = stream.readInt<size_t>();
539 activeAttributes.resize(size);
540 for (sh::ShaderVariable &shaderVariable : activeAttributes)
541 {
542 LoadShaderVar(&stream, &shaderVariable);
543 }
544 stream.readInt(&numViews);
545 break;
546 }
547 case gl::ShaderType::Fragment:
548 {
549 size = stream.readInt<size_t>();
550 inputVaryings.resize(size);
551 for (sh::ShaderVariable &shaderVariable : inputVaryings)
552 {
553 LoadShaderVar(&stream, &shaderVariable);
554 }
555 size = stream.readInt<size_t>();
556 activeOutputVariables.resize(size);
557 for (sh::ShaderVariable &shaderVariable : activeOutputVariables)
558 {
559 LoadShaderVar(&stream, &shaderVariable);
560 }
561 int advancedBlendEquationBits;
562 stream.readInt(&advancedBlendEquationBits);
563 advancedBlendEquations = gl::BlendEquationBitSet(advancedBlendEquationBits);
564 pixelLocalStorageFormats.resize(stream.readInt<size_t>());
565 stream.readBytes(reinterpret_cast<uint8_t *>(pixelLocalStorageFormats.data()),
566 pixelLocalStorageFormats.size());
567 break;
568 }
569 case gl::ShaderType::Geometry:
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 {
585 unsigned char value;
586 stream.readBytes(&value, 1);
587 geometryShaderInputPrimitiveType = static_cast<gl::PrimitiveMode>(value);
588 }
589
590 {
591 unsigned char value;
592 stream.readBytes(&value, 1);
593 geometryShaderOutputPrimitiveType = static_cast<gl::PrimitiveMode>(value);
594 }
595
596 {
597 int value;
598 stream.readInt(&value);
599 geometryShaderMaxVertices = static_cast<GLint>(value);
600 }
601
602 stream.readInt(&geometryShaderInvocations);
603 break;
604 }
605 case gl::ShaderType::TessControl:
606 {
607 size = stream.readInt<size_t>();
608 inputVaryings.resize(size);
609 for (sh::ShaderVariable &shaderVariable : inputVaryings)
610 {
611 LoadShaderVar(&stream, &shaderVariable);
612 }
613 size = stream.readInt<size_t>();
614 outputVaryings.resize(size);
615 for (sh::ShaderVariable &shaderVariable : outputVaryings)
616 {
617 LoadShaderVar(&stream, &shaderVariable);
618 }
619 stream.readInt(&tessControlShaderVertices);
620 break;
621 }
622 case gl::ShaderType::TessEvaluation:
623 {
624 unsigned int value;
625
626 size = stream.readInt<size_t>();
627 inputVaryings.resize(size);
628 for (sh::ShaderVariable &shaderVariable : inputVaryings)
629 {
630 LoadShaderVar(&stream, &shaderVariable);
631 }
632 size = stream.readInt<size_t>();
633 outputVaryings.resize(size);
634 for (sh::ShaderVariable &shaderVariable : outputVaryings)
635 {
636 LoadShaderVar(&stream, &shaderVariable);
637 }
638
639 stream.readInt(&value);
640 tessGenMode = (GLenum)value;
641
642 stream.readInt(&value);
643 tessGenSpacing = (GLenum)value;
644
645 stream.readInt(&value);
646 tessGenVertexOrder = (GLenum)value;
647
648 stream.readInt(&value);
649 tessGenPointMode = (GLenum)value;
650 break;
651 }
652 default:
653 UNREACHABLE();
654 }
655
656 stream.readString(&translatedSource);
657 stream.readVector(&compiledBinary);
658 }
659 } // namespace gl
660