mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-01 05:48:11 +03:00
The link job is split as such:
- Front-end link
- Back-end link
- Independent back-end link subtasks (typically native driver compile
jobs)
- Post-link finalization
Each step depends on the previous. These steps are executed as such:
1. Program::link calls into ProgramImpl::link
- ProgramImpl::link runs whatever needs the Context, such as releasing
resources
- ProgramImpl::link returns a LinkTask
2. Program::link implements a closure that calls the front-end link and
passes the results to the backend's LinkTask.
3. The LinkTask potentially returns a set of LinkSubTasks to be
scheduled by the worker pool
4. Once the link is resolved, the post-link finalization is run
In the above, steps 1 and 4 are done under the share group lock. Steps
2 and 3 can be done in threads or without holding the share group lock
if the backend supports it. Step 2 is not yet made independent of the
Context on some backends, and a frontend feature is used to make that
step either run on the main thread or as a worker thread.
Bug: angleproject:8297
Change-Id: I12f1e6bbaf365543dfcac969e166e0b5aa622104
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4808191
Reviewed-by: Charlie Lao <cclao@google.com>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@google.com>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
689 lines
24 KiB
C++
689 lines
24 KiB
C++
//
|
|
// Copyright 2022 The ANGLE Project Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
//
|
|
// CompiledShaderState.cpp:
|
|
// Implements CompiledShaderState, and helper functions for serializing and deserializing
|
|
// shader variables.
|
|
//
|
|
|
|
#include "common/CompiledShaderState.h"
|
|
|
|
#include "common/BinaryStream.h"
|
|
#include "common/utilities.h"
|
|
|
|
namespace gl
|
|
{
|
|
namespace
|
|
{
|
|
template <typename VarT>
|
|
std::vector<VarT> GetActiveShaderVariables(const std::vector<VarT> *variableList)
|
|
{
|
|
ASSERT(variableList);
|
|
std::vector<VarT> result;
|
|
for (size_t varIndex = 0; varIndex < variableList->size(); varIndex++)
|
|
{
|
|
const VarT &var = variableList->at(varIndex);
|
|
if (var.active)
|
|
{
|
|
result.push_back(var);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <typename VarT>
|
|
const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableList)
|
|
{
|
|
ASSERT(variableList);
|
|
return *variableList;
|
|
}
|
|
} // namespace
|
|
|
|
// true if varying x has a higher priority in packing than y
|
|
bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
|
|
{
|
|
if (x.type == y.type)
|
|
{
|
|
return x.getArraySizeProduct() > y.getArraySizeProduct();
|
|
}
|
|
|
|
// Special case for handling structs: we sort these to the end of the list
|
|
if (x.type == GL_NONE)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (y.type == GL_NONE)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
|
|
}
|
|
|
|
void WriteShaderVar(gl::BinaryOutputStream *stream, const sh::ShaderVariable &var)
|
|
{
|
|
stream->writeInt(var.type);
|
|
stream->writeInt(var.precision);
|
|
stream->writeString(var.name);
|
|
stream->writeString(var.mappedName);
|
|
stream->writeVector(var.arraySizes);
|
|
stream->writeBool(var.staticUse);
|
|
stream->writeBool(var.active);
|
|
stream->writeInt<size_t>(var.fields.size());
|
|
for (const sh::ShaderVariable &shaderVariable : var.fields)
|
|
{
|
|
WriteShaderVar(stream, shaderVariable);
|
|
}
|
|
stream->writeString(var.structOrBlockName);
|
|
stream->writeString(var.mappedStructOrBlockName);
|
|
stream->writeBool(var.isRowMajorLayout);
|
|
stream->writeInt(var.location);
|
|
stream->writeBool(var.hasImplicitLocation);
|
|
stream->writeInt(var.binding);
|
|
stream->writeInt(var.imageUnitFormat);
|
|
stream->writeInt(var.offset);
|
|
stream->writeBool(var.rasterOrdered);
|
|
stream->writeBool(var.readonly);
|
|
stream->writeBool(var.writeonly);
|
|
stream->writeBool(var.isFragmentInOut);
|
|
stream->writeInt(var.index);
|
|
stream->writeBool(var.yuv);
|
|
stream->writeEnum(var.interpolation);
|
|
stream->writeBool(var.isInvariant);
|
|
stream->writeBool(var.isShaderIOBlock);
|
|
stream->writeBool(var.isPatch);
|
|
stream->writeBool(var.texelFetchStaticUse);
|
|
stream->writeInt(var.getFlattenedOffsetInParentArrays());
|
|
stream->writeInt(var.id);
|
|
}
|
|
|
|
void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var)
|
|
{
|
|
var->type = stream->readInt<GLenum>();
|
|
var->precision = stream->readInt<GLenum>();
|
|
stream->readString(&var->name);
|
|
stream->readString(&var->mappedName);
|
|
stream->readVector(&var->arraySizes);
|
|
var->staticUse = stream->readBool();
|
|
var->active = stream->readBool();
|
|
size_t elementCount = stream->readInt<size_t>();
|
|
var->fields.resize(elementCount);
|
|
for (sh::ShaderVariable &variable : var->fields)
|
|
{
|
|
LoadShaderVar(stream, &variable);
|
|
}
|
|
stream->readString(&var->structOrBlockName);
|
|
stream->readString(&var->mappedStructOrBlockName);
|
|
var->isRowMajorLayout = stream->readBool();
|
|
var->location = stream->readInt<int>();
|
|
var->hasImplicitLocation = stream->readBool();
|
|
var->binding = stream->readInt<int>();
|
|
var->imageUnitFormat = stream->readInt<GLenum>();
|
|
var->offset = stream->readInt<int>();
|
|
var->rasterOrdered = stream->readBool();
|
|
var->readonly = stream->readBool();
|
|
var->writeonly = stream->readBool();
|
|
var->isFragmentInOut = stream->readBool();
|
|
var->index = stream->readInt<int>();
|
|
var->yuv = stream->readBool();
|
|
var->interpolation = stream->readEnum<sh::InterpolationType>();
|
|
var->isInvariant = stream->readBool();
|
|
var->isShaderIOBlock = stream->readBool();
|
|
var->isPatch = stream->readBool();
|
|
var->texelFetchStaticUse = stream->readBool();
|
|
var->setParentArrayIndex(stream->readInt<int>());
|
|
var->id = stream->readInt<uint32_t>();
|
|
}
|
|
|
|
void WriteShInterfaceBlock(gl::BinaryOutputStream *stream, const sh::InterfaceBlock &block)
|
|
{
|
|
stream->writeString(block.name);
|
|
stream->writeString(block.mappedName);
|
|
stream->writeString(block.instanceName);
|
|
stream->writeInt(block.arraySize);
|
|
stream->writeEnum(block.layout);
|
|
stream->writeBool(block.isRowMajorLayout);
|
|
stream->writeInt(block.binding);
|
|
stream->writeBool(block.staticUse);
|
|
stream->writeBool(block.active);
|
|
stream->writeEnum(block.blockType);
|
|
stream->writeInt(block.id);
|
|
|
|
stream->writeInt<size_t>(block.fields.size());
|
|
for (const sh::ShaderVariable &shaderVariable : block.fields)
|
|
{
|
|
WriteShaderVar(stream, shaderVariable);
|
|
}
|
|
}
|
|
|
|
void LoadShInterfaceBlock(gl::BinaryInputStream *stream, sh::InterfaceBlock *block)
|
|
{
|
|
block->name = stream->readString();
|
|
block->mappedName = stream->readString();
|
|
block->instanceName = stream->readString();
|
|
block->arraySize = stream->readInt<unsigned int>();
|
|
block->layout = stream->readEnum<sh::BlockLayoutType>();
|
|
block->isRowMajorLayout = stream->readBool();
|
|
block->binding = stream->readInt<int>();
|
|
block->staticUse = stream->readBool();
|
|
block->active = stream->readBool();
|
|
block->blockType = stream->readEnum<sh::BlockType>();
|
|
block->id = stream->readInt<uint32_t>();
|
|
|
|
block->fields.resize(stream->readInt<size_t>());
|
|
for (sh::ShaderVariable &variable : block->fields)
|
|
{
|
|
LoadShaderVar(stream, &variable);
|
|
}
|
|
}
|
|
|
|
CompiledShaderState::CompiledShaderState(gl::ShaderType type)
|
|
: shaderType(type),
|
|
successfullyCompiled(false),
|
|
shaderVersion(100),
|
|
hasClipDistance(false),
|
|
hasDiscard(false),
|
|
enablesPerSampleShading(false),
|
|
numViews(-1),
|
|
geometryShaderInvocations(1),
|
|
tessControlShaderVertices(0),
|
|
tessGenMode(0),
|
|
tessGenSpacing(0),
|
|
tessGenVertexOrder(0),
|
|
tessGenPointMode(0)
|
|
{
|
|
localSize.fill(-1);
|
|
}
|
|
|
|
CompiledShaderState::~CompiledShaderState() {}
|
|
|
|
void CompiledShaderState::buildCompiledShaderState(const ShHandle compilerHandle,
|
|
const bool isBinaryOutput)
|
|
{
|
|
if (isBinaryOutput)
|
|
{
|
|
compiledBinary = sh::GetObjectBinaryBlob(compilerHandle);
|
|
}
|
|
else
|
|
{
|
|
translatedSource = sh::GetObjectCode(compilerHandle);
|
|
}
|
|
|
|
// Gather the shader information
|
|
shaderVersion = sh::GetShaderVersion(compilerHandle);
|
|
|
|
uniforms = GetShaderVariables(sh::GetUniforms(compilerHandle));
|
|
uniformBlocks = GetShaderVariables(sh::GetUniformBlocks(compilerHandle));
|
|
shaderStorageBlocks = GetShaderVariables(sh::GetShaderStorageBlocks(compilerHandle));
|
|
specConstUsageBits = SpecConstUsageBits(sh::GetShaderSpecConstUsageBits(compilerHandle));
|
|
|
|
switch (shaderType)
|
|
{
|
|
case gl::ShaderType::Compute:
|
|
{
|
|
allAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
|
|
activeAttributes = GetActiveShaderVariables(&allAttributes);
|
|
localSize = sh::GetComputeShaderLocalGroupSize(compilerHandle);
|
|
break;
|
|
}
|
|
case gl::ShaderType::Vertex:
|
|
{
|
|
outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
|
|
allAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
|
|
activeAttributes = GetActiveShaderVariables(&allAttributes);
|
|
hasClipDistance = sh::HasClipDistanceInVertexShader(compilerHandle);
|
|
numViews = sh::GetVertexShaderNumViews(compilerHandle);
|
|
break;
|
|
}
|
|
case gl::ShaderType::Fragment:
|
|
{
|
|
allAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
|
|
activeAttributes = GetActiveShaderVariables(&allAttributes);
|
|
inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
|
|
// TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
|
|
std::sort(inputVaryings.begin(), inputVaryings.end(), CompareShaderVar);
|
|
activeOutputVariables =
|
|
GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
|
|
hasDiscard = sh::HasDiscardInFragmentShader(compilerHandle);
|
|
enablesPerSampleShading = sh::EnablesPerSampleShading(compilerHandle);
|
|
advancedBlendEquations =
|
|
gl::BlendEquationBitSet(sh::GetAdvancedBlendEquations(compilerHandle));
|
|
break;
|
|
}
|
|
case gl::ShaderType::Geometry:
|
|
{
|
|
inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
|
|
outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
|
|
|
|
if (sh::HasValidGeometryShaderInputPrimitiveType(compilerHandle))
|
|
{
|
|
geometryShaderInputPrimitiveType = gl::FromGLenum<gl::PrimitiveMode>(
|
|
sh::GetGeometryShaderInputPrimitiveType(compilerHandle));
|
|
}
|
|
if (sh::HasValidGeometryShaderOutputPrimitiveType(compilerHandle))
|
|
{
|
|
geometryShaderOutputPrimitiveType = gl::FromGLenum<gl::PrimitiveMode>(
|
|
sh::GetGeometryShaderOutputPrimitiveType(compilerHandle));
|
|
}
|
|
if (sh::HasValidGeometryShaderMaxVertices(compilerHandle))
|
|
{
|
|
geometryShaderMaxVertices = sh::GetGeometryShaderMaxVertices(compilerHandle);
|
|
}
|
|
geometryShaderInvocations = sh::GetGeometryShaderInvocations(compilerHandle);
|
|
break;
|
|
}
|
|
case gl::ShaderType::TessControl:
|
|
{
|
|
inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
|
|
outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
|
|
tessControlShaderVertices = sh::GetTessControlShaderVertices(compilerHandle);
|
|
break;
|
|
}
|
|
case gl::ShaderType::TessEvaluation:
|
|
{
|
|
inputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
|
|
outputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
|
|
if (sh::HasValidTessGenMode(compilerHandle))
|
|
{
|
|
tessGenMode = sh::GetTessGenMode(compilerHandle);
|
|
}
|
|
if (sh::HasValidTessGenSpacing(compilerHandle))
|
|
{
|
|
tessGenSpacing = sh::GetTessGenSpacing(compilerHandle);
|
|
}
|
|
if (sh::HasValidTessGenVertexOrder(compilerHandle))
|
|
{
|
|
tessGenVertexOrder = sh::GetTessGenVertexOrder(compilerHandle);
|
|
}
|
|
if (sh::HasValidTessGenPointMode(compilerHandle))
|
|
{
|
|
tessGenPointMode = sh::GetTessGenPointMode(compilerHandle);
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
}
|
|
|
|
void CompiledShaderState::serialize(gl::BinaryOutputStream &stream) const
|
|
{
|
|
stream.writeInt(shaderVersion);
|
|
|
|
stream.writeInt(uniforms.size());
|
|
for (const sh::ShaderVariable &shaderVariable : uniforms)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
|
|
stream.writeInt(uniformBlocks.size());
|
|
for (const sh::InterfaceBlock &interfaceBlock : uniformBlocks)
|
|
{
|
|
WriteShInterfaceBlock(&stream, interfaceBlock);
|
|
}
|
|
|
|
stream.writeInt(shaderStorageBlocks.size());
|
|
for (const sh::InterfaceBlock &interfaceBlock : shaderStorageBlocks)
|
|
{
|
|
WriteShInterfaceBlock(&stream, interfaceBlock);
|
|
}
|
|
|
|
stream.writeInt(specConstUsageBits.bits());
|
|
|
|
switch (shaderType)
|
|
{
|
|
case gl::ShaderType::Compute:
|
|
{
|
|
stream.writeInt(allAttributes.size());
|
|
for (const sh::ShaderVariable &shaderVariable : allAttributes)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
stream.writeInt(activeAttributes.size());
|
|
for (const sh::ShaderVariable &shaderVariable : activeAttributes)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
stream.writeInt(localSize[0]);
|
|
stream.writeInt(localSize[1]);
|
|
stream.writeInt(localSize[2]);
|
|
break;
|
|
}
|
|
|
|
case gl::ShaderType::Vertex:
|
|
{
|
|
stream.writeInt(outputVaryings.size());
|
|
for (const sh::ShaderVariable &shaderVariable : outputVaryings)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
stream.writeInt(allAttributes.size());
|
|
for (const sh::ShaderVariable &shaderVariable : allAttributes)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
stream.writeInt(activeAttributes.size());
|
|
for (const sh::ShaderVariable &shaderVariable : activeAttributes)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
stream.writeBool(hasClipDistance);
|
|
stream.writeInt(numViews);
|
|
break;
|
|
}
|
|
case gl::ShaderType::Fragment:
|
|
{
|
|
stream.writeInt(inputVaryings.size());
|
|
for (const sh::ShaderVariable &shaderVariable : inputVaryings)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
stream.writeInt(activeOutputVariables.size());
|
|
for (const sh::ShaderVariable &shaderVariable : activeOutputVariables)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
stream.writeBool(hasDiscard);
|
|
stream.writeBool(enablesPerSampleShading);
|
|
stream.writeInt(advancedBlendEquations.bits());
|
|
break;
|
|
}
|
|
case gl::ShaderType::Geometry:
|
|
{
|
|
bool valid;
|
|
|
|
stream.writeInt(inputVaryings.size());
|
|
for (const sh::ShaderVariable &shaderVariable : inputVaryings)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
stream.writeInt(outputVaryings.size());
|
|
for (const sh::ShaderVariable &shaderVariable : outputVaryings)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
|
|
valid = (bool)geometryShaderInputPrimitiveType.valid();
|
|
stream.writeBool(valid);
|
|
if (valid)
|
|
{
|
|
unsigned char value = (unsigned char)geometryShaderInputPrimitiveType.value();
|
|
stream.writeBytes(&value, 1);
|
|
}
|
|
valid = (bool)geometryShaderOutputPrimitiveType.valid();
|
|
stream.writeBool(valid);
|
|
if (valid)
|
|
{
|
|
unsigned char value = (unsigned char)geometryShaderOutputPrimitiveType.value();
|
|
stream.writeBytes(&value, 1);
|
|
}
|
|
valid = geometryShaderMaxVertices.valid();
|
|
stream.writeBool(valid);
|
|
if (valid)
|
|
{
|
|
int value = (int)geometryShaderMaxVertices.value();
|
|
stream.writeInt(value);
|
|
}
|
|
|
|
stream.writeInt(geometryShaderInvocations);
|
|
break;
|
|
}
|
|
case gl::ShaderType::TessControl:
|
|
{
|
|
stream.writeInt(inputVaryings.size());
|
|
for (const sh::ShaderVariable &shaderVariable : inputVaryings)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
stream.writeInt(outputVaryings.size());
|
|
for (const sh::ShaderVariable &shaderVariable : outputVaryings)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
stream.writeInt(tessControlShaderVertices);
|
|
break;
|
|
}
|
|
case gl::ShaderType::TessEvaluation:
|
|
{
|
|
unsigned int value;
|
|
|
|
stream.writeInt(inputVaryings.size());
|
|
for (const sh::ShaderVariable &shaderVariable : inputVaryings)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
stream.writeInt(outputVaryings.size());
|
|
for (const sh::ShaderVariable &shaderVariable : outputVaryings)
|
|
{
|
|
WriteShaderVar(&stream, shaderVariable);
|
|
}
|
|
|
|
value = (unsigned int)(tessGenMode);
|
|
stream.writeInt(value);
|
|
|
|
value = (unsigned int)tessGenSpacing;
|
|
stream.writeInt(value);
|
|
|
|
value = (unsigned int)tessGenVertexOrder;
|
|
stream.writeInt(value);
|
|
|
|
value = (unsigned int)tessGenPointMode;
|
|
stream.writeInt(value);
|
|
break;
|
|
}
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
|
|
stream.writeVector(compiledBinary);
|
|
}
|
|
|
|
void CompiledShaderState::deserialize(gl::BinaryInputStream &stream)
|
|
{
|
|
stream.readInt(&shaderVersion);
|
|
|
|
size_t size;
|
|
size = stream.readInt<size_t>();
|
|
uniforms.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : uniforms)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
|
|
size = stream.readInt<size_t>();
|
|
uniformBlocks.resize(size);
|
|
for (sh::InterfaceBlock &interfaceBlock : uniformBlocks)
|
|
{
|
|
LoadShInterfaceBlock(&stream, &interfaceBlock);
|
|
}
|
|
|
|
size = stream.readInt<size_t>();
|
|
shaderStorageBlocks.resize(size);
|
|
for (sh::InterfaceBlock &interfaceBlock : shaderStorageBlocks)
|
|
{
|
|
LoadShInterfaceBlock(&stream, &interfaceBlock);
|
|
}
|
|
|
|
specConstUsageBits = SpecConstUsageBits(stream.readInt<uint32_t>());
|
|
|
|
switch (shaderType)
|
|
{
|
|
case gl::ShaderType::Compute:
|
|
{
|
|
size = stream.readInt<size_t>();
|
|
allAttributes.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : allAttributes)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
size = stream.readInt<size_t>();
|
|
activeAttributes.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : activeAttributes)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
stream.readInt(&localSize[0]);
|
|
stream.readInt(&localSize[1]);
|
|
stream.readInt(&localSize[2]);
|
|
break;
|
|
}
|
|
case gl::ShaderType::Vertex:
|
|
{
|
|
size = stream.readInt<size_t>();
|
|
outputVaryings.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : outputVaryings)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
size = stream.readInt<size_t>();
|
|
allAttributes.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : allAttributes)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
size = stream.readInt<size_t>();
|
|
activeAttributes.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : activeAttributes)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
stream.readBool(&hasClipDistance);
|
|
stream.readInt(&numViews);
|
|
break;
|
|
}
|
|
case gl::ShaderType::Fragment:
|
|
{
|
|
size = stream.readInt<size_t>();
|
|
inputVaryings.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : inputVaryings)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
size = stream.readInt<size_t>();
|
|
activeOutputVariables.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : activeOutputVariables)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
stream.readBool(&hasDiscard);
|
|
stream.readBool(&enablesPerSampleShading);
|
|
int advancedBlendEquationBits;
|
|
stream.readInt(&advancedBlendEquationBits);
|
|
advancedBlendEquations = gl::BlendEquationBitSet(advancedBlendEquationBits);
|
|
break;
|
|
}
|
|
case gl::ShaderType::Geometry:
|
|
{
|
|
bool valid;
|
|
|
|
size = stream.readInt<size_t>();
|
|
inputVaryings.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : inputVaryings)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
size = stream.readInt<size_t>();
|
|
outputVaryings.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : outputVaryings)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
|
|
stream.readBool(&valid);
|
|
if (valid)
|
|
{
|
|
unsigned char value;
|
|
stream.readBytes(&value, 1);
|
|
geometryShaderInputPrimitiveType = static_cast<gl::PrimitiveMode>(value);
|
|
}
|
|
else
|
|
{
|
|
geometryShaderInputPrimitiveType.reset();
|
|
}
|
|
|
|
stream.readBool(&valid);
|
|
if (valid)
|
|
{
|
|
unsigned char value;
|
|
stream.readBytes(&value, 1);
|
|
geometryShaderOutputPrimitiveType = static_cast<gl::PrimitiveMode>(value);
|
|
}
|
|
else
|
|
{
|
|
geometryShaderOutputPrimitiveType.reset();
|
|
}
|
|
|
|
stream.readBool(&valid);
|
|
if (valid)
|
|
{
|
|
int value;
|
|
stream.readInt(&value);
|
|
geometryShaderMaxVertices = static_cast<GLint>(value);
|
|
}
|
|
else
|
|
{
|
|
geometryShaderMaxVertices.reset();
|
|
}
|
|
|
|
stream.readInt(&geometryShaderInvocations);
|
|
break;
|
|
}
|
|
case gl::ShaderType::TessControl:
|
|
{
|
|
size = stream.readInt<size_t>();
|
|
inputVaryings.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : inputVaryings)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
size = stream.readInt<size_t>();
|
|
outputVaryings.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : outputVaryings)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
stream.readInt(&tessControlShaderVertices);
|
|
break;
|
|
}
|
|
case gl::ShaderType::TessEvaluation:
|
|
{
|
|
unsigned int value;
|
|
|
|
size = stream.readInt<size_t>();
|
|
inputVaryings.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : inputVaryings)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
size = stream.readInt<size_t>();
|
|
outputVaryings.resize(size);
|
|
for (sh::ShaderVariable &shaderVariable : outputVaryings)
|
|
{
|
|
LoadShaderVar(&stream, &shaderVariable);
|
|
}
|
|
|
|
stream.readInt(&value);
|
|
tessGenMode = (GLenum)value;
|
|
|
|
stream.readInt(&value);
|
|
tessGenSpacing = (GLenum)value;
|
|
|
|
stream.readInt(&value);
|
|
tessGenVertexOrder = (GLenum)value;
|
|
|
|
stream.readInt(&value);
|
|
tessGenPointMode = (GLenum)value;
|
|
break;
|
|
}
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
|
|
stream.readVector(&compiledBinary);
|
|
}
|
|
} // namespace gl
|