Commit fecd1afc by Tim Van Patten Committed by Commit Bot

Vulkan: Move necessary members from ProgramState to ProgramExecutable

ProgramPipeline's need to be able to link Programs before drawing, even if the Program's previous linkProgram() failed. To work towards this, some ProgramState members are being moved to ProgramExecutable so they can be saved when linkProgram() succeeds and not overwritten by any subsequent linkProgram() attempts that may fail. This also allows the second half of this change, which is to pass in the Program's ProgramExecutable to GlslangAssignLocations() and GlslangWrapperVk::TransformSpirV() so the values saved from the last successful linkProgram() are used. Bug: angleproject:4514 Test: CQ Change-Id: I68aa429be76c0c6e1b886be09a12200217fcc7ab Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2181448 Commit-Queue: Tim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 39d187b8
...@@ -746,7 +746,7 @@ struct Program::LinkingState ...@@ -746,7 +746,7 @@ struct Program::LinkingState
const char *const g_fakepath = "C:\\fakepath"; const char *const g_fakepath = "C:\\fakepath";
// InfoLog implementation. // InfoLog implementation.
InfoLog::InfoLog() {} InfoLog::InfoLog() : mLazyStream(nullptr) {}
InfoLog::~InfoLog() {} InfoLog::~InfoLog() {}
...@@ -1079,10 +1079,7 @@ ProgramState::ProgramState() ...@@ -1079,10 +1079,7 @@ ProgramState::ProgramState()
: mLabel(), : mLabel(),
mAttachedShaders{}, mAttachedShaders{},
mAttachedShadersMarkedForDetach{}, mAttachedShadersMarkedForDetach{},
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
mDefaultUniformRange(0, 0), mDefaultUniformRange(0, 0),
mSamplerUniformRange(0, 0),
mImageUniformRange(0, 0),
mAtomicCounterUniformRange(0, 0), mAtomicCounterUniformRange(0, 0),
mBinaryRetrieveableHint(false), mBinaryRetrieveableHint(false),
mSeparable(false), mSeparable(false),
...@@ -1123,12 +1120,12 @@ Shader *ProgramState::getAttachedShader(ShaderType shaderType) const ...@@ -1123,12 +1120,12 @@ Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
size_t ProgramState::getTransformFeedbackBufferCount() const size_t ProgramState::getTransformFeedbackBufferCount() const
{ {
return mTransformFeedbackStrides.size(); return mExecutable->mTransformFeedbackStrides.size();
} }
GLuint ProgramState::getUniformIndexFromName(const std::string &name) const GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
{ {
return GetResourceIndexFromName(mUniforms, name); return GetResourceIndexFromName(mExecutable->mUniforms, name);
} }
GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
...@@ -1155,41 +1152,41 @@ Optional<GLuint> ProgramState::getSamplerIndex(UniformLocation location) const ...@@ -1155,41 +1152,41 @@ Optional<GLuint> ProgramState::getSamplerIndex(UniformLocation location) const
bool ProgramState::isSamplerUniformIndex(GLuint index) const bool ProgramState::isSamplerUniformIndex(GLuint index) const
{ {
return mSamplerUniformRange.contains(index); return mExecutable->mSamplerUniformRange.contains(index);
} }
GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
{ {
ASSERT(isSamplerUniformIndex(uniformIndex)); ASSERT(isSamplerUniformIndex(uniformIndex));
return uniformIndex - mSamplerUniformRange.low(); return uniformIndex - mExecutable->mSamplerUniformRange.low();
} }
GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
{ {
ASSERT(samplerIndex < mSamplerUniformRange.length()); ASSERT(samplerIndex < mExecutable->mSamplerUniformRange.length());
return samplerIndex + mSamplerUniformRange.low(); return samplerIndex + mExecutable->mSamplerUniformRange.low();
} }
bool ProgramState::isImageUniformIndex(GLuint index) const bool ProgramState::isImageUniformIndex(GLuint index) const
{ {
return mImageUniformRange.contains(index); return mExecutable->mImageUniformRange.contains(index);
} }
GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
{ {
ASSERT(isImageUniformIndex(uniformIndex)); ASSERT(isImageUniformIndex(uniformIndex));
return uniformIndex - mImageUniformRange.low(); return uniformIndex - mExecutable->mImageUniformRange.low();
} }
GLuint ProgramState::getUniformIndexFromImageIndex(GLuint imageIndex) const GLuint ProgramState::getUniformIndexFromImageIndex(GLuint imageIndex) const
{ {
ASSERT(imageIndex < mImageUniformRange.length()); ASSERT(imageIndex < mExecutable->mImageUniformRange.length());
return imageIndex + mImageUniformRange.low(); return imageIndex + mExecutable->mImageUniformRange.low();
} }
GLuint ProgramState::getAttributeLocation(const std::string &name) const GLuint ProgramState::getAttributeLocation(const std::string &name) const
{ {
for (const sh::ShaderVariable &attribute : mProgramInputs) for (const sh::ShaderVariable &attribute : mExecutable->mProgramInputs)
{ {
if (attribute.name == name) if (attribute.name == name)
{ {
...@@ -1386,6 +1383,7 @@ void Program::bindFragmentOutputIndex(GLuint index, const char *name) ...@@ -1386,6 +1383,7 @@ void Program::bindFragmentOutputIndex(GLuint index, const char *name)
} }
angle::Result Program::linkMergedVaryings(const Context *context, angle::Result Program::linkMergedVaryings(const Context *context,
const ProgramExecutable &executable,
const ProgramMergedVaryings &mergedVaryings) const ProgramMergedVaryings &mergedVaryings)
{ {
ShaderType tfStage = ShaderType tfStage =
...@@ -1398,7 +1396,7 @@ angle::Result Program::linkMergedVaryings(const Context *context, ...@@ -1398,7 +1396,7 @@ angle::Result Program::linkMergedVaryings(const Context *context,
return angle::Result::Stop; return angle::Result::Stop;
} }
if (!mResources->varyingPacking.collectAndPackUserVaryings( if (!executable.mResources->varyingPacking.collectAndPackUserVaryings(
infoLog, mergedVaryings, mState.getTransformFeedbackVaryingNames(), isSeparable())) infoLog, mergedVaryings, mState.getTransformFeedbackVaryingNames(), isSeparable()))
{ {
return angle::Result::Stop; return angle::Result::Stop;
...@@ -1464,14 +1462,15 @@ angle::Result Program::link(const Context *context) ...@@ -1464,14 +1462,15 @@ angle::Result Program::link(const Context *context)
if (mState.mAttachedShaders[ShaderType::Compute]) if (mState.mAttachedShaders[ShaderType::Compute])
{ {
mResources.reset(new ProgramLinkedResources( mState.mExecutable->mResources.reset(new ProgramLinkedResources(
0, PackMode::ANGLE_RELAXED, &mState.mUniformBlocks, &mState.mUniforms, 0, PackMode::ANGLE_RELAXED, &mState.mExecutable->mUniformBlocks,
&mState.mShaderStorageBlocks, &mState.mBufferVariables, &mState.mAtomicCounterBuffers)); &mState.mExecutable->mUniforms, &mState.mExecutable->mShaderStorageBlocks,
&mState.mBufferVariables, &mState.mExecutable->mAtomicCounterBuffers));
GLuint combinedImageUniforms = 0u; GLuint combinedImageUniforms = 0u;
if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog, if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
mState.mUniformLocationBindings, &combinedImageUniforms, mState.mUniformLocationBindings, &combinedImageUniforms,
&mResources->unusedUniforms)) &mState.mExecutable->getResources().unusedUniforms))
{ {
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -1500,8 +1499,9 @@ angle::Result Program::link(const Context *context) ...@@ -1500,8 +1499,9 @@ angle::Result Program::link(const Context *context)
return angle::Result::Continue; return angle::Result::Continue;
} }
InitUniformBlockLinker(mState, &mResources->uniformBlockLinker); InitUniformBlockLinker(mState, &mState.mExecutable->getResources().uniformBlockLinker);
InitShaderStorageBlockLinker(mState, &mResources->shaderStorageBlockLinker); InitShaderStorageBlockLinker(mState,
&mState.mExecutable->getResources().shaderStorageBlockLinker);
} }
else else
{ {
...@@ -1518,10 +1518,11 @@ angle::Result Program::link(const Context *context) ...@@ -1518,10 +1518,11 @@ angle::Result Program::link(const Context *context)
packMode = PackMode::WEBGL_STRICT; packMode = PackMode::WEBGL_STRICT;
} }
mResources.reset(new ProgramLinkedResources( mState.mExecutable->mResources.reset(new ProgramLinkedResources(
static_cast<GLuint>(data.getCaps().maxVaryingVectors), packMode, &mState.mUniformBlocks, static_cast<GLuint>(data.getCaps().maxVaryingVectors), packMode,
&mState.mUniforms, &mState.mShaderStorageBlocks, &mState.mBufferVariables, &mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
&mState.mAtomicCounterBuffers)); &mState.mExecutable->mShaderStorageBlocks, &mState.mBufferVariables,
&mState.mExecutable->mAtomicCounterBuffers));
if (!linkAttributes(context, infoLog)) if (!linkAttributes(context, infoLog))
{ {
...@@ -1536,7 +1537,7 @@ angle::Result Program::link(const Context *context) ...@@ -1536,7 +1537,7 @@ angle::Result Program::link(const Context *context)
GLuint combinedImageUniforms = 0u; GLuint combinedImageUniforms = 0u;
if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog, if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
mState.mUniformLocationBindings, &combinedImageUniforms, mState.mUniformLocationBindings, &combinedImageUniforms,
&mResources->unusedUniforms)) &mState.mExecutable->getResources().unusedUniforms))
{ {
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -1574,20 +1575,21 @@ angle::Result Program::link(const Context *context) ...@@ -1574,20 +1575,21 @@ angle::Result Program::link(const Context *context)
fragmentShader->hasEarlyFragmentTestsOptimization(); fragmentShader->hasEarlyFragmentTestsOptimization();
} }
InitUniformBlockLinker(mState, &mResources->uniformBlockLinker); InitUniformBlockLinker(mState, &mState.mExecutable->getResources().uniformBlockLinker);
InitShaderStorageBlockLinker(mState, &mResources->shaderStorageBlockLinker); InitShaderStorageBlockLinker(mState,
&mState.mExecutable->getResources().shaderStorageBlockLinker);
ProgramPipeline *programPipeline = context->getState().getProgramPipeline(); ProgramPipeline *programPipeline = context->getState().getProgramPipeline();
if (programPipeline && programPipeline->usesShaderProgram(id())) if (programPipeline && programPipeline->usesShaderProgram(id()))
{ {
const ProgramMergedVaryings &mergedVaryings = const ProgramMergedVaryings &mergedVaryings =
context->getState().getProgramPipeline()->getMergedVaryings(); context->getState().getProgramPipeline()->getMergedVaryings();
ANGLE_TRY(linkMergedVaryings(context, mergedVaryings)); ANGLE_TRY(linkMergedVaryings(context, *mState.mExecutable, mergedVaryings));
} }
else else
{ {
const ProgramMergedVaryings &mergedVaryings = getMergedVaryings(); const ProgramMergedVaryings &mergedVaryings = getMergedVaryings();
ANGLE_TRY(linkMergedVaryings(context, mergedVaryings)); ANGLE_TRY(linkMergedVaryings(context, *mState.mExecutable, mergedVaryings));
} }
} }
...@@ -1596,8 +1598,8 @@ angle::Result Program::link(const Context *context) ...@@ -1596,8 +1598,8 @@ angle::Result Program::link(const Context *context)
mLinkingState.reset(new LinkingState()); mLinkingState.reset(new LinkingState());
mLinkingState->linkingFromBinary = false; mLinkingState->linkingFromBinary = false;
mLinkingState->programHash = programHash; mLinkingState->programHash = programHash;
mLinkingState->linkEvent = mProgram->link(context, *mResources, infoLog); mLinkingState->linkEvent = mProgram->link(context, mState.mExecutable->getResources(), infoLog);
mLinkResolved = false; mLinkResolved = false;
// Must be after mProgram->link() to avoid misleading the linker about output variables. // Must be after mProgram->link() to avoid misleading the linker about output variables.
mState.updateProgramInterfaceInputs(); mState.updateProgramInterfaceInputs();
...@@ -1649,7 +1651,7 @@ void Program::resolveLinkImpl(const Context *context) ...@@ -1649,7 +1651,7 @@ void Program::resolveLinkImpl(const Context *context)
MemoryProgramCache *cache = context->getMemoryProgramCache(); MemoryProgramCache *cache = context->getMemoryProgramCache();
// TODO: http://anglebug.com/4530: Enable program caching for separable programs // TODO: http://anglebug.com/4530: Enable program caching for separable programs
if (cache && !isSeparable() && if (cache && !isSeparable() &&
(mState.mLinkedTransformFeedbackVaryings.empty() || (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
!context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)) !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
{ {
if (cache->putProgram(linkingState->programHash, context, this) == angle::Result::Stop) if (cache->putProgram(linkingState->programHash, context, this) == angle::Result::Stop)
...@@ -1676,23 +1678,25 @@ void Program::updateLinkedShaderStages() ...@@ -1676,23 +1678,25 @@ void Program::updateLinkedShaderStages()
void ProgramState::updateTransformFeedbackStrides() void ProgramState::updateTransformFeedbackStrides()
{ {
if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS) if (mExecutable->mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
{ {
mTransformFeedbackStrides.resize(1); mExecutable->mTransformFeedbackStrides.resize(1);
size_t totalSize = 0; size_t totalSize = 0;
for (const TransformFeedbackVarying &varying : mLinkedTransformFeedbackVaryings) for (const TransformFeedbackVarying &varying :
mExecutable->mLinkedTransformFeedbackVaryings)
{ {
totalSize += varying.size() * VariableExternalSize(varying.type); totalSize += varying.size() * VariableExternalSize(varying.type);
} }
mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize); mExecutable->mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize);
} }
else else
{ {
mTransformFeedbackStrides.resize(mLinkedTransformFeedbackVaryings.size()); mExecutable->mTransformFeedbackStrides.resize(
for (size_t i = 0; i < mLinkedTransformFeedbackVaryings.size(); i++) mExecutable->mLinkedTransformFeedbackVaryings.size());
for (size_t i = 0; i < mExecutable->mLinkedTransformFeedbackVaryings.size(); i++)
{ {
TransformFeedbackVarying &varying = mLinkedTransformFeedbackVaryings[i]; TransformFeedbackVarying &varying = mExecutable->mLinkedTransformFeedbackVaryings[i];
mTransformFeedbackStrides[i] = mExecutable->mTransformFeedbackStrides[i] =
static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type)); static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type));
} }
} }
...@@ -1735,7 +1739,7 @@ void ProgramState::updateProgramInterfaceInputs() ...@@ -1735,7 +1739,7 @@ void ProgramState::updateProgramInterfaceInputs()
// in uvec3 gl_GlobalInvocationID; // in uvec3 gl_GlobalInvocationID;
// in uint gl_LocalInvocationIndex; // in uint gl_LocalInvocationIndex;
// They are all vecs or uints, so no special handling is required. // They are all vecs or uints, so no special handling is required.
mProgramInputs.emplace_back(attribute); mExecutable->mProgramInputs.emplace_back(attribute);
} }
} }
else if (shader->getType() == ShaderType::Fragment) else if (shader->getType() == ShaderType::Fragment)
...@@ -1749,12 +1753,12 @@ void ProgramState::updateProgramInterfaceInputs() ...@@ -1749,12 +1753,12 @@ void ProgramState::updateProgramInterfaceInputs()
sh::ShaderVariable fieldVarying = sh::ShaderVariable(field); sh::ShaderVariable fieldVarying = sh::ShaderVariable(field);
fieldVarying.location = varying.location; fieldVarying.location = varying.location;
fieldVarying.name = varying.name + "." + field.name; fieldVarying.name = varying.name + "." + field.name;
mProgramInputs.emplace_back(fieldVarying); mExecutable->mProgramInputs.emplace_back(fieldVarying);
} }
} }
else else
{ {
mProgramInputs.emplace_back(varying); mExecutable->mProgramInputs.emplace_back(varying);
} }
} }
} }
...@@ -1788,12 +1792,12 @@ void ProgramState::updateProgramInterfaceOutputs() ...@@ -1788,12 +1792,12 @@ void ProgramState::updateProgramInterfaceOutputs()
sh::ShaderVariable fieldVarying = sh::ShaderVariable(field); sh::ShaderVariable fieldVarying = sh::ShaderVariable(field);
fieldVarying.location = varying.location; fieldVarying.location = varying.location;
fieldVarying.name = varying.name + "." + field.name; fieldVarying.name = varying.name + "." + field.name;
mOutputVariables.emplace_back(fieldVarying); mExecutable->mOutputVariables.emplace_back(fieldVarying);
} }
} }
else else
{ {
mOutputVariables.emplace_back(varying); mExecutable->mOutputVariables.emplace_back(varying);
} }
} }
} }
...@@ -1801,17 +1805,9 @@ void ProgramState::updateProgramInterfaceOutputs() ...@@ -1801,17 +1805,9 @@ void ProgramState::updateProgramInterfaceOutputs()
// Returns the program object to an unlinked state, before re-linking, or at destruction // Returns the program object to an unlinked state, before re-linking, or at destruction
void Program::unlink() void Program::unlink()
{ {
mState.mProgramInputs.clear();
mState.mLinkedTransformFeedbackVaryings.clear();
mState.mUniforms.clear();
mState.mUniformLocations.clear(); mState.mUniformLocations.clear();
mState.mUniformBlocks.clear();
mState.mBufferVariables.clear(); mState.mBufferVariables.clear();
mState.mShaderStorageBlocks.clear();
mState.mActiveUniformBlockBindings.reset(); mState.mActiveUniformBlockBindings.reset();
mState.mAtomicCounterBuffers.clear();
mState.mOutputVariables.clear();
mState.mOutputLocations.clear();
mState.mSecondaryOutputLocations.clear(); mState.mSecondaryOutputLocations.clear();
mState.mOutputVariableTypes.clear(); mState.mOutputVariableTypes.clear();
mState.mDrawBufferTypeMask.reset(); mState.mDrawBufferTypeMask.reset();
...@@ -1863,8 +1859,8 @@ angle::Result Program::loadBinary(const Context *context, ...@@ -1863,8 +1859,8 @@ angle::Result Program::loadBinary(const Context *context,
// Currently we require the full shader text to compute the program hash. // Currently we require the full shader text to compute the program hash.
// We could also store the binary in the internal program cache. // We could also store the binary in the internal program cache.
for (size_t uniformBlockIndex = 0; uniformBlockIndex < mState.mUniformBlocks.size(); for (size_t uniformBlockIndex = 0;
++uniformBlockIndex) uniformBlockIndex < mState.mExecutable->getActiveUniformBlockCount(); ++uniformBlockIndex)
{ {
mDirtyBits.set(uniformBlockIndex); mDirtyBits.set(uniformBlockIndex);
} }
...@@ -2039,8 +2035,8 @@ void Program::getActiveAttribute(GLuint index, ...@@ -2039,8 +2035,8 @@ void Program::getActiveAttribute(GLuint index,
return; return;
} }
ASSERT(index < mState.mProgramInputs.size()); ASSERT(index < mState.mExecutable->getProgramInputs().size());
const sh::ShaderVariable &attrib = mState.mProgramInputs[index]; const sh::ShaderVariable &attrib = mState.mExecutable->getProgramInputs()[index];
if (bufsize > 0) if (bufsize > 0)
{ {
...@@ -2060,7 +2056,7 @@ GLint Program::getActiveAttributeCount() const ...@@ -2060,7 +2056,7 @@ GLint Program::getActiveAttributeCount() const
return 0; return 0;
} }
return static_cast<GLint>(mState.mProgramInputs.size()); return static_cast<GLint>(mState.mExecutable->getProgramInputs().size());
} }
GLint Program::getActiveAttributeMaxLength() const GLint Program::getActiveAttributeMaxLength() const
...@@ -2073,7 +2069,7 @@ GLint Program::getActiveAttributeMaxLength() const ...@@ -2073,7 +2069,7 @@ GLint Program::getActiveAttributeMaxLength() const
size_t maxLength = 0; size_t maxLength = 0;
for (const sh::ShaderVariable &attrib : mState.mProgramInputs) for (const sh::ShaderVariable &attrib : mState.mExecutable->getProgramInputs())
{ {
maxLength = std::max(attrib.name.length() + 1, maxLength); maxLength = std::max(attrib.name.length() + 1, maxLength);
} }
...@@ -2084,7 +2080,7 @@ GLint Program::getActiveAttributeMaxLength() const ...@@ -2084,7 +2080,7 @@ GLint Program::getActiveAttributeMaxLength() const
const std::vector<sh::ShaderVariable> &Program::getAttributes() const const std::vector<sh::ShaderVariable> &Program::getAttributes() const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return mState.mProgramInputs; return mState.mExecutable->getProgramInputs();
} }
const std::vector<SamplerBinding> &Program::getSamplerBindings() const const std::vector<SamplerBinding> &Program::getSamplerBindings() const
...@@ -2123,8 +2119,8 @@ GLint Program::getGeometryShaderMaxVertices() const ...@@ -2123,8 +2119,8 @@ GLint Program::getGeometryShaderMaxVertices() const
const sh::ShaderVariable &Program::getInputResource(size_t index) const const sh::ShaderVariable &Program::getInputResource(size_t index) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
ASSERT(index < mState.mProgramInputs.size()); ASSERT(index < mState.mExecutable->getProgramInputs().size());
return mState.mProgramInputs[index]; return mState.mExecutable->getProgramInputs()[index];
} }
GLuint Program::getInputResourceIndex(const GLchar *name) const GLuint Program::getInputResourceIndex(const GLchar *name) const
...@@ -2132,7 +2128,7 @@ GLuint Program::getInputResourceIndex(const GLchar *name) const ...@@ -2132,7 +2128,7 @@ GLuint Program::getInputResourceIndex(const GLchar *name) const
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
const std::string nameString = StripLastArrayIndex(name); const std::string nameString = StripLastArrayIndex(name);
for (size_t index = 0; index < mState.mProgramInputs.size(); index++) for (size_t index = 0; index < mState.mExecutable->getProgramInputs().size(); index++)
{ {
sh::ShaderVariable resource = getInputResource(index); sh::ShaderVariable resource = getInputResource(index);
if (resource.name == nameString) if (resource.name == nameString)
...@@ -2160,7 +2156,7 @@ GLuint Program::getInputResourceMaxNameSize() const ...@@ -2160,7 +2156,7 @@ GLuint Program::getInputResourceMaxNameSize() const
{ {
GLint max = 0; GLint max = 0;
for (const sh::ShaderVariable &resource : mState.mProgramInputs) for (const sh::ShaderVariable &resource : mState.mExecutable->getProgramInputs())
{ {
max = getResourceMaxNameSize(resource, max); max = getResourceMaxNameSize(resource, max);
} }
...@@ -2172,7 +2168,7 @@ GLuint Program::getOutputResourceMaxNameSize() const ...@@ -2172,7 +2168,7 @@ GLuint Program::getOutputResourceMaxNameSize() const
{ {
GLint max = 0; GLint max = 0;
for (const sh::ShaderVariable &resource : mState.mOutputVariables) for (const sh::ShaderVariable &resource : mState.mExecutable->getOutputVariables())
{ {
max = getResourceMaxNameSize(resource, max); max = getResourceMaxNameSize(resource, max);
} }
...@@ -2233,7 +2229,7 @@ GLuint Program::getOutputResourceIndex(const GLchar *name) const ...@@ -2233,7 +2229,7 @@ GLuint Program::getOutputResourceIndex(const GLchar *name) const
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
const std::string nameString = StripLastArrayIndex(name); const std::string nameString = StripLastArrayIndex(name);
for (size_t index = 0; index < mState.mOutputVariables.size(); index++) for (size_t index = 0; index < mState.mExecutable->getOutputVariables().size(); index++)
{ {
sh::ShaderVariable resource = getOutputResource(index); sh::ShaderVariable resource = getOutputResource(index);
if (resource.name == nameString) if (resource.name == nameString)
...@@ -2248,7 +2244,7 @@ GLuint Program::getOutputResourceIndex(const GLchar *name) const ...@@ -2248,7 +2244,7 @@ GLuint Program::getOutputResourceIndex(const GLchar *name) const
size_t Program::getOutputResourceCount() const size_t Program::getOutputResourceCount() const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return (mLinked ? mState.mOutputVariables.size() : 0); return (mLinked ? mState.mExecutable->getOutputVariables().size() : 0);
} }
const std::vector<GLenum> &Program::getOutputVariableTypes() const const std::vector<GLenum> &Program::getOutputVariableTypes() const
...@@ -2306,8 +2302,8 @@ void Program::getUniformResourceName(GLuint index, ...@@ -2306,8 +2302,8 @@ void Program::getUniformResourceName(GLuint index,
GLchar *name) const GLchar *name) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
ASSERT(index < mState.mUniforms.size()); ASSERT(index < mState.mExecutable->getUniforms().size());
getResourceName(mState.mUniforms[index].name, bufSize, length, name); getResourceName(mState.mExecutable->getUniforms()[index].name, bufSize, length, name);
} }
void Program::getBufferVariableResourceName(GLuint index, void Program::getBufferVariableResourceName(GLuint index,
...@@ -2351,8 +2347,8 @@ const std::string Program::getOutputResourceName(GLuint index) const ...@@ -2351,8 +2347,8 @@ const std::string Program::getOutputResourceName(GLuint index) const
const sh::ShaderVariable &Program::getOutputResource(size_t index) const const sh::ShaderVariable &Program::getOutputResource(size_t index) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
ASSERT(index < mState.mOutputVariables.size()); ASSERT(index < mState.mExecutable->getOutputVariables().size());
return mState.mOutputVariables[index]; return mState.mExecutable->getOutputVariables()[index];
} }
const ProgramBindings &Program::getAttributeBindings() const const ProgramBindings &Program::getAttributeBindings() const
...@@ -2387,29 +2383,32 @@ ComponentTypeMask Program::getDrawBufferTypeMask() const ...@@ -2387,29 +2383,32 @@ ComponentTypeMask Program::getDrawBufferTypeMask() const
const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return mState.mTransformFeedbackStrides; return mState.mExecutable->getTransformFeedbackStrides();
} }
GLint Program::getFragDataLocation(const std::string &name) const GLint Program::getFragDataLocation(const std::string &name) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
GLint primaryLocation = GLint primaryLocation = GetVariableLocation(mState.mExecutable->getOutputVariables(),
GetVariableLocation(mState.mOutputVariables, mState.mOutputLocations, name); mState.mExecutable->getOutputLocations(), name);
if (primaryLocation != -1) if (primaryLocation != -1)
{ {
return primaryLocation; return primaryLocation;
} }
return GetVariableLocation(mState.mOutputVariables, mState.mSecondaryOutputLocations, name); return GetVariableLocation(mState.mExecutable->getOutputVariables(),
mState.mSecondaryOutputLocations, name);
} }
GLint Program::getFragDataIndex(const std::string &name) const GLint Program::getFragDataIndex(const std::string &name) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
if (GetVariableLocation(mState.mOutputVariables, mState.mOutputLocations, name) != -1) if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
mState.mExecutable->getOutputLocations(), name) != -1)
{ {
return 0; return 0;
} }
if (GetVariableLocation(mState.mOutputVariables, mState.mSecondaryOutputLocations, name) != -1) if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
mState.mSecondaryOutputLocations, name) != -1)
{ {
return 1; return 1;
} }
...@@ -2427,8 +2426,8 @@ void Program::getActiveUniform(GLuint index, ...@@ -2427,8 +2426,8 @@ void Program::getActiveUniform(GLuint index,
if (mLinked) if (mLinked)
{ {
// index must be smaller than getActiveUniformCount() // index must be smaller than getActiveUniformCount()
ASSERT(index < mState.mUniforms.size()); ASSERT(index < mState.mExecutable->getUniforms().size());
const LinkedUniform &uniform = mState.mUniforms[index]; const LinkedUniform &uniform = mState.mExecutable->getUniforms()[index];
if (bufsize > 0) if (bufsize > 0)
{ {
...@@ -2461,7 +2460,7 @@ GLint Program::getActiveUniformCount() const ...@@ -2461,7 +2460,7 @@ GLint Program::getActiveUniformCount() const
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
if (mLinked) if (mLinked)
{ {
return static_cast<GLint>(mState.mUniforms.size()); return static_cast<GLint>(mState.mExecutable->getUniforms().size());
} }
else else
{ {
...@@ -2482,7 +2481,7 @@ GLint Program::getActiveUniformMaxLength() const ...@@ -2482,7 +2481,7 @@ GLint Program::getActiveUniformMaxLength() const
if (mLinked) if (mLinked)
{ {
for (const LinkedUniform &uniform : mState.mUniforms) for (const LinkedUniform &uniform : mState.mExecutable->getUniforms())
{ {
if (!uniform.name.empty()) if (!uniform.name.empty())
{ {
...@@ -2513,7 +2512,7 @@ const LinkedUniform &Program::getUniformByLocation(UniformLocation location) con ...@@ -2513,7 +2512,7 @@ const LinkedUniform &Program::getUniformByLocation(UniformLocation location) con
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
ASSERT(location.value >= 0 && ASSERT(location.value >= 0 &&
static_cast<size_t>(location.value) < mState.mUniformLocations.size()); static_cast<size_t>(location.value) < mState.mUniformLocations.size());
return mState.mUniforms[mState.getUniformIndexFromLocation(location)]; return mState.mExecutable->getUniforms()[mState.getUniformIndexFromLocation(location)];
} }
const VariableLocation &Program::getUniformLocation(UniformLocation location) const const VariableLocation &Program::getUniformLocation(UniformLocation location) const
...@@ -2534,7 +2533,7 @@ const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const ...@@ -2534,7 +2533,7 @@ const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
UniformLocation Program::getUniformLocation(const std::string &name) const UniformLocation Program::getUniformLocation(const std::string &name) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return {GetVariableLocation(mState.mUniforms, mState.mUniformLocations, name)}; return {GetVariableLocation(mState.mExecutable->getUniforms(), mState.mUniformLocations, name)};
} }
GLuint Program::getUniformIndex(const std::string &name) const GLuint Program::getUniformIndex(const std::string &name) const
...@@ -3027,7 +3026,8 @@ void Program::getActiveUniformBlockName(const GLuint blockIndex, ...@@ -3027,7 +3026,8 @@ void Program::getActiveUniformBlockName(const GLuint blockIndex,
GLchar *blockName) const GLchar *blockName) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
GetInterfaceBlockName(blockIndex, mState.mUniformBlocks, bufSize, length, blockName); GetInterfaceBlockName(blockIndex, mState.mExecutable->getUniformBlocks(), bufSize, length,
blockName);
} }
void Program::getActiveShaderStorageBlockName(const GLuint blockIndex, void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
...@@ -3036,7 +3036,8 @@ void Program::getActiveShaderStorageBlockName(const GLuint blockIndex, ...@@ -3036,7 +3036,8 @@ void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
GLchar *blockName) const GLchar *blockName) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
GetInterfaceBlockName(blockIndex, mState.mShaderStorageBlocks, bufSize, length, blockName); GetInterfaceBlockName(blockIndex, mState.mExecutable->getShaderStorageBlocks(), bufSize, length,
blockName);
} }
template <typename T> template <typename T>
...@@ -3062,45 +3063,45 @@ GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resour ...@@ -3062,45 +3063,45 @@ GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resour
GLint Program::getActiveUniformBlockMaxNameLength() const GLint Program::getActiveUniformBlockMaxNameLength() const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return getActiveInterfaceBlockMaxNameLength(mState.mUniformBlocks); return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getUniformBlocks());
} }
GLint Program::getActiveShaderStorageBlockMaxNameLength() const GLint Program::getActiveShaderStorageBlockMaxNameLength() const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return getActiveInterfaceBlockMaxNameLength(mState.mShaderStorageBlocks); return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getShaderStorageBlocks());
} }
GLuint Program::getUniformBlockIndex(const std::string &name) const GLuint Program::getUniformBlockIndex(const std::string &name) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return GetInterfaceBlockIndex(mState.mUniformBlocks, name); return GetInterfaceBlockIndex(mState.mExecutable->getUniformBlocks(), name);
} }
GLuint Program::getShaderStorageBlockIndex(const std::string &name) const GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return GetInterfaceBlockIndex(mState.mShaderStorageBlocks, name); return GetInterfaceBlockIndex(mState.mExecutable->getShaderStorageBlocks(), name);
} }
const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
ASSERT(index < static_cast<GLuint>(mState.mUniformBlocks.size())); ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount()));
return mState.mUniformBlocks[index]; return mState.mExecutable->getUniformBlocks()[index];
} }
const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
ASSERT(index < static_cast<GLuint>(mState.mShaderStorageBlocks.size())); ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount()));
return mState.mShaderStorageBlocks[index]; return mState.mExecutable->getShaderStorageBlocks()[index];
} }
void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding) void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
mState.mUniformBlocks[uniformBlockIndex].binding = uniformBlockBinding; mState.mExecutable->mUniformBlocks[uniformBlockIndex].binding = uniformBlockBinding;
mState.mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlockBinding != 0); mState.mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlockBinding != 0);
mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex); mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex);
} }
...@@ -3128,7 +3129,7 @@ void Program::setTransformFeedbackVaryings(GLsizei count, ...@@ -3128,7 +3129,7 @@ void Program::setTransformFeedbackVaryings(GLsizei count,
mState.mTransformFeedbackVaryingNames[i] = varyings[i]; mState.mTransformFeedbackVaryingNames[i] = varyings[i];
} }
mState.mTransformFeedbackBufferMode = bufferMode; mState.mExecutable->mTransformFeedbackBufferMode = bufferMode;
} }
void Program::getTransformFeedbackVarying(GLuint index, void Program::getTransformFeedbackVarying(GLuint index,
...@@ -3141,8 +3142,8 @@ void Program::getTransformFeedbackVarying(GLuint index, ...@@ -3141,8 +3142,8 @@ void Program::getTransformFeedbackVarying(GLuint index,
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
if (mLinked) if (mLinked)
{ {
ASSERT(index < mState.mLinkedTransformFeedbackVaryings.size()); ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
const auto &var = mState.mLinkedTransformFeedbackVaryings[index]; const auto &var = mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
std::string varName = var.nameWithArrayIndex(); std::string varName = var.nameWithArrayIndex();
GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length())); GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
if (length) if (length)
...@@ -3170,7 +3171,7 @@ GLsizei Program::getTransformFeedbackVaryingCount() const ...@@ -3170,7 +3171,7 @@ GLsizei Program::getTransformFeedbackVaryingCount() const
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
if (mLinked) if (mLinked)
{ {
return static_cast<GLsizei>(mState.mLinkedTransformFeedbackVaryings.size()); return static_cast<GLsizei>(mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
} }
else else
{ {
...@@ -3184,7 +3185,7 @@ GLsizei Program::getTransformFeedbackVaryingMaxLength() const ...@@ -3184,7 +3185,7 @@ GLsizei Program::getTransformFeedbackVaryingMaxLength() const
if (mLinked) if (mLinked)
{ {
GLsizei maxSize = 0; GLsizei maxSize = 0;
for (const auto &var : mState.mLinkedTransformFeedbackVaryings) for (const auto &var : mState.mExecutable->mLinkedTransformFeedbackVaryings)
{ {
maxSize = maxSize =
std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1)); std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
...@@ -3201,7 +3202,7 @@ GLsizei Program::getTransformFeedbackVaryingMaxLength() const ...@@ -3201,7 +3202,7 @@ GLsizei Program::getTransformFeedbackVaryingMaxLength() const
GLenum Program::getTransformFeedbackBufferMode() const GLenum Program::getTransformFeedbackBufferMode() const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return mState.mTransformFeedbackBufferMode; return mState.mExecutable->getTransformFeedbackBufferMode();
} }
bool Program::linkValidateShaders(InfoLog &infoLog) bool Program::linkValidateShaders(InfoLog &infoLog)
...@@ -3359,9 +3360,10 @@ bool Program::linkValidateShaders(InfoLog &infoLog) ...@@ -3359,9 +3360,10 @@ bool Program::linkValidateShaders(InfoLog &infoLog)
GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
for (GLuint tfIndex = 0; tfIndex < mState.mLinkedTransformFeedbackVaryings.size(); ++tfIndex) for (GLuint tfIndex = 0; tfIndex < mState.mExecutable->mLinkedTransformFeedbackVaryings.size();
++tfIndex)
{ {
const auto &tf = mState.mLinkedTransformFeedbackVaryings[tfIndex]; const auto &tf = mState.mExecutable->mLinkedTransformFeedbackVaryings[tfIndex];
if (tf.nameWithArrayIndex() == name) if (tf.nameWithArrayIndex() == name)
{ {
return tfIndex; return tfIndex;
...@@ -3373,8 +3375,8 @@ GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) con ...@@ -3373,8 +3375,8 @@ GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) con
const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
ASSERT(index < mState.mLinkedTransformFeedbackVaryings.size()); ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
return mState.mLinkedTransformFeedbackVaryings[index]; return mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
} }
bool Program::hasDrawIDUniform() const bool Program::hasDrawIDUniform() const
...@@ -3586,7 +3588,7 @@ bool Program::linkUniforms(const Caps &caps, ...@@ -3586,7 +3588,7 @@ bool Program::linkUniforms(const Caps &caps,
return false; return false;
} }
linker.getResults(&mState.mUniforms, unusedUniforms, &mState.mUniformLocations); linker.getResults(&mState.mExecutable->mUniforms, unusedUniforms, &mState.mUniformLocations);
linkSamplerAndImageBindings(combinedImageUniformsCount); linkSamplerAndImageBindings(combinedImageUniformsCount);
...@@ -3613,19 +3615,20 @@ void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms) ...@@ -3613,19 +3615,20 @@ void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
{ {
ASSERT(combinedImageUniforms); ASSERT(combinedImageUniforms);
// Iterate over mUniforms from the back, and find the range of atomic counters, images and // Iterate over mExecutable->mUniforms from the back, and find the range of atomic counters,
// samplers in that order. // images and samplers in that order.
auto highIter = mState.mUniforms.rbegin(); auto highIter = mState.mExecutable->getUniforms().rbegin();
auto lowIter = highIter; auto lowIter = highIter;
unsigned int high = static_cast<unsigned int>(mState.mUniforms.size()); unsigned int high = static_cast<unsigned int>(mState.mExecutable->getUniforms().size());
unsigned int low = high; unsigned int low = high;
// Note that uniform block uniforms are not yet appended to this list. // Note that uniform block uniforms are not yet appended to this list.
ASSERT(mState.mUniforms.size() == 0 || highIter->isAtomicCounter() || highIter->isImage() || ASSERT(mState.mExecutable->getUniforms().size() == 0 || highIter->isAtomicCounter() ||
highIter->isSampler() || highIter->isInDefaultBlock()); highIter->isImage() || highIter->isSampler() || highIter->isInDefaultBlock());
for (; lowIter != mState.mUniforms.rend() && lowIter->isAtomicCounter(); ++lowIter) for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isAtomicCounter();
++lowIter)
{ {
--low; --low;
} }
...@@ -3635,21 +3638,21 @@ void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms) ...@@ -3635,21 +3638,21 @@ void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
highIter = lowIter; highIter = lowIter;
high = low; high = low;
for (; lowIter != mState.mUniforms.rend() && lowIter->isImage(); ++lowIter) for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isImage(); ++lowIter)
{ {
--low; --low;
} }
mState.mImageUniformRange = RangeUI(low, high); mState.mExecutable->mImageUniformRange = RangeUI(low, high);
*combinedImageUniforms = 0u; *combinedImageUniforms = 0u;
// If uniform is a image type, insert it into the mImageBindings array. // If uniform is a image type, insert it into the mImageBindings array.
for (unsigned int imageIndex : mState.mImageUniformRange) for (unsigned int imageIndex : mState.mExecutable->getImageUniformRange())
{ {
// ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
// cannot load values into a uniform defined as an image. if declare without a // cannot load values into a uniform defined as an image. if declare without a
// binding qualifier, any uniform image variable (include all elements of // binding qualifier, any uniform image variable (include all elements of
// unbound image array) shoud be bound to unit zero. // unbound image array) shoud be bound to unit zero.
auto &imageUniform = mState.mUniforms[imageIndex]; auto &imageUniform = mState.mExecutable->getUniforms()[imageIndex];
if (imageUniform.binding == -1) if (imageUniform.binding == -1)
{ {
mState.mImageBindings.emplace_back( mState.mImageBindings.emplace_back(
...@@ -3668,17 +3671,17 @@ void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms) ...@@ -3668,17 +3671,17 @@ void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
highIter = lowIter; highIter = lowIter;
high = low; high = low;
for (; lowIter != mState.mUniforms.rend() && lowIter->isSampler(); ++lowIter) for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isSampler(); ++lowIter)
{ {
--low; --low;
} }
mState.mSamplerUniformRange = RangeUI(low, high); mState.mExecutable->mSamplerUniformRange = RangeUI(low, high);
// If uniform is a sampler type, insert it into the mSamplerBindings array. // If uniform is a sampler type, insert it into the mSamplerBindings array.
for (unsigned int samplerIndex : mState.mSamplerUniformRange) for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
{ {
const auto &samplerUniform = mState.mUniforms[samplerIndex]; const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
TextureType textureType = SamplerTypeToTextureType(samplerUniform.type); TextureType textureType = SamplerTypeToTextureType(samplerUniform.type);
unsigned int elementCount = samplerUniform.getBasicTypeElementCount(); unsigned int elementCount = samplerUniform.getBasicTypeElementCount();
SamplerFormat format = samplerUniform.typeInfo->samplerFormat; SamplerFormat format = samplerUniform.typeInfo->samplerFormat;
...@@ -3693,17 +3696,17 @@ bool Program::linkAtomicCounterBuffers() ...@@ -3693,17 +3696,17 @@ bool Program::linkAtomicCounterBuffers()
{ {
for (unsigned int index : mState.mAtomicCounterUniformRange) for (unsigned int index : mState.mAtomicCounterUniformRange)
{ {
auto &uniform = mState.mUniforms[index]; auto &uniform = mState.mExecutable->mUniforms[index];
uniform.blockInfo.offset = uniform.offset; uniform.blockInfo.offset = uniform.offset;
uniform.blockInfo.arrayStride = (uniform.isArray() ? 4 : 0); uniform.blockInfo.arrayStride = (uniform.isArray() ? 4 : 0);
uniform.blockInfo.matrixStride = 0; uniform.blockInfo.matrixStride = 0;
uniform.blockInfo.isRowMajorMatrix = false; uniform.blockInfo.isRowMajorMatrix = false;
bool found = false; bool found = false;
for (unsigned int bufferIndex = 0; bufferIndex < mState.mAtomicCounterBuffers.size(); for (unsigned int bufferIndex = 0;
++bufferIndex) bufferIndex < mState.mExecutable->getActiveAtomicCounterBufferCount(); ++bufferIndex)
{ {
auto &buffer = mState.mAtomicCounterBuffers[bufferIndex]; auto &buffer = mState.mExecutable->mAtomicCounterBuffers[bufferIndex];
if (buffer.binding == uniform.binding) if (buffer.binding == uniform.binding)
{ {
buffer.memberIndexes.push_back(index); buffer.memberIndexes.push_back(index);
...@@ -3719,8 +3722,9 @@ bool Program::linkAtomicCounterBuffers() ...@@ -3719,8 +3722,9 @@ bool Program::linkAtomicCounterBuffers()
atomicCounterBuffer.binding = uniform.binding; atomicCounterBuffer.binding = uniform.binding;
atomicCounterBuffer.memberIndexes.push_back(index); atomicCounterBuffer.memberIndexes.push_back(index);
atomicCounterBuffer.unionReferencesWith(uniform); atomicCounterBuffer.unionReferencesWith(uniform);
mState.mAtomicCounterBuffers.push_back(atomicCounterBuffer); mState.mExecutable->mAtomicCounterBuffers.push_back(atomicCounterBuffer);
uniform.bufferIndex = static_cast<int>(mState.mAtomicCounterBuffers.size() - 1); uniform.bufferIndex =
static_cast<int>(mState.mExecutable->getActiveAtomicCounterBufferCount() - 1);
} }
} }
// TODO(jie.a.chen@intel.com): Count each atomic counter buffer to validate against // TODO(jie.a.chen@intel.com): Count each atomic counter buffer to validate against
...@@ -3752,19 +3756,19 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog) ...@@ -3752,19 +3756,19 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
// In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes - // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
// see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
// aliasing checks. // aliasing checks.
mState.mProgramInputs = vertexShader->getAllAttributes(); mState.mExecutable->mProgramInputs = vertexShader->getAllAttributes();
} }
else else
{ {
// In GLSL ES 1.00.17 we only do aliasing checks for active attributes. // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
mState.mProgramInputs = vertexShader->getActiveAttributes(); mState.mExecutable->mProgramInputs = vertexShader->getActiveAttributes();
} }
GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes); GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
std::vector<sh::ShaderVariable *> usedAttribMap(maxAttribs, nullptr); std::vector<sh::ShaderVariable *> usedAttribMap(maxAttribs, nullptr);
// Assign locations to attributes that have a binding location and check for attribute aliasing. // Assign locations to attributes that have a binding location and check for attribute aliasing.
for (sh::ShaderVariable &attribute : mState.mProgramInputs) for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
{ {
// GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
// structures, so we don't need to worry about adjusting their names or generating entries // structures, so we don't need to worry about adjusting their names or generating entries
...@@ -3820,7 +3824,7 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog) ...@@ -3820,7 +3824,7 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
} }
// Assign locations to attributes that don't have a binding location. // Assign locations to attributes that don't have a binding location.
for (sh::ShaderVariable &attribute : mState.mProgramInputs) for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
{ {
// Not set by glBindAttribLocation or by location layout qualifier // Not set by glBindAttribLocation or by location layout qualifier
if (attribute.location == -1) if (attribute.location == -1)
...@@ -3845,8 +3849,8 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog) ...@@ -3845,8 +3849,8 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
// shader versions we're only processing active attributes to begin with. // shader versions we're only processing active attributes to begin with.
if (shaderVersion >= 300) if (shaderVersion >= 300)
{ {
for (auto attributeIter = mState.mProgramInputs.begin(); for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
attributeIter != mState.mProgramInputs.end();) attributeIter != mState.mExecutable->getProgramInputs().end();)
{ {
if (attributeIter->active) if (attributeIter->active)
{ {
...@@ -3854,12 +3858,12 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog) ...@@ -3854,12 +3858,12 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
} }
else else
{ {
attributeIter = mState.mProgramInputs.erase(attributeIter); attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
} }
} }
} }
for (const sh::ShaderVariable &attribute : mState.mProgramInputs) for (const sh::ShaderVariable &attribute : mState.mExecutable->getProgramInputs())
{ {
ASSERT(attribute.active); ASSERT(attribute.active);
ASSERT(attribute.location != -1); ASSERT(attribute.location != -1);
...@@ -4268,7 +4272,7 @@ bool Program::linkValidateTransformFeedback(const Version &version, ...@@ -4268,7 +4272,7 @@ bool Program::linkValidateTransformFeedback(const Version &version,
// TODO(jmadill): Investigate implementation limits on D3D11 // TODO(jmadill): Investigate implementation limits on D3D11
componentCount = VariableComponentCount(var->type) * elementCount; componentCount = VariableComponentCount(var->type) * elementCount;
if (mState.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && if (mState.mExecutable->getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS &&
componentCount > static_cast<GLuint>(caps.maxTransformFeedbackSeparateComponents)) componentCount > static_cast<GLuint>(caps.maxTransformFeedbackSeparateComponents))
{ {
infoLog << "Transform feedback varying " << tfVaryingName << " components (" infoLog << "Transform feedback varying " << tfVaryingName << " components ("
...@@ -4278,7 +4282,7 @@ bool Program::linkValidateTransformFeedback(const Version &version, ...@@ -4278,7 +4282,7 @@ bool Program::linkValidateTransformFeedback(const Version &version,
} }
totalComponents += componentCount; totalComponents += componentCount;
if (mState.mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && if (mState.mExecutable->getTransformFeedbackBufferMode() == GL_INTERLEAVED_ATTRIBS &&
totalComponents > static_cast<GLuint>(caps.maxTransformFeedbackInterleavedComponents)) totalComponents > static_cast<GLuint>(caps.maxTransformFeedbackInterleavedComponents))
{ {
infoLog << "Transform feedback varying total components (" << totalComponents infoLog << "Transform feedback varying total components (" << totalComponents
...@@ -4294,7 +4298,7 @@ void Program::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyi ...@@ -4294,7 +4298,7 @@ void Program::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyi
ShaderType stage) ShaderType stage)
{ {
// Gather the linked varyings that are used for transform feedback, they should all exist. // Gather the linked varyings that are used for transform feedback, they should all exist.
mState.mLinkedTransformFeedbackVaryings.clear(); mState.mExecutable->mLinkedTransformFeedbackVaryings.clear();
for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames) for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
{ {
std::vector<unsigned int> subscripts; std::vector<unsigned int> subscripts;
...@@ -4314,7 +4318,7 @@ void Program::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyi ...@@ -4314,7 +4318,7 @@ void Program::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyi
const sh::ShaderVariable *varying = ref.get(stage); const sh::ShaderVariable *varying = ref.get(stage);
if (baseName == varying->name) if (baseName == varying->name)
{ {
mState.mLinkedTransformFeedbackVaryings.emplace_back( mState.mExecutable->mLinkedTransformFeedbackVaryings.emplace_back(
*varying, static_cast<GLuint>(subscript)); *varying, static_cast<GLuint>(subscript));
break; break;
} }
...@@ -4324,7 +4328,8 @@ void Program::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyi ...@@ -4324,7 +4328,8 @@ void Program::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyi
const auto *field = FindShaderVarField(*varying, tfVaryingName, &fieldIndex); const auto *field = FindShaderVarField(*varying, tfVaryingName, &fieldIndex);
if (field != nullptr) if (field != nullptr)
{ {
mState.mLinkedTransformFeedbackVaryings.emplace_back(*field, *varying); mState.mExecutable->mLinkedTransformFeedbackVaryings.emplace_back(*field,
*varying);
break; break;
} }
} }
...@@ -4619,7 +4624,7 @@ bool Program::linkOutputVariables(const Caps &caps, ...@@ -4619,7 +4624,7 @@ bool Program::linkOutputVariables(const Caps &caps,
if (fragmentShader && fragmentShader->getShaderVersion() == 100) if (fragmentShader && fragmentShader->getShaderVersion() == 100)
return true; return true;
mState.mOutputVariables = outputVariables; mState.mExecutable->mOutputVariables = outputVariables;
// TODO(jmadill): any caps validation here? // TODO(jmadill): any caps validation here?
// EXT_blend_func_extended doesn't specify anything related to binding specific elements of an // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
...@@ -4655,9 +4660,11 @@ bool Program::linkOutputVariables(const Caps &caps, ...@@ -4655,9 +4660,11 @@ bool Program::linkOutputVariables(const Caps &caps,
continue; continue;
} }
for (unsigned int outputVariableIndex = 0; for (unsigned int outputVariableIndex = 0;
outputVariableIndex < mState.mOutputVariables.size(); outputVariableIndex++) outputVariableIndex < mState.mExecutable->getOutputVariables().size();
outputVariableIndex++)
{ {
const sh::ShaderVariable &outputVariable = mState.mOutputVariables[outputVariableIndex]; const sh::ShaderVariable &outputVariable =
mState.mExecutable->getOutputVariables()[outputVariableIndex];
// Check that the binding corresponds to an output array and its array index fits. // Check that the binding corresponds to an output array and its array index fits.
if (outputVariable.isBuiltIn() || !outputVariable.isArray() || if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
!angle::BeginsWith(outputVariable.name, binding.first, !angle::BeginsWith(outputVariable.name, binding.first,
...@@ -4671,7 +4678,7 @@ bool Program::linkOutputVariables(const Caps &caps, ...@@ -4671,7 +4678,7 @@ bool Program::linkOutputVariables(const Caps &caps,
// This index may differ from the index used for the array's base. // This index may differ from the index used for the array's base.
auto &outputLocations = mFragmentOutputIndexes.getBindingByName(binding.first) == 1 auto &outputLocations = mFragmentOutputIndexes.getBindingByName(binding.first) == 1
? mState.mSecondaryOutputLocations ? mState.mSecondaryOutputLocations
: mState.mOutputLocations; : mState.mExecutable->mOutputLocations;
unsigned int location = binding.second.location; unsigned int location = binding.second.location;
VariableLocation locationInfo(arrayIndex, outputVariableIndex); VariableLocation locationInfo(arrayIndex, outputVariableIndex);
if (location >= outputLocations.size()) if (location >= outputLocations.size())
...@@ -4693,10 +4700,12 @@ bool Program::linkOutputVariables(const Caps &caps, ...@@ -4693,10 +4700,12 @@ bool Program::linkOutputVariables(const Caps &caps,
// Reserve locations for output variables whose location is fixed in the shader or through the // Reserve locations for output variables whose location is fixed in the shader or through the
// API. Otherwise, the remaining unallocated outputs will be processed later. // API. Otherwise, the remaining unallocated outputs will be processed later.
for (unsigned int outputVariableIndex = 0; outputVariableIndex < mState.mOutputVariables.size(); for (unsigned int outputVariableIndex = 0;
outputVariableIndex < mState.mExecutable->getOutputVariables().size();
outputVariableIndex++) outputVariableIndex++)
{ {
const sh::ShaderVariable &outputVariable = mState.mOutputVariables[outputVariableIndex]; const sh::ShaderVariable &outputVariable =
mState.mExecutable->getOutputVariables()[outputVariableIndex];
// Don't store outputs for gl_FragDepth, gl_FragColor, etc. // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
if (outputVariable.isBuiltIn()) if (outputVariable.isBuiltIn())
...@@ -4712,7 +4721,7 @@ bool Program::linkOutputVariables(const Caps &caps, ...@@ -4712,7 +4721,7 @@ bool Program::linkOutputVariables(const Caps &caps,
auto &outputLocations = isOutputSecondaryForLink(outputVariable) auto &outputLocations = isOutputSecondaryForLink(outputVariable)
? mState.mSecondaryOutputLocations ? mState.mSecondaryOutputLocations
: mState.mOutputLocations; : mState.mExecutable->mOutputLocations;
// GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
// structures, so we may use getBasicTypeElementCount(). // structures, so we may use getBasicTypeElementCount().
...@@ -4725,7 +4734,8 @@ bool Program::linkOutputVariables(const Caps &caps, ...@@ -4725,7 +4734,8 @@ bool Program::linkOutputVariables(const Caps &caps,
return false; return false;
} }
AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations, AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
outputVariableIndex, mState.mOutputVariables[outputVariableIndex]); outputVariableIndex,
mState.mExecutable->mOutputVariables[outputVariableIndex]);
} }
// Here we assign locations for the output variables that don't yet have them. Note that we're // Here we assign locations for the output variables that don't yet have them. Note that we're
...@@ -4741,10 +4751,12 @@ bool Program::linkOutputVariables(const Caps &caps, ...@@ -4741,10 +4751,12 @@ bool Program::linkOutputVariables(const Caps &caps,
maxLocation = extensions.maxDualSourceDrawBuffers; maxLocation = extensions.maxDualSourceDrawBuffers;
} }
for (unsigned int outputVariableIndex = 0; outputVariableIndex < mState.mOutputVariables.size(); for (unsigned int outputVariableIndex = 0;
outputVariableIndex < mState.mExecutable->getOutputVariables().size();
outputVariableIndex++) outputVariableIndex++)
{ {
const sh::ShaderVariable &outputVariable = mState.mOutputVariables[outputVariableIndex]; const sh::ShaderVariable &outputVariable =
mState.mExecutable->getOutputVariables()[outputVariableIndex];
// Don't store outputs for gl_FragDepth, gl_FragColor, etc. // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
if (outputVariable.isBuiltIn()) if (outputVariable.isBuiltIn())
...@@ -4753,7 +4765,7 @@ bool Program::linkOutputVariables(const Caps &caps, ...@@ -4753,7 +4765,7 @@ bool Program::linkOutputVariables(const Caps &caps,
int fixedLocation = getOutputLocationForLink(outputVariable); int fixedLocation = getOutputLocationForLink(outputVariable);
auto &outputLocations = isOutputSecondaryForLink(outputVariable) auto &outputLocations = isOutputSecondaryForLink(outputVariable)
? mState.mSecondaryOutputLocations ? mState.mSecondaryOutputLocations
: mState.mOutputLocations; : mState.mExecutable->mOutputLocations;
unsigned int baseLocation = 0; unsigned int baseLocation = 0;
unsigned int elementCount = outputVariable.getBasicTypeElementCount(); unsigned int elementCount = outputVariable.getBasicTypeElementCount();
if (fixedLocation != -1) if (fixedLocation != -1)
...@@ -4774,7 +4786,7 @@ bool Program::linkOutputVariables(const Caps &caps, ...@@ -4774,7 +4786,7 @@ bool Program::linkOutputVariables(const Caps &caps,
} }
AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations, AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
outputVariableIndex, outputVariableIndex,
mState.mOutputVariables[outputVariableIndex]); mState.mExecutable->mOutputVariables[outputVariableIndex]);
} }
// Check for any elements assigned above the max location that are actually used. // Check for any elements assigned above the max location that are actually used.
...@@ -4799,9 +4811,9 @@ bool Program::linkOutputVariables(const Caps &caps, ...@@ -4799,9 +4811,9 @@ bool Program::linkOutputVariables(const Caps &caps,
void Program::setUniformValuesFromBindingQualifiers() void Program::setUniformValuesFromBindingQualifiers()
{ {
for (unsigned int samplerIndex : mState.mSamplerUniformRange) for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
{ {
const auto &samplerUniform = mState.mUniforms[samplerIndex]; const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
if (samplerUniform.binding != -1) if (samplerUniform.binding != -1)
{ {
UniformLocation location = getUniformLocation(samplerUniform.name); UniformLocation location = getUniformLocation(samplerUniform.name);
...@@ -4824,9 +4836,10 @@ void Program::setUniformValuesFromBindingQualifiers() ...@@ -4824,9 +4836,10 @@ void Program::setUniformValuesFromBindingQualifiers()
void Program::initInterfaceBlockBindings() void Program::initInterfaceBlockBindings()
{ {
// Set initial bindings from shader. // Set initial bindings from shader.
for (unsigned int blockIndex = 0; blockIndex < mState.mUniformBlocks.size(); blockIndex++) for (unsigned int blockIndex = 0; blockIndex < mState.mExecutable->getActiveUniformBlockCount();
blockIndex++)
{ {
InterfaceBlock &uniformBlock = mState.mUniformBlocks[blockIndex]; InterfaceBlock &uniformBlock = mState.mExecutable->mUniformBlocks[blockIndex];
bindUniformBlock(blockIndex, uniformBlock.binding); bindUniformBlock(blockIndex, uniformBlock.binding);
} }
} }
...@@ -4875,7 +4888,7 @@ void Program::updateSamplerUniform(Context *context, ...@@ -4875,7 +4888,7 @@ void Program::updateSamplerUniform(Context *context,
newSamplerFormat = samplerBinding.format; newSamplerFormat = samplerBinding.format;
mState.mExecutable->mActiveSamplersMask.set(newTextureUnit); mState.mExecutable->mActiveSamplersMask.set(newTextureUnit);
mState.mExecutable->mActiveSamplerShaderBits[newTextureUnit] = mState.mExecutable->mActiveSamplerShaderBits[newTextureUnit] =
mState.mUniforms[locationInfo.index].activeShaders(); mState.mExecutable->getUniforms()[locationInfo.index].activeShaders();
} }
else else
{ {
...@@ -4933,7 +4946,7 @@ GLsizei Program::clampUniformCount(const VariableLocation &locationInfo, ...@@ -4933,7 +4946,7 @@ GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
if (count == 1) if (count == 1)
return 1; return 1;
const LinkedUniform &linkedUniform = mState.mUniforms[locationInfo.index]; const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
// OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
// element index used, as reported by GetActiveUniform, will be ignored by the GL." // element index used, as reported by GetActiveUniform, will be ignored by the GL."
...@@ -4963,7 +4976,7 @@ GLsizei Program::clampMatrixUniformCount(UniformLocation location, ...@@ -4963,7 +4976,7 @@ GLsizei Program::clampMatrixUniformCount(UniformLocation location,
return clampUniformCount(locationInfo, count, cols * rows, v); return clampUniformCount(locationInfo, count, cols * rows, v);
} }
const LinkedUniform &linkedUniform = mState.mUniforms[locationInfo.index]; const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
// OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
// element index used, as reported by GetActiveUniform, will be ignored by the GL." // element index used, as reported by GetActiveUniform, will be ignored by the GL."
...@@ -5119,8 +5132,8 @@ angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *bi ...@@ -5119,8 +5132,8 @@ angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *bi
WriteInterfaceBlock(&stream, shaderStorageBlock); WriteInterfaceBlock(&stream, shaderStorageBlock);
} }
stream.writeInt(mState.mAtomicCounterBuffers.size()); stream.writeInt(mState.mExecutable->getActiveAtomicCounterBufferCount());
for (const auto &atomicCounterBuffer : mState.mAtomicCounterBuffers) for (const auto &atomicCounterBuffer : mState.mExecutable->getAtomicCounterBuffers())
{ {
WriteShaderVariableBuffer(&stream, atomicCounterBuffer); WriteShaderVariableBuffer(&stream, atomicCounterBuffer);
} }
...@@ -5262,17 +5275,17 @@ angle::Result Program::deserialize(const Context *context, ...@@ -5262,17 +5275,17 @@ angle::Result Program::deserialize(const Context *context,
mState.mEarlyFramentTestsOptimization = stream.readInt<bool>(); mState.mEarlyFramentTestsOptimization = stream.readInt<bool>();
unsigned int attribCount = stream.readInt<unsigned int>(); unsigned int attribCount = stream.readInt<unsigned int>();
ASSERT(mState.mProgramInputs.empty()); ASSERT(mState.mExecutable->getProgramInputs().empty());
for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex) for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
{ {
sh::ShaderVariable attrib; sh::ShaderVariable attrib;
LoadShaderVar(&stream, &attrib); LoadShaderVar(&stream, &attrib);
attrib.location = stream.readInt<int>(); attrib.location = stream.readInt<int>();
mState.mProgramInputs.push_back(attrib); mState.mExecutable->mProgramInputs.push_back(attrib);
} }
unsigned int uniformCount = stream.readInt<unsigned int>(); unsigned int uniformCount = stream.readInt<unsigned int>();
ASSERT(mState.mUniforms.empty()); ASSERT(mState.mExecutable->getUniforms().empty());
for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex) for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
{ {
LinkedUniform uniform; LinkedUniform uniform;
...@@ -5291,7 +5304,7 @@ angle::Result Program::deserialize(const Context *context, ...@@ -5291,7 +5304,7 @@ angle::Result Program::deserialize(const Context *context,
uniform.setActive(shaderType, stream.readBool()); uniform.setActive(shaderType, stream.readBool());
} }
mState.mUniforms.push_back(uniform); mState.mExecutable->mUniforms.push_back(uniform);
} }
const unsigned int uniformIndexCount = stream.readInt<unsigned int>(); const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
...@@ -5308,13 +5321,13 @@ angle::Result Program::deserialize(const Context *context, ...@@ -5308,13 +5321,13 @@ angle::Result Program::deserialize(const Context *context,
} }
unsigned int uniformBlockCount = stream.readInt<unsigned int>(); unsigned int uniformBlockCount = stream.readInt<unsigned int>();
ASSERT(mState.mUniformBlocks.empty()); ASSERT(mState.mExecutable->getUniformBlocks().empty());
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
++uniformBlockIndex) ++uniformBlockIndex)
{ {
InterfaceBlock uniformBlock; InterfaceBlock uniformBlock;
LoadInterfaceBlock(&stream, &uniformBlock); LoadInterfaceBlock(&stream, &uniformBlock);
mState.mUniformBlocks.push_back(uniformBlock); mState.mExecutable->mUniformBlocks.push_back(uniformBlock);
mState.mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0); mState.mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
} }
...@@ -5329,23 +5342,23 @@ angle::Result Program::deserialize(const Context *context, ...@@ -5329,23 +5342,23 @@ angle::Result Program::deserialize(const Context *context,
} }
unsigned int shaderStorageBlockCount = stream.readInt<unsigned int>(); unsigned int shaderStorageBlockCount = stream.readInt<unsigned int>();
ASSERT(mState.mShaderStorageBlocks.empty()); ASSERT(mState.mExecutable->getShaderStorageBlocks().empty());
for (unsigned int shaderStorageBlockIndex = 0; for (unsigned int shaderStorageBlockIndex = 0;
shaderStorageBlockIndex < shaderStorageBlockCount; ++shaderStorageBlockIndex) shaderStorageBlockIndex < shaderStorageBlockCount; ++shaderStorageBlockIndex)
{ {
InterfaceBlock shaderStorageBlock; InterfaceBlock shaderStorageBlock;
LoadInterfaceBlock(&stream, &shaderStorageBlock); LoadInterfaceBlock(&stream, &shaderStorageBlock);
mState.mShaderStorageBlocks.push_back(shaderStorageBlock); mState.mExecutable->mShaderStorageBlocks.push_back(shaderStorageBlock);
} }
unsigned int atomicCounterBufferCount = stream.readInt<unsigned int>(); unsigned int atomicCounterBufferCount = stream.readInt<unsigned int>();
ASSERT(mState.mAtomicCounterBuffers.empty()); ASSERT(mState.mExecutable->getAtomicCounterBuffers().empty());
for (unsigned int bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex) for (unsigned int bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
{ {
AtomicCounterBuffer atomicCounterBuffer; AtomicCounterBuffer atomicCounterBuffer;
LoadShaderVariableBuffer(&stream, &atomicCounterBuffer); LoadShaderVariableBuffer(&stream, &atomicCounterBuffer);
mState.mAtomicCounterBuffers.push_back(atomicCounterBuffer); mState.mExecutable->mAtomicCounterBuffers.push_back(atomicCounterBuffer);
} }
unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>(); unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
...@@ -5358,7 +5371,7 @@ angle::Result Program::deserialize(const Context *context, ...@@ -5358,7 +5371,7 @@ angle::Result Program::deserialize(const Context *context,
return angle::Result::Incomplete; return angle::Result::Incomplete;
} }
ASSERT(mState.mLinkedTransformFeedbackVaryings.empty()); ASSERT(mState.mExecutable->mLinkedTransformFeedbackVaryings.empty());
for (unsigned int transformFeedbackVaryingIndex = 0; for (unsigned int transformFeedbackVaryingIndex = 0;
transformFeedbackVaryingIndex < transformFeedbackVaryingCount; transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
++transformFeedbackVaryingIndex) ++transformFeedbackVaryingIndex)
...@@ -5370,31 +5383,31 @@ angle::Result Program::deserialize(const Context *context, ...@@ -5370,31 +5383,31 @@ angle::Result Program::deserialize(const Context *context,
GLuint arrayIndex = stream.readInt<GLuint>(); GLuint arrayIndex = stream.readInt<GLuint>();
mState.mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex); mState.mExecutable->mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex);
} }
stream.readInt(&mState.mTransformFeedbackBufferMode); stream.readInt(&mState.mExecutable->mTransformFeedbackBufferMode);
unsigned int outputCount = stream.readInt<unsigned int>(); unsigned int outputCount = stream.readInt<unsigned int>();
ASSERT(mState.mOutputVariables.empty()); ASSERT(mState.mExecutable->getOutputVariables().empty());
for (unsigned int outputIndex = 0; outputIndex < outputCount; ++outputIndex) for (unsigned int outputIndex = 0; outputIndex < outputCount; ++outputIndex)
{ {
sh::ShaderVariable output; sh::ShaderVariable output;
LoadShaderVar(&stream, &output); LoadShaderVar(&stream, &output);
output.location = stream.readInt<int>(); output.location = stream.readInt<int>();
output.index = stream.readInt<int>(); output.index = stream.readInt<int>();
mState.mOutputVariables.push_back(output); mState.mExecutable->mOutputVariables.push_back(output);
} }
unsigned int outputVarCount = stream.readInt<unsigned int>(); unsigned int outputVarCount = stream.readInt<unsigned int>();
ASSERT(mState.mOutputLocations.empty()); ASSERT(mState.mExecutable->getOutputLocations().empty());
for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex) for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
{ {
VariableLocation locationData; VariableLocation locationData;
stream.readInt(&locationData.arrayIndex); stream.readInt(&locationData.arrayIndex);
stream.readInt(&locationData.index); stream.readInt(&locationData.index);
stream.readBool(&locationData.ignored); stream.readBool(&locationData.ignored);
mState.mOutputLocations.push_back(locationData); mState.mExecutable->mOutputLocations.push_back(locationData);
} }
unsigned int secondaryOutputVarCount = stream.readInt<unsigned int>(); unsigned int secondaryOutputVarCount = stream.readInt<unsigned int>();
...@@ -5424,10 +5437,10 @@ angle::Result Program::deserialize(const Context *context, ...@@ -5424,10 +5437,10 @@ angle::Result Program::deserialize(const Context *context,
unsigned int defaultUniformRangeHigh = stream.readInt<unsigned int>(); unsigned int defaultUniformRangeHigh = stream.readInt<unsigned int>();
mState.mDefaultUniformRange = RangeUI(defaultUniformRangeLow, defaultUniformRangeHigh); mState.mDefaultUniformRange = RangeUI(defaultUniformRangeLow, defaultUniformRangeHigh);
unsigned int samplerRangeLow = stream.readInt<unsigned int>(); unsigned int samplerRangeLow = stream.readInt<unsigned int>();
unsigned int samplerRangeHigh = stream.readInt<unsigned int>(); unsigned int samplerRangeHigh = stream.readInt<unsigned int>();
mState.mSamplerUniformRange = RangeUI(samplerRangeLow, samplerRangeHigh); mState.mExecutable->mSamplerUniformRange = RangeUI(samplerRangeLow, samplerRangeHigh);
unsigned int samplerCount = stream.readInt<unsigned int>(); unsigned int samplerCount = stream.readInt<unsigned int>();
for (unsigned int samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex) for (unsigned int samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
{ {
TextureType textureType = stream.readEnum<TextureType>(); TextureType textureType = stream.readEnum<TextureType>();
...@@ -5437,10 +5450,10 @@ angle::Result Program::deserialize(const Context *context, ...@@ -5437,10 +5450,10 @@ angle::Result Program::deserialize(const Context *context,
mState.mSamplerBindings.emplace_back(textureType, format, bindingCount, unreferenced); mState.mSamplerBindings.emplace_back(textureType, format, bindingCount, unreferenced);
} }
unsigned int imageRangeLow = stream.readInt<unsigned int>(); unsigned int imageRangeLow = stream.readInt<unsigned int>();
unsigned int imageRangeHigh = stream.readInt<unsigned int>(); unsigned int imageRangeHigh = stream.readInt<unsigned int>();
mState.mImageUniformRange = RangeUI(imageRangeLow, imageRangeHigh); mState.mExecutable->mImageUniformRange = RangeUI(imageRangeLow, imageRangeHigh);
unsigned int imageBindingCount = stream.readInt<unsigned int>(); unsigned int imageBindingCount = stream.readInt<unsigned int>();
for (unsigned int imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex) for (unsigned int imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
{ {
unsigned int elementCount = stream.readInt<unsigned int>(); unsigned int elementCount = stream.readInt<unsigned int>();
......
...@@ -51,6 +51,7 @@ struct Caps; ...@@ -51,6 +51,7 @@ struct Caps;
class Context; class Context;
struct Extensions; struct Extensions;
class Framebuffer; class Framebuffer;
class ProgramExecutable;
class Shader; class Shader;
class ShaderProgramManager; class ShaderProgramManager;
class State; class State;
...@@ -151,45 +152,6 @@ struct BindingInfo ...@@ -151,45 +152,6 @@ struct BindingInfo
bool valid; bool valid;
}; };
// A varying with tranform feedback enabled. If it's an array, either the whole array or one of its
// elements specified by 'arrayIndex' can set to be enabled.
struct TransformFeedbackVarying : public sh::ShaderVariable
{
TransformFeedbackVarying(const sh::ShaderVariable &varyingIn, GLuint arrayIndexIn)
: sh::ShaderVariable(varyingIn), arrayIndex(arrayIndexIn)
{
ASSERT(!isArrayOfArrays());
}
TransformFeedbackVarying(const sh::ShaderVariable &field, const sh::ShaderVariable &parent)
: arrayIndex(GL_INVALID_INDEX)
{
sh::ShaderVariable *thisVar = this;
*thisVar = field;
interpolation = parent.interpolation;
isInvariant = parent.isInvariant;
name = parent.name + "." + name;
mappedName = parent.mappedName + "." + mappedName;
}
std::string nameWithArrayIndex() const
{
std::stringstream fullNameStr;
fullNameStr << name;
if (arrayIndex != GL_INVALID_INDEX)
{
fullNameStr << "[" << arrayIndex << "]";
}
return fullNameStr.str();
}
GLsizei size() const
{
return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
}
GLuint arrayIndex;
};
struct ProgramBinding struct ProgramBinding
{ {
ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {} ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {}
...@@ -252,56 +214,69 @@ class ProgramState final : angle::NonCopyable ...@@ -252,56 +214,69 @@ class ProgramState final : angle::NonCopyable
{ {
return mTransformFeedbackVaryingNames; return mTransformFeedbackVaryingNames;
} }
GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } GLint getTransformFeedbackBufferMode() const
{
return mExecutable->getTransformFeedbackBufferMode();
}
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
{ {
ASSERT(uniformBlockIndex < mUniformBlocks.size()); return mExecutable->getUniformBlockBinding(uniformBlockIndex);
return mUniformBlocks[uniformBlockIndex].binding;
} }
GLuint getShaderStorageBlockBinding(GLuint blockIndex) const GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
{ {
ASSERT(blockIndex < mShaderStorageBlocks.size()); return mExecutable->getShaderStorageBlockBinding(blockIndex);
return mShaderStorageBlocks[blockIndex].binding;
} }
const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
{ {
return mActiveUniformBlockBindings; return mActiveUniformBlockBindings;
} }
const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; } const std::vector<sh::ShaderVariable> &getProgramInputs() const
{
return mExecutable->getProgramInputs();
}
DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; } DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; }
const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; } const std::vector<sh::ShaderVariable> &getOutputVariables() const
const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; } {
return mExecutable->getOutputVariables();
}
const std::vector<VariableLocation> &getOutputLocations() const
{
return mExecutable->getOutputLocations();
}
const std::vector<VariableLocation> &getSecondaryOutputLocations() const const std::vector<VariableLocation> &getSecondaryOutputLocations() const
{ {
return mSecondaryOutputLocations; return mSecondaryOutputLocations;
} }
const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; } const std::vector<LinkedUniform> &getUniforms() const { return mExecutable->getUniforms(); }
const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; } const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; } const std::vector<InterfaceBlock> &getUniformBlocks() const
{
return mExecutable->getUniformBlocks();
}
const std::vector<InterfaceBlock> &getShaderStorageBlocks() const const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
{ {
return mShaderStorageBlocks; return mExecutable->getShaderStorageBlocks();
} }
const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; } const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; }
const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; } const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; } const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
const RangeUI &getDefaultUniformRange() const { return mDefaultUniformRange; } const RangeUI &getDefaultUniformRange() const { return mDefaultUniformRange; }
const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; } const RangeUI &getSamplerUniformRange() const { return mExecutable->getSamplerUniformRange(); }
const RangeUI &getImageUniformRange() const { return mImageUniformRange; } const RangeUI &getImageUniformRange() const { return mExecutable->getImageUniformRange(); }
const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; } const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
{ {
return mLinkedTransformFeedbackVaryings; return mExecutable->getLinkedTransformFeedbackVaryings();
} }
const std::vector<GLsizei> &getTransformFeedbackStrides() const const std::vector<GLsizei> &getTransformFeedbackStrides() const
{ {
return mTransformFeedbackStrides; return mExecutable->getTransformFeedbackStrides();
} }
const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
{ {
return mAtomicCounterBuffers; return mExecutable->getAtomicCounterBuffers();
} }
// Count the number of uniform and storage buffer declarations, counting arrays as one. // Count the number of uniform and storage buffer declarations, counting arrays as one.
...@@ -387,36 +362,13 @@ class ProgramState final : angle::NonCopyable ...@@ -387,36 +362,13 @@ class ProgramState final : angle::NonCopyable
uint32_t mLocationsUsedForXfbExtension; uint32_t mLocationsUsedForXfbExtension;
std::vector<std::string> mTransformFeedbackVaryingNames; std::vector<std::string> mTransformFeedbackVaryingNames;
std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
GLenum mTransformFeedbackBufferMode;
// For faster iteration on the blocks currently being bound. // For faster iteration on the blocks currently being bound.
UniformBlockBindingMask mActiveUniformBlockBindings; UniformBlockBindingMask mActiveUniformBlockBindings;
// Vertex attributes, Fragment input varyings, etc.
std::vector<sh::ShaderVariable> mProgramInputs;
// Uniforms are sorted in order:
// 1. Non-opaque uniforms
// 2. Sampler uniforms
// 3. Image uniforms
// 4. Atomic counter uniforms
// 5. Uniform block uniforms
// This makes opaque uniform validation easier, since we don't need a separate list.
// For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section
// 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each
// inner array of an array of arrays. Names and mapped names of uniforms that are arrays include
// [0] in the end. This makes implementation of queries simpler.
std::vector<LinkedUniform> mUniforms;
std::vector<VariableLocation> mUniformLocations; std::vector<VariableLocation> mUniformLocations;
std::vector<InterfaceBlock> mUniformBlocks;
std::vector<BufferVariable> mBufferVariables; std::vector<BufferVariable> mBufferVariables;
std::vector<InterfaceBlock> mShaderStorageBlocks;
std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
RangeUI mDefaultUniformRange; RangeUI mDefaultUniformRange;
RangeUI mSamplerUniformRange;
RangeUI mImageUniformRange;
RangeUI mAtomicCounterUniformRange; RangeUI mAtomicCounterUniformRange;
// An array of the samplers that are used by the program // An array of the samplers that are used by the program
...@@ -425,11 +377,6 @@ class ProgramState final : angle::NonCopyable ...@@ -425,11 +377,6 @@ class ProgramState final : angle::NonCopyable
// An array of the images that are used by the program // An array of the images that are used by the program
std::vector<ImageBinding> mImageBindings; std::vector<ImageBinding> mImageBindings;
// Names and mapped names of output variables that are arrays include [0] in the end, similarly
// to uniforms.
std::vector<sh::ShaderVariable> mOutputVariables;
std::vector<VariableLocation> mOutputLocations;
// EXT_blend_func_extended secondary outputs (ones with index 1) in ESSL 3.00 shaders. // EXT_blend_func_extended secondary outputs (ones with index 1) in ESSL 3.00 shaders.
std::vector<VariableLocation> mSecondaryOutputLocations; std::vector<VariableLocation> mSecondaryOutputLocations;
...@@ -463,9 +410,6 @@ class ProgramState final : angle::NonCopyable ...@@ -463,9 +410,6 @@ class ProgramState final : angle::NonCopyable
GLint mCachedBaseVertex; GLint mCachedBaseVertex;
GLuint mCachedBaseInstance; GLuint mCachedBaseInstance;
// The size of the data written to each transform feedback buffer per vertex.
std::vector<GLsizei> mTransformFeedbackStrides;
// Note that this has nothing to do with binding layout qualifiers that can be set for some // Note that this has nothing to do with binding layout qualifiers that can be set for some
// uniforms in GLES3.1+. It is used to pre-set the location of uniforms. // uniforms in GLES3.1+. It is used to pre-set the location of uniforms.
ProgramAliasedBindings mUniformLocationBindings; ProgramAliasedBindings mUniformLocationBindings;
...@@ -522,6 +466,7 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -522,6 +466,7 @@ class Program final : angle::NonCopyable, public LabeledObject
void bindFragmentOutputIndex(GLuint index, const char *name); void bindFragmentOutputIndex(GLuint index, const char *name);
angle::Result linkMergedVaryings(const Context *context, angle::Result linkMergedVaryings(const Context *context,
const ProgramExecutable &executable,
const ProgramMergedVaryings &mergedVaryings); const ProgramMergedVaryings &mergedVaryings);
// KHR_parallel_shader_compile // KHR_parallel_shader_compile
...@@ -602,8 +547,7 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -602,8 +547,7 @@ class Program final : angle::NonCopyable, public LabeledObject
const LinkedUniform &getUniformByIndex(GLuint index) const const LinkedUniform &getUniformByIndex(GLuint index) const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
ASSERT(index < static_cast<size_t>(mState.mUniforms.size())); return mState.mExecutable->getUniformByIndex(index);
return mState.mUniforms[index];
} }
const BufferVariable &getBufferVariableByIndex(GLuint index) const; const BufferVariable &getBufferVariableByIndex(GLuint index) const;
...@@ -681,19 +625,19 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -681,19 +625,19 @@ class Program final : angle::NonCopyable, public LabeledObject
ANGLE_INLINE GLuint getActiveUniformBlockCount() const ANGLE_INLINE GLuint getActiveUniformBlockCount() const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return static_cast<GLuint>(mState.mUniformBlocks.size()); return static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount());
} }
ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return static_cast<GLuint>(mState.mAtomicCounterBuffers.size()); return static_cast<GLuint>(mState.mExecutable->getActiveAtomicCounterBufferCount());
} }
ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
return static_cast<GLuint>(mState.mShaderStorageBlocks.size()); return static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount());
} }
GLint getActiveUniformBlockMaxNameLength() const; GLint getActiveUniformBlockMaxNameLength() const;
...@@ -860,12 +804,6 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -860,12 +804,6 @@ class Program final : angle::NonCopyable, public LabeledObject
ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); } ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
gl::ProgramLinkedResources &getResources() const
{
ASSERT(mResources);
return *mResources;
}
// Writes a program's binary to the output memory buffer. // Writes a program's binary to the output memory buffer.
angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const; angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const;
...@@ -1022,9 +960,6 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -1022,9 +960,6 @@ class Program final : angle::NonCopyable, public LabeledObject
Optional<bool> mCachedValidateSamplersResult; Optional<bool> mCachedValidateSamplersResult;
DirtyBits mDirtyBits; DirtyBits mDirtyBits;
// TODO: http://anglebug.com/4514: Remove
std::unique_ptr<gl::ProgramLinkedResources> mResources;
}; };
} // namespace gl } // namespace gl
......
...@@ -25,7 +25,10 @@ ProgramExecutable::ProgramExecutable() ...@@ -25,7 +25,10 @@ ProgramExecutable::ProgramExecutable()
mActiveSamplersMask(0), mActiveSamplersMask(0),
mActiveSamplerRefCounts{}, mActiveSamplerRefCounts{},
mActiveImagesMask(0), mActiveImagesMask(0),
mCanDrawWith(false) mCanDrawWith(false),
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
mSamplerUniformRange(0, 0),
mImageUniformRange(0, 0)
{ {
mActiveSamplerTypes.fill(TextureType::InvalidEnum); mActiveSamplerTypes.fill(TextureType::InvalidEnum);
mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum); mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
...@@ -47,6 +50,15 @@ void ProgramExecutable::reset() ...@@ -47,6 +50,15 @@ void ProgramExecutable::reset()
mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum); mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
mActiveImagesMask.reset(); mActiveImagesMask.reset();
mProgramInputs.clear();
mLinkedTransformFeedbackVaryings.clear();
mUniforms.clear();
mUniformBlocks.clear();
mShaderStorageBlocks.clear();
mAtomicCounterBuffers.clear();
mOutputVariables.clear();
mOutputLocations.clear();
} }
void ProgramExecutable::load(gl::BinaryInputStream *stream) void ProgramExecutable::load(gl::BinaryInputStream *stream)
......
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
#include "BinaryStream.h" #include "BinaryStream.h"
#include "libANGLE/Caps.h" #include "libANGLE/Caps.h"
#include "libANGLE/InfoLog.h" #include "libANGLE/InfoLog.h"
#include "libANGLE/ProgramLinkedResources.h"
#include "libANGLE/Shader.h"
#include "libANGLE/Uniform.h"
#include "libANGLE/VaryingPacking.h" #include "libANGLE/VaryingPacking.h"
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
...@@ -53,6 +56,45 @@ struct ImageBinding ...@@ -53,6 +56,45 @@ struct ImageBinding
bool unreferenced; bool unreferenced;
}; };
// A varying with transform feedback enabled. If it's an array, either the whole array or one of its
// elements specified by 'arrayIndex' can set to be enabled.
struct TransformFeedbackVarying : public sh::ShaderVariable
{
TransformFeedbackVarying(const sh::ShaderVariable &varyingIn, GLuint arrayIndexIn)
: sh::ShaderVariable(varyingIn), arrayIndex(arrayIndexIn)
{
ASSERT(!isArrayOfArrays());
}
TransformFeedbackVarying(const sh::ShaderVariable &field, const sh::ShaderVariable &parent)
: arrayIndex(GL_INVALID_INDEX)
{
sh::ShaderVariable *thisVar = this;
*thisVar = field;
interpolation = parent.interpolation;
isInvariant = parent.isInvariant;
name = parent.name + "." + name;
mappedName = parent.mappedName + "." + mappedName;
}
std::string nameWithArrayIndex() const
{
std::stringstream fullNameStr;
fullNameStr << name;
if (arrayIndex != GL_INVALID_INDEX)
{
fullNameStr << "[" << arrayIndex << "]";
}
return fullNameStr.str();
}
GLsizei size() const
{
return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
}
GLuint arrayIndex;
};
class ProgramState; class ProgramState;
class ProgramPipelineState; class ProgramPipelineState;
...@@ -170,6 +212,67 @@ class ProgramExecutable ...@@ -170,6 +212,67 @@ class ProgramExecutable
void updateCanDrawWith(); void updateCanDrawWith();
bool hasVertexAndFragmentShader() const { return mCanDrawWith; } bool hasVertexAndFragmentShader() const { return mCanDrawWith; }
const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; }
const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; }
const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
{
return mLinkedTransformFeedbackVaryings;
}
GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
{
ASSERT(uniformBlockIndex < mUniformBlocks.size());
return mUniformBlocks[uniformBlockIndex].binding;
}
GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
{
ASSERT(blockIndex < mShaderStorageBlocks.size());
return mShaderStorageBlocks[blockIndex].binding;
}
const std::vector<GLsizei> &getTransformFeedbackStrides() const
{
return mTransformFeedbackStrides;
}
const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
{
return mAtomicCounterBuffers;
}
const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
{
return mShaderStorageBlocks;
}
const LinkedUniform &getUniformByIndex(GLuint index) const
{
ASSERT(index < static_cast<size_t>(mUniforms.size()));
return mUniforms[index];
}
ANGLE_INLINE GLuint getActiveUniformBlockCount() const
{
return static_cast<GLuint>(mUniformBlocks.size());
}
ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const
{
return static_cast<GLuint>(mAtomicCounterBuffers.size());
}
ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const
{
return static_cast<GLuint>(mShaderStorageBlocks.size());
}
gl::ProgramLinkedResources &getResources() const
{
ASSERT(mResources);
return *mResources;
}
private: private:
// TODO(timvp): http://anglebug.com/3570: Investigate removing these friend // TODO(timvp): http://anglebug.com/3570: Investigate removing these friend
// class declarations and accessing the necessary members with getters/setters. // class declarations and accessing the necessary members with getters/setters.
...@@ -211,6 +314,37 @@ class ProgramExecutable ...@@ -211,6 +314,37 @@ class ProgramExecutable
ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits; ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits;
bool mCanDrawWith; bool mCanDrawWith;
// Names and mapped names of output variables that are arrays include [0] in the end, similarly
// to uniforms.
std::vector<sh::ShaderVariable> mOutputVariables;
std::vector<VariableLocation> mOutputLocations;
// Vertex attributes, Fragment input varyings, etc.
std::vector<sh::ShaderVariable> mProgramInputs;
std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
// The size of the data written to each transform feedback buffer per vertex.
std::vector<GLsizei> mTransformFeedbackStrides;
GLenum mTransformFeedbackBufferMode;
// Uniforms are sorted in order:
// 1. Non-opaque uniforms
// 2. Sampler uniforms
// 3. Image uniforms
// 4. Atomic counter uniforms
// 5. Uniform block uniforms
// This makes opaque uniform validation easier, since we don't need a separate list.
// For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section
// 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each
// inner array of an array of arrays. Names and mapped names of uniforms that are arrays include
// [0] in the end. This makes implementation of queries simpler.
std::vector<LinkedUniform> mUniforms;
RangeUI mSamplerUniformRange;
std::vector<InterfaceBlock> mUniformBlocks;
std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
RangeUI mImageUniformRange;
std::vector<InterfaceBlock> mShaderStorageBlocks;
// TODO: http://anglebug.com/4514: Remove
std::unique_ptr<gl::ProgramLinkedResources> mResources;
}; };
} // namespace gl } // namespace gl
......
...@@ -498,8 +498,9 @@ angle::Result ProgramPipeline::link(const Context *context) ...@@ -498,8 +498,9 @@ angle::Result ProgramPipeline::link(const Context *context)
{ {
Program *program = mState.mPrograms[shaderType]; Program *program = mState.mPrograms[shaderType];
ASSERT(program); ASSERT(program);
program->getResources().varyingPacking.reset(); program->getExecutable().getResources().varyingPacking.reset();
ANGLE_TRY(program->linkMergedVaryings(context, mergedVaryings)); ANGLE_TRY(
program->linkMergedVaryings(context, program->getExecutable(), mergedVaryings));
} }
} }
......
...@@ -457,12 +457,12 @@ void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programSt ...@@ -457,12 +457,12 @@ void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programSt
*vertexShader = SubstituteTransformFeedbackMarkers(*vertexShader, xfbDecl, xfbOut); *vertexShader = SubstituteTransformFeedbackMarkers(*vertexShader, xfbDecl, xfbOut);
} }
void AssignAttributeLocations(const gl::ProgramState &programState, void AssignAttributeLocations(const gl::ProgramExecutable &programExecutable,
gl::ShaderType stage, gl::ShaderType stage,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
// Assign attribute locations for the vertex shader. // Assign attribute locations for the vertex shader.
for (const sh::ShaderVariable &attribute : programState.getProgramInputs()) for (const sh::ShaderVariable &attribute : programExecutable.getProgramInputs())
{ {
ASSERT(attribute.active); ASSERT(attribute.active);
...@@ -471,15 +471,15 @@ void AssignAttributeLocations(const gl::ProgramState &programState, ...@@ -471,15 +471,15 @@ void AssignAttributeLocations(const gl::ProgramState &programState,
} }
} }
void AssignOutputLocations(const gl::ProgramState &programState, void AssignOutputLocations(const gl::ProgramExecutable &programExecutable,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
// Assign output locations for the fragment shader. // Assign output locations for the fragment shader.
ASSERT(shaderType == gl::ShaderType::Fragment); ASSERT(shaderType == gl::ShaderType::Fragment);
// TODO(syoussefi): Add support for EXT_blend_func_extended. http://anglebug.com/3385 // TODO(syoussefi): Add support for EXT_blend_func_extended. http://anglebug.com/3385
const auto &outputLocations = programState.getOutputLocations(); const auto &outputLocations = programExecutable.getOutputLocations();
const auto &outputVariables = programState.getOutputVariables(); const auto &outputVariables = programExecutable.getOutputVariables();
const std::array<std::string, 3> implicitOutputs = {"gl_FragDepth", "gl_SampleMask", const std::array<std::string, 3> implicitOutputs = {"gl_FragDepth", "gl_SampleMask",
"gl_FragStencilRefARB"}; "gl_FragStencilRefARB"};
...@@ -518,8 +518,7 @@ void AssignOutputLocations(const gl::ProgramState &programState, ...@@ -518,8 +518,7 @@ void AssignOutputLocations(const gl::ProgramState &programState,
} }
void AssignVaryingLocations(const GlslangSourceOptions &options, void AssignVaryingLocations(const GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramExecutable &programExecutable,
const gl::ProgramLinkedResources &resources,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderMapInterfaceVariableInfoMap *variableInfoMapOut) ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
...@@ -538,7 +537,8 @@ void AssignVaryingLocations(const GlslangSourceOptions &options, ...@@ -538,7 +537,8 @@ void AssignVaryingLocations(const GlslangSourceOptions &options,
} }
// Assign varying locations. // Assign varying locations.
for (const gl::PackedVaryingRegister &varyingReg : resources.varyingPacking.getRegisterList()) for (const gl::PackedVaryingRegister &varyingReg :
programExecutable.getResources().varyingPacking.getRegisterList())
{ {
if (!IsFirstRegisterOfVarying(varyingReg)) if (!IsFirstRegisterOfVarying(varyingReg))
{ {
...@@ -583,7 +583,7 @@ void AssignVaryingLocations(const GlslangSourceOptions &options, ...@@ -583,7 +583,7 @@ void AssignVaryingLocations(const GlslangSourceOptions &options,
// Add an entry for inactive varyings. // Add an entry for inactive varyings.
const gl::ShaderMap<std::vector<std::string>> &inactiveVaryingMappedNames = const gl::ShaderMap<std::vector<std::string>> &inactiveVaryingMappedNames =
resources.varyingPacking.getInactiveVaryingMappedNames(); programExecutable.getResources().varyingPacking.getInactiveVaryingMappedNames();
for (const std::string &varyingName : inactiveVaryingMappedNames[shaderType]) for (const std::string &varyingName : inactiveVaryingMappedNames[shaderType])
{ {
bool isBuiltin = angle::BeginsWith(varyingName, "gl_"); bool isBuiltin = angle::BeginsWith(varyingName, "gl_");
...@@ -608,17 +608,16 @@ void AssignVaryingLocations(const GlslangSourceOptions &options, ...@@ -608,17 +608,16 @@ void AssignVaryingLocations(const GlslangSourceOptions &options,
// Calculates XFB layout qualifier arguments for each tranform feedback varying. Stores calculated // Calculates XFB layout qualifier arguments for each tranform feedback varying. Stores calculated
// values for the SPIR-V transformation. // values for the SPIR-V transformation.
void AssignTransformFeedbackExtensionQualifiers(const gl::ProgramState &programState, void AssignTransformFeedbackExtensionQualifiers(const gl::ProgramExecutable &programExecutable,
const gl::ProgramLinkedResources &resources,
uint32_t locationsUsedForXfbExtension, uint32_t locationsUsedForXfbExtension,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
const std::vector<gl::TransformFeedbackVarying> &tfVaryings = const std::vector<gl::TransformFeedbackVarying> &tfVaryings =
programState.getLinkedTransformFeedbackVaryings(); programExecutable.getLinkedTransformFeedbackVaryings();
const std::vector<GLsizei> &varyingStrides = programState.getTransformFeedbackStrides(); const std::vector<GLsizei> &varyingStrides = programExecutable.getTransformFeedbackStrides();
const bool isInterleaved = const bool isInterleaved =
programState.getTransformFeedbackBufferMode() == GL_INTERLEAVED_ATTRIBS; programExecutable.getTransformFeedbackBufferMode() == GL_INTERLEAVED_ATTRIBS;
std::string xfbDecl; std::string xfbDecl;
std::string xfbOut; std::string xfbOut;
...@@ -672,7 +671,7 @@ void AssignTransformFeedbackExtensionQualifiers(const gl::ProgramState &programS ...@@ -672,7 +671,7 @@ void AssignTransformFeedbackExtensionQualifiers(const gl::ProgramState &programS
// only that, but also we should only do this for the first field of the struct. // only that, but also we should only do this for the first field of the struct.
const gl::PackedVarying *originalVarying = nullptr; const gl::PackedVarying *originalVarying = nullptr;
for (const gl::PackedVaryingRegister &varyingReg : for (const gl::PackedVaryingRegister &varyingReg :
resources.varyingPacking.getRegisterList()) programExecutable.getResources().varyingPacking.getRegisterList())
{ {
if (!IsFirstRegisterOfVarying(varyingReg)) if (!IsFirstRegisterOfVarying(varyingReg))
{ {
...@@ -705,13 +704,12 @@ void AssignTransformFeedbackExtensionQualifiers(const gl::ProgramState &programS ...@@ -705,13 +704,12 @@ void AssignTransformFeedbackExtensionQualifiers(const gl::ProgramState &programS
} }
void AssignUniformBindings(GlslangSourceOptions &options, void AssignUniformBindings(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramExecutable &programExecutable,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderMapInterfaceVariableInfoMap *variableInfoMapOut) ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
{ {
if (programState.getAttachedShader(shaderType) || if (programExecutable.hasLinkedShaderStage(shaderType))
programState.getProgramExecutable().hasLinkedShaderStage(shaderType))
{ {
AddResourceInfo(&(*variableInfoMapOut)[shaderType], kDefaultUniformNames[shaderType], AddResourceInfo(&(*variableInfoMapOut)[shaderType], kDefaultUniformNames[shaderType],
programInterfaceInfo->uniformsAndXfbDescriptorSetIndex, programInterfaceInfo->uniformsAndXfbDescriptorSetIndex,
...@@ -728,7 +726,7 @@ void AssignUniformBindings(GlslangSourceOptions &options, ...@@ -728,7 +726,7 @@ void AssignUniformBindings(GlslangSourceOptions &options,
// TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across // TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
// shader stages. // shader stages.
void AssignInterfaceBlockBindings(GlslangSourceOptions &options, void AssignInterfaceBlockBindings(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramExecutable &programExecutable,
const std::vector<gl::InterfaceBlock> &blocks, const std::vector<gl::InterfaceBlock> &blocks,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
...@@ -739,8 +737,7 @@ void AssignInterfaceBlockBindings(GlslangSourceOptions &options, ...@@ -739,8 +737,7 @@ void AssignInterfaceBlockBindings(GlslangSourceOptions &options,
if (!block.isArray || block.arrayElement == 0) if (!block.isArray || block.arrayElement == 0)
{ {
// TODO: http://anglebug.com/4523: All blocks should be active // TODO: http://anglebug.com/4523: All blocks should be active
if (programState.getProgramExecutable().hasLinkedShaderStage(shaderType) && if (programExecutable.hasLinkedShaderStage(shaderType) && block.isActive(shaderType))
block.isActive(shaderType))
{ {
AddResourceInfo(&(*variableInfoMapOut)[shaderType], block.mappedName, AddResourceInfo(&(*variableInfoMapOut)[shaderType], block.mappedName,
programInterfaceInfo->shaderResourceDescriptorSetIndex, programInterfaceInfo->shaderResourceDescriptorSetIndex,
...@@ -755,7 +752,7 @@ void AssignInterfaceBlockBindings(GlslangSourceOptions &options, ...@@ -755,7 +752,7 @@ void AssignInterfaceBlockBindings(GlslangSourceOptions &options,
// TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across // TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
// shader stages. // shader stages.
void AssignAtomicCounterBufferBindings(GlslangSourceOptions &options, void AssignAtomicCounterBufferBindings(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramExecutable &programExecutable,
const std::vector<gl::AtomicCounterBuffer> &buffers, const std::vector<gl::AtomicCounterBuffer> &buffers,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
...@@ -766,7 +763,7 @@ void AssignAtomicCounterBufferBindings(GlslangSourceOptions &options, ...@@ -766,7 +763,7 @@ void AssignAtomicCounterBufferBindings(GlslangSourceOptions &options,
return; return;
} }
if (programState.getProgramExecutable().hasLinkedShaderStage(shaderType)) if (programExecutable.hasLinkedShaderStage(shaderType))
{ {
AddResourceInfo(&(*variableInfoMapOut)[shaderType], sh::vk::kAtomicCountersBlockName, AddResourceInfo(&(*variableInfoMapOut)[shaderType], sh::vk::kAtomicCountersBlockName,
programInterfaceInfo->shaderResourceDescriptorSetIndex, programInterfaceInfo->shaderResourceDescriptorSetIndex,
...@@ -778,7 +775,7 @@ void AssignAtomicCounterBufferBindings(GlslangSourceOptions &options, ...@@ -778,7 +775,7 @@ void AssignAtomicCounterBufferBindings(GlslangSourceOptions &options,
// TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across // TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
// shader stages. // shader stages.
void AssignImageBindings(GlslangSourceOptions &options, void AssignImageBindings(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramExecutable &programExecutable,
const std::vector<gl::LinkedUniform> &uniforms, const std::vector<gl::LinkedUniform> &uniforms,
const gl::RangeUI &imageUniformRange, const gl::RangeUI &imageUniformRange,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
...@@ -792,7 +789,7 @@ void AssignImageBindings(GlslangSourceOptions &options, ...@@ -792,7 +789,7 @@ void AssignImageBindings(GlslangSourceOptions &options,
std::string name = imageUniform.mappedName; std::string name = imageUniform.mappedName;
if (GetImageNameWithoutIndices(&name)) if (GetImageNameWithoutIndices(&name))
{ {
if (programState.getProgramExecutable().hasLinkedShaderStage(shaderType)) if (programExecutable.hasLinkedShaderStage(shaderType))
{ {
AddResourceInfo(&(*variableInfoMapOut)[shaderType], name, AddResourceInfo(&(*variableInfoMapOut)[shaderType], name,
programInterfaceInfo->shaderResourceDescriptorSetIndex, programInterfaceInfo->shaderResourceDescriptorSetIndex,
...@@ -805,42 +802,43 @@ void AssignImageBindings(GlslangSourceOptions &options, ...@@ -805,42 +802,43 @@ void AssignImageBindings(GlslangSourceOptions &options,
} }
void AssignNonTextureBindings(GlslangSourceOptions &options, void AssignNonTextureBindings(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramExecutable &programExecutable,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderMapInterfaceVariableInfoMap *variableInfoMapOut) ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
{ {
const std::vector<gl::InterfaceBlock> &uniformBlocks = programState.getUniformBlocks(); const std::vector<gl::InterfaceBlock> &uniformBlocks = programExecutable.getUniformBlocks();
AssignInterfaceBlockBindings(options, programState, uniformBlocks, shaderType, AssignInterfaceBlockBindings(options, programExecutable, uniformBlocks, shaderType,
programInterfaceInfo, variableInfoMapOut); programInterfaceInfo, variableInfoMapOut);
const std::vector<gl::InterfaceBlock> &storageBlocks = programState.getShaderStorageBlocks(); const std::vector<gl::InterfaceBlock> &storageBlocks =
AssignInterfaceBlockBindings(options, programState, storageBlocks, shaderType, programExecutable.getShaderStorageBlocks();
AssignInterfaceBlockBindings(options, programExecutable, storageBlocks, shaderType,
programInterfaceInfo, variableInfoMapOut); programInterfaceInfo, variableInfoMapOut);
const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers = const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
programState.getAtomicCounterBuffers(); programExecutable.getAtomicCounterBuffers();
AssignAtomicCounterBufferBindings(options, programState, atomicCounterBuffers, shaderType, AssignAtomicCounterBufferBindings(options, programExecutable, atomicCounterBuffers, shaderType,
programInterfaceInfo, variableInfoMapOut); programInterfaceInfo, variableInfoMapOut);
const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms(); const std::vector<gl::LinkedUniform> &uniforms = programExecutable.getUniforms();
const gl::RangeUI &imageUniformRange = programState.getImageUniformRange(); const gl::RangeUI &imageUniformRange = programExecutable.getImageUniformRange();
AssignImageBindings(options, programState, uniforms, imageUniformRange, shaderType, AssignImageBindings(options, programExecutable, uniforms, imageUniformRange, shaderType,
programInterfaceInfo, variableInfoMapOut); programInterfaceInfo, variableInfoMapOut);
} }
// TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across // TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
// shader stages. // shader stages.
void AssignTextureBindings(GlslangSourceOptions &options, void AssignTextureBindings(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramExecutable &programExecutable,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderMapInterfaceVariableInfoMap *variableInfoMapOut) ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
{ {
// Assign textures to a descriptor set and binding. // Assign textures to a descriptor set and binding.
const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms(); const std::vector<gl::LinkedUniform> &uniforms = programExecutable.getUniforms();
for (unsigned int uniformIndex : programState.getSamplerUniformRange()) for (unsigned int uniformIndex : programExecutable.getSamplerUniformRange())
{ {
const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex]; const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
...@@ -858,7 +856,7 @@ void AssignTextureBindings(GlslangSourceOptions &options, ...@@ -858,7 +856,7 @@ void AssignTextureBindings(GlslangSourceOptions &options,
: GlslangGetMappedSamplerName(samplerUniform.name); : GlslangGetMappedSamplerName(samplerUniform.name);
// TODO: http://anglebug.com/4523: All uniforms should be active // TODO: http://anglebug.com/4523: All uniforms should be active
if (programState.getProgramExecutable().hasLinkedShaderStage(shaderType) && if (programExecutable.hasLinkedShaderStage(shaderType) &&
samplerUniform.isActive(shaderType)) samplerUniform.isActive(shaderType))
{ {
AddResourceInfo(&(*variableInfoMapOut)[shaderType], samplerName, AddResourceInfo(&(*variableInfoMapOut)[shaderType], samplerName,
...@@ -1846,53 +1844,47 @@ std::string GetXfbBufferName(const uint32_t bufferIndex) ...@@ -1846,53 +1844,47 @@ std::string GetXfbBufferName(const uint32_t bufferIndex)
} }
void GlslangAssignLocations(GlslangSourceOptions &options, void GlslangAssignLocations(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramExecutable &programExecutable,
const gl::ProgramLinkedResources &resources,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderMapInterfaceVariableInfoMap *variableInfoMapOut) ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
{ {
const gl::ProgramExecutable &executable = programState.getProgramExecutable();
// Assign outputs to the fragment shader, if any. // Assign outputs to the fragment shader, if any.
if ((shaderType == gl::ShaderType::Fragment) && if ((shaderType == gl::ShaderType::Fragment) &&
(programState.getAttachedShader(gl::ShaderType::Fragment) || programExecutable.hasLinkedShaderStage(gl::ShaderType::Fragment))
executable.hasLinkedShaderStage(gl::ShaderType::Fragment)))
{ {
AssignOutputLocations(programState, gl::ShaderType::Fragment, AssignOutputLocations(programExecutable, gl::ShaderType::Fragment,
&(*variableInfoMapOut)[gl::ShaderType::Fragment]); &(*variableInfoMapOut)[gl::ShaderType::Fragment]);
} }
// Assign attributes to the vertex shader, if any. // Assign attributes to the vertex shader, if any.
if ((shaderType == gl::ShaderType::Vertex) && if ((shaderType == gl::ShaderType::Vertex) &&
(programState.getAttachedShader(gl::ShaderType::Vertex) || programExecutable.hasLinkedShaderStage(gl::ShaderType::Vertex))
executable.hasLinkedShaderStage(gl::ShaderType::Vertex)))
{ {
AssignAttributeLocations(programState, gl::ShaderType::Vertex, AssignAttributeLocations(programExecutable, gl::ShaderType::Vertex,
&(*variableInfoMapOut)[gl::ShaderType::Vertex]); &(*variableInfoMapOut)[gl::ShaderType::Vertex]);
} }
if (!programState.getAttachedShader(gl::ShaderType::Compute) && if (!programExecutable.hasLinkedShaderStage(gl::ShaderType::Compute))
!executable.hasLinkedShaderStage(gl::ShaderType::Compute))
{ {
// Assign varying locations. // Assign varying locations.
AssignVaryingLocations(options, programState, resources, shaderType, programInterfaceInfo, AssignVaryingLocations(options, programExecutable, shaderType, programInterfaceInfo,
variableInfoMapOut); variableInfoMapOut);
if (!programState.getLinkedTransformFeedbackVaryings().empty() && if (!programExecutable.getLinkedTransformFeedbackVaryings().empty() &&
options.supportsTransformFeedbackExtension && (shaderType == gl::ShaderType::Vertex)) options.supportsTransformFeedbackExtension && (shaderType == gl::ShaderType::Vertex))
{ {
AssignTransformFeedbackExtensionQualifiers( AssignTransformFeedbackExtensionQualifiers(
programState, resources, programInterfaceInfo->locationsUsedForXfbExtension, programExecutable, programInterfaceInfo->locationsUsedForXfbExtension,
gl::ShaderType::Vertex, &(*variableInfoMapOut)[gl::ShaderType::Vertex]); gl::ShaderType::Vertex, &(*variableInfoMapOut)[gl::ShaderType::Vertex]);
} }
} }
AssignUniformBindings(options, programState, shaderType, programInterfaceInfo, AssignUniformBindings(options, programExecutable, shaderType, programInterfaceInfo,
variableInfoMapOut); variableInfoMapOut);
AssignTextureBindings(options, programState, shaderType, programInterfaceInfo, AssignTextureBindings(options, programExecutable, shaderType, programInterfaceInfo,
variableInfoMapOut); variableInfoMapOut);
AssignNonTextureBindings(options, programState, shaderType, programInterfaceInfo, AssignNonTextureBindings(options, programExecutable, shaderType, programInterfaceInfo,
variableInfoMapOut); variableInfoMapOut);
} }
...@@ -1938,8 +1930,8 @@ void GlslangGetShaderSource(GlslangSourceOptions &options, ...@@ -1938,8 +1930,8 @@ void GlslangGetShaderSource(GlslangSourceOptions &options,
for (const gl::ShaderType shaderType : for (const gl::ShaderType shaderType :
programState.getProgramExecutable().getLinkedShaderStages()) programState.getProgramExecutable().getLinkedShaderStages())
{ {
GlslangAssignLocations(options, programState, resources, shaderType, programInterfaceInfo, GlslangAssignLocations(options, programState.getProgramExecutable(), shaderType,
variableInfoMapOut); programInterfaceInfo, variableInfoMapOut);
} }
} }
......
...@@ -99,8 +99,7 @@ std::string GlslangGetMappedSamplerName(const std::string &originalName); ...@@ -99,8 +99,7 @@ std::string GlslangGetMappedSamplerName(const std::string &originalName);
std::string GetXfbBufferName(const uint32_t bufferIndex); std::string GetXfbBufferName(const uint32_t bufferIndex);
void GlslangAssignLocations(GlslangSourceOptions &options, void GlslangAssignLocations(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramExecutable &programExecutable,
const gl::ProgramLinkedResources &resources,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
gl::ShaderMap<ShaderInterfaceVariableInfoMap> *variableInfoMapOut); gl::ShaderMap<ShaderInterfaceVariableInfoMap> *variableInfoMapOut);
......
...@@ -80,7 +80,7 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext) ...@@ -80,7 +80,7 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext)
glslangProgramInterfaceInfo.locationsUsedForXfbExtension = glslangProgramInterfaceInfo.locationsUsedForXfbExtension =
programProgramInterfaceInfo.locationsUsedForXfbExtension; programProgramInterfaceInfo.locationsUsedForXfbExtension;
GlslangAssignLocations(options, glProgram->getState(), glProgram->getResources(), GlslangAssignLocations(options, glProgram->getState().getProgramExecutable(),
shaderType, &glslangProgramInterfaceInfo, shaderType, &glslangProgramInterfaceInfo,
&mExecutable.getShaderInterfaceVariableInfoMap()); &mExecutable.getShaderInterfaceVariableInfoMap());
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment