Separate out std::vector<GLuint> boundTextureUnits from SamplerBinding

SamplerBinding struct is trivial copy-able except the
std::vector<GLuint> boundTextureUnits.  This CL moves boundTextureUnits
out of the SamplerBinding struct and becomes a vector in
ProgramExecutable. This means all of sampler binding's texture units
will be stored in one vector and SamplerBinding will remember where its
own texture units is stored in that vector by keeping
textureUnitsStartIndex and textureUnitsCount. In other word,
SamplerBinding::boundTextureUnits (before this CL) is equivalent to
mSamplerBoundTextureUnits[SamplerBinding.textureUnitsStartIndex], ...,
mSamplerBoundTextureUnits[SamplerBinding.textureUnitsStartIndex +
SamplerBinding.textureUnitsCount - 1] after this CL. With this,
ProgramExecutable::mSamplerBindings are load/stored with one
readBytes/writeBytes call since it is trivially copyable.

Bug: b/275102061
Change-Id: I0974cf940875ecbcf655b4469b3bbc910717f1ec
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4798195
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Roman Lavrov <romanl@google.com>
Commit-Queue: Charlie Lao <cclao@google.com>
This commit is contained in:
Charlie Lao
2023-08-21 16:57:12 -07:00
committed by Angle LUCI CQ
parent a8d77dc4cd
commit 03f9dff61b
9 changed files with 132 additions and 87 deletions

View File

@@ -753,23 +753,6 @@ VariableLocation::VariableLocation(unsigned int arrayIndex, unsigned int index)
ASSERT(arrayIndex != GL_INVALID_INDEX);
}
// SamplerBindings implementation.
SamplerBinding::SamplerBinding() = default;
SamplerBinding::SamplerBinding(TextureType textureTypeIn,
GLenum samplerTypeIn,
SamplerFormat formatIn,
size_t elementCount)
: textureType(textureTypeIn),
samplerType(samplerTypeIn),
format(formatIn),
boundTextureUnits(elementCount, 0)
{}
SamplerBinding::SamplerBinding(const SamplerBinding &other) = default;
SamplerBinding::~SamplerBinding() = default;
// ProgramBindings implementation.
ProgramBindings::ProgramBindings() {}
@@ -2508,11 +2491,14 @@ GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation
{
ASSERT(!mLinkingState);
GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformLocation.index);
const std::vector<GLuint> &boundTextureUnits =
mState.mExecutable->mSamplerBindings[samplerIndex].boundTextureUnits;
return (uniformLocation.arrayIndex < boundTextureUnits.size())
? boundTextureUnits[uniformLocation.arrayIndex]
: 0;
const SamplerBinding &samplerBinding = mState.mExecutable->mSamplerBindings[samplerIndex];
if (uniformLocation.arrayIndex >= samplerBinding.textureUnitsCount)
{
return 0;
}
const std::vector<GLuint> &boundTextureUnits = mState.mExecutable->mSamplerBoundTextureUnits;
return samplerBinding.getTextureUnit(boundTextureUnits, uniformLocation.arrayIndex);
}
GLuint Program::getImageUniformBinding(const VariableLocation &uniformLocation) const
@@ -3403,19 +3389,21 @@ void Program::updateSamplerUniform(Context *context,
ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
SamplerBinding &samplerBinding = mState.mExecutable->mSamplerBindings[samplerIndex];
std::vector<GLuint> &boundTextureUnits = samplerBinding.boundTextureUnits;
std::vector<GLuint> &boundTextureUnits = mState.mExecutable->mSamplerBoundTextureUnits;
if (locationInfo.arrayIndex >= boundTextureUnits.size())
if (locationInfo.arrayIndex >= samplerBinding.textureUnitsCount)
{
return;
}
GLsizei safeUniformCount = std::min(
clampedCount, static_cast<GLsizei>(boundTextureUnits.size() - locationInfo.arrayIndex));
GLsizei safeUniformCount =
std::min(clampedCount,
static_cast<GLsizei>(samplerBinding.textureUnitsCount - locationInfo.arrayIndex));
// Update the sampler uniforms.
for (GLsizei arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
for (uint16_t arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
{
GLint oldTextureUnit = boundTextureUnits[arrayIndex + locationInfo.arrayIndex];
GLint oldTextureUnit =
samplerBinding.getTextureUnit(boundTextureUnits, arrayIndex + locationInfo.arrayIndex);
GLint newTextureUnit = v[arrayIndex];
if (oldTextureUnit == newTextureUnit)
@@ -3424,7 +3412,8 @@ void Program::updateSamplerUniform(Context *context,
}
// Update sampler's bound textureUnit
boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
boundTextureUnits[samplerBinding.textureUnitsStartIndex + arrayIndex +
locationInfo.arrayIndex] = newTextureUnit;
// Update the reference counts.
uint32_t &oldRefCount = mState.mExecutable->mActiveSamplerRefCounts[oldTextureUnit];
@@ -3499,8 +3488,8 @@ void Program::updateSamplerUniform(Context *context,
void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
{
mExecutable->setSamplerUniformTextureTypeAndFormat(textureUnitIndex,
mExecutable->mSamplerBindings);
mExecutable->setSamplerUniformTextureTypeAndFormat(
textureUnitIndex, mExecutable->mSamplerBindings, mExecutable->mSamplerBoundTextureUnits);
}
template <typename T>

View File

@@ -287,6 +287,10 @@ class ProgramState final : angle::NonCopyable
{
return mExecutable->getSamplerBindings();
}
const std::vector<GLuint> &getSamplerBoundTextureUnits() const
{
return mExecutable->getSamplerBoundTextureUnits();
}
const std::vector<ImageBinding> &getImageBindings() const
{
return getExecutable().getImageBindings();

View File

@@ -233,7 +233,7 @@ void SaveUniforms(BinaryOutputStream *stream,
{
// LinkedUniform is a simple structure with fundamental data types, we can just do bulk save
// for performance.
stream->writeBytes(reinterpret_cast<const unsigned char *>(uniforms.data()),
stream->writeBytes(reinterpret_cast<const uint8_t *>(uniforms.data()),
sizeof(LinkedUniform) * uniforms.size());
for (const std::string &name : uniformNames)
{
@@ -257,7 +257,7 @@ void LoadUniforms(BinaryInputStream *stream,
uniforms->resize(uniformCount);
// LinkedUniform is a simple structure with fundamental data types, we can just do bulk load
// for performance.
stream->readBytes(reinterpret_cast<unsigned char *>(uniforms->data()),
stream->readBytes(reinterpret_cast<uint8_t *>(uniforms->data()),
sizeof(LinkedUniform) * uniforms->size());
uniformNames->resize(uniformCount);
for (size_t uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
@@ -271,6 +271,33 @@ void LoadUniforms(BinaryInputStream *stream,
}
}
}
void SaveSamplerBindings(BinaryOutputStream *stream,
const std::vector<SamplerBinding> &samplerBindings,
const std::vector<GLuint> &samplerBoundTextureUnits)
{
stream->writeInt(samplerBindings.size());
stream->writeBytes(reinterpret_cast<const uint8_t *>(samplerBindings.data()),
sizeof(*samplerBindings.data()) * samplerBindings.size());
stream->writeInt(samplerBoundTextureUnits.size());
}
void LoadSamplerBindings(BinaryInputStream *stream,
std::vector<SamplerBinding> *samplerBindings,
std::vector<GLuint> *samplerBoundTextureUnits)
{
ASSERT(samplerBindings->empty());
size_t samplerBindingCount = stream->readInt<size_t>();
if (samplerBindingCount > 0)
{
samplerBindings->resize(samplerBindingCount);
stream->readBytes(reinterpret_cast<uint8_t *>(samplerBindings->data()),
sizeof(*samplerBindings->data()) * samplerBindingCount);
}
ASSERT(samplerBoundTextureUnits->empty());
size_t boundTextureUnitsCount = stream->readInt<size_t>();
samplerBoundTextureUnits->resize(boundTextureUnitsCount, 0);
}
} // anonymous namespace
ProgramExecutable::PODStruct::PODStruct() = default;
@@ -374,6 +401,7 @@ void ProgramExecutable::reset(bool clearInfoLog)
mOutputLocations.clear();
mSecondaryOutputLocations.clear();
mSamplerBindings.clear();
mSamplerBoundTextureUnits.clear();
mImageBindings.clear();
mOutputVariableTypes.clear();
@@ -478,18 +506,7 @@ void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
stream->readBool(&locationData.ignored);
}
size_t samplerCount = stream->readInt<size_t>();
ASSERT(mSamplerBindings.empty());
mSamplerBindings.resize(samplerCount);
for (size_t samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
{
SamplerBinding &samplerBinding = mSamplerBindings[samplerIndex];
samplerBinding.textureType = stream->readEnum<TextureType>();
samplerBinding.samplerType = stream->readInt<GLenum>();
samplerBinding.format = stream->readEnum<SamplerFormat>();
size_t bindingCount = stream->readInt<size_t>();
samplerBinding.boundTextureUnits.resize(bindingCount, 0);
}
LoadSamplerBindings(stream, &mSamplerBindings, &mSamplerBoundTextureUnits);
size_t imageBindingCount = stream->readInt<size_t>();
ASSERT(mImageBindings.empty());
@@ -608,14 +625,7 @@ void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) c
stream->writeBool(outputVar.ignored);
}
stream->writeInt(getSamplerBindings().size());
for (const auto &samplerBinding : getSamplerBindings())
{
stream->writeEnum(samplerBinding.textureType);
stream->writeInt(samplerBinding.samplerType);
stream->writeEnum(samplerBinding.format);
stream->writeInt(samplerBinding.boundTextureUnits.size());
}
SaveSamplerBindings(stream, mSamplerBindings, mSamplerBoundTextureUnits);
stream->writeInt(getImageBindings().size());
for (const auto &imageBinding : getImageBindings())
@@ -709,13 +719,15 @@ void ProgramExecutable::hasSamplerFormatConflict(size_t textureUnit)
void ProgramExecutable::updateActiveSamplers(const ProgramState &programState)
{
const std::vector<SamplerBinding> &samplerBindings = programState.getSamplerBindings();
const std::vector<GLuint> &boundTextureUnits = programState.getSamplerBoundTextureUnits();
for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
{
const SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
for (GLint textureUnit : samplerBinding.boundTextureUnits)
for (uint16_t index = 0; index < samplerBinding.textureUnitsCount; index++)
{
GLint textureUnit = samplerBinding.getTextureUnit(boundTextureUnits, index);
if (++mActiveSamplerRefCounts[textureUnit] == 1)
{
uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(samplerIndex);
@@ -763,7 +775,8 @@ void ProgramExecutable::updateActiveImages(const ProgramExecutable &executable)
void ProgramExecutable::setSamplerUniformTextureTypeAndFormat(
size_t textureUnitIndex,
std::vector<SamplerBinding> &samplerBindings)
const std::vector<SamplerBinding> &samplerBindings,
const std::vector<GLuint> &boundTextureUnits)
{
bool foundBinding = false;
TextureType foundType = TextureType::InvalidEnum;
@@ -776,8 +789,9 @@ void ProgramExecutable::setSamplerUniformTextureTypeAndFormat(
// A conflict exists if samplers of different types are sourced by the same texture unit.
// We need to check all bound textures to detect this error case.
for (GLuint textureUnit : binding.boundTextureUnits)
for (uint16_t index = 0; index < binding.textureUnitsCount; index++)
{
GLuint textureUnit = binding.getTextureUnit(boundTextureUnits, index);
if (textureUnit != textureUnitIndex)
{
continue;
@@ -1488,15 +1502,18 @@ void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniform
mPODStruct.samplerUniformRange = RangeUI(low, high);
// If uniform is a sampler type, insert it into the mSamplerBindings array.
uint16_t totalCount = 0;
for (unsigned int samplerIndex : mPODStruct.samplerUniformRange)
{
const auto &samplerUniform = mUniforms[samplerIndex];
TextureType textureType = SamplerTypeToTextureType(samplerUniform.getType());
GLenum samplerType = samplerUniform.getType();
unsigned int elementCount = samplerUniform.getBasicTypeElementCount();
uint16_t elementCount = samplerUniform.getBasicTypeElementCount();
SamplerFormat format = GetUniformTypeInfo(samplerType).samplerFormat;
mSamplerBindings.emplace_back(textureType, samplerType, format, elementCount);
mSamplerBindings.emplace_back(textureType, samplerType, format, totalCount, elementCount);
totalCount += elementCount;
}
mSamplerBoundTextureUnits.resize(totalCount, 0);
// Whatever is left constitutes the default uniforms.
mPODStruct.defaultUniformRange = RangeUI(0, low);
@@ -1588,12 +1605,21 @@ void ProgramExecutable::copyShaderBuffersFromProgram(const ProgramState &program
void ProgramExecutable::clearSamplerBindings()
{
mSamplerBindings.clear();
mSamplerBoundTextureUnits.clear();
}
void ProgramExecutable::copySamplerBindingsFromProgram(const ProgramState &programState)
{
const std::vector<SamplerBinding> &bindings = programState.getSamplerBindings();
mSamplerBindings.insert(mSamplerBindings.end(), bindings.begin(), bindings.end());
const std::vector<GLuint> &textureUnits = programState.getSamplerBoundTextureUnits();
uint16_t adjustedStartIndex = mSamplerBoundTextureUnits.size();
mSamplerBoundTextureUnits.insert(mSamplerBoundTextureUnits.end(), textureUnits.begin(),
textureUnits.end());
for (const SamplerBinding &binding : bindings)
{
mSamplerBindings.push_back(binding);
mSamplerBindings.back().textureUnitsStartIndex += adjustedStartIndex;
}
}
void ProgramExecutable::copyImageBindingsFromProgram(const ProgramState &programState)

View File

@@ -24,25 +24,37 @@ namespace gl
// This small structure encapsulates binding sampler uniforms to active GL textures.
struct SamplerBinding
{
SamplerBinding();
SamplerBinding() = default;
SamplerBinding(TextureType textureTypeIn,
GLenum samplerTypeIn,
SamplerFormat formatIn,
size_t elementCount);
SamplerBinding(const SamplerBinding &other);
~SamplerBinding();
uint16_t startIndex,
uint16_t elementCount)
: textureType(textureTypeIn),
samplerType(samplerTypeIn),
format(formatIn),
textureUnitsStartIndex(startIndex),
textureUnitsCount(elementCount)
{}
~SamplerBinding() = default;
GLuint getTextureUnit(const std::vector<GLuint> &boundTextureUnits,
unsigned int arrayIndex) const
{
return boundTextureUnits[textureUnitsStartIndex + arrayIndex];
}
// Necessary for retrieving active textures from the GL state.
TextureType textureType;
GLenum samplerType;
SamplerFormat format;
// List of all textures bound to this sampler, of type textureType.
// Cropped by the amount of unused elements reported by the driver.
std::vector<GLuint> boundTextureUnits;
// [textureUnitsStartIndex, textureUnitsStartIndex+textureUnitsCount) Points to the subset in
// mSamplerBoundTextureUnits that stores the texture unit bound to this sampler. Cropped by the
// amount of unused elements reported by the driver.
uint16_t textureUnitsStartIndex;
uint16_t textureUnitsCount;
};
static_assert(std::is_trivially_copyable<SamplerBinding>(), "must be memcpy-able");
struct ImageBinding
{
@@ -304,6 +316,10 @@ class ProgramExecutable final : public angle::Subject
return mPODStruct.activeUniformBlockBindings;
}
const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
const std::vector<GLuint> &getSamplerBoundTextureUnits() const
{
return mSamplerBoundTextureUnits;
}
const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
std::vector<ImageBinding> *getImageBindings() { return &mImageBindings; }
const RangeUI &getDefaultUniformRange() const { return mPODStruct.defaultUniformRange; }
@@ -475,7 +491,8 @@ class ProgramExecutable final : public angle::Subject
// Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex,
std::vector<SamplerBinding> &samplerBindings);
const std::vector<SamplerBinding> &samplerBindings,
const std::vector<GLuint> &boundTextureUnits);
bool linkMergedVaryings(const Context *context,
const ProgramMergedVaryings &mergedVaryings,
@@ -616,6 +633,9 @@ class ProgramExecutable final : public angle::Subject
// An array of the samplers that are used by the program
std::vector<SamplerBinding> mSamplerBindings;
// List of all textures bound to all samplers. Each SamplerBinding will point to a subset in
// this vector.
std::vector<GLuint> mSamplerBoundTextureUnits;
// An array of the images that are used by the program
std::vector<ImageBinding> mImageBindings;

View File

@@ -1077,10 +1077,11 @@ void ProgramGL::markUnusedUniformLocations(std::vector<gl::VariableLocation> *un
{
GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationRef.index);
gl::SamplerBinding &samplerBinding = (*samplerBindings)[samplerIndex];
if (locationRef.arrayIndex < samplerBinding.boundTextureUnits.size())
if (locationRef.arrayIndex <
static_cast<unsigned int>(samplerBinding.textureUnitsCount))
{
// Crop unused sampler bindings in the sampler array.
samplerBinding.boundTextureUnits.resize(locationRef.arrayIndex);
SetBitField(samplerBinding.textureUnitsCount, locationRef.arrayIndex);
}
}
else if (mState.isImageUniformIndex(locationRef.index))

View File

@@ -1728,10 +1728,11 @@ angle::Result ProgramMtl::updateTextures(const gl::Context *glContext,
gl::TextureType textureType = samplerBinding.textureType;
for (uint32_t arrayElement = 0; arrayElement < samplerBinding.boundTextureUnits.size();
for (uint32_t arrayElement = 0; arrayElement < samplerBinding.textureUnitsCount;
++arrayElement)
{
GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
GLuint textureUnit = samplerBinding.getTextureUnit(
mState.getSamplerBoundTextureUnits(), arrayElement);
gl::Texture *texture = completeTextures[textureUnit];
gl::Sampler *sampler = contextMtl->getState().getSampler(textureUnit);
uint32_t textureSlot = mslBinding.textureBinding + arrayElement;

View File

@@ -493,7 +493,7 @@ angle::Result MTLGetMSL(const gl::Context *glContext,
if (isSamplerInStruct)
structSamplers.insert(mappedSamplerName);
originalSamplerBindings[mappedSamplerName].push_back(
{textureIndex, static_cast<uint32_t>(samplerBinding.boundTextureUnits.size())});
{textureIndex, static_cast<uint32_t>(samplerBinding.textureUnitsCount)});
}
for (gl::ShaderType type : {gl::ShaderType::Vertex, gl::ShaderType::Fragment})
{

View File

@@ -864,6 +864,7 @@ angle::Result ProgramExecutableVk::addTextureDescriptorSetDesc(
{
const std::vector<gl::SamplerBinding> &samplerBindings = executable.getSamplerBindings();
const std::vector<gl::LinkedUniform> &uniforms = executable.getUniforms();
const std::vector<GLuint> &samplerBoundTextureUnits = executable.getSamplerBoundTextureUnits();
for (uint32_t textureIndex = 0; textureIndex < samplerBindings.size(); ++textureIndex)
{
@@ -885,7 +886,7 @@ angle::Result ProgramExecutableVk::addTextureDescriptorSetDesc(
// The front-end always binds array sampler units sequentially.
const gl::SamplerBinding &samplerBinding = samplerBindings[textureIndex];
uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
uint32_t arraySize = static_cast<uint32_t>(samplerBinding.textureUnitsCount);
arraySize *= samplerUniform.getOuterArraySizeProduct();
const gl::ShaderType firstShaderType = samplerUniform.getFirstActiveShaderType();
@@ -896,11 +897,11 @@ angle::Result ProgramExecutableVk::addTextureDescriptorSetDesc(
// TODO: https://issuetracker.google.com/issues/158215272: how do we handle array of
// immutable samplers?
GLuint textureUnit = samplerBinding.boundTextureUnits[0];
GLuint textureUnit = samplerBinding.getTextureUnit(samplerBoundTextureUnits, 0);
if (activeTextures != nullptr &&
(*activeTextures)[textureUnit]->getImage().hasImmutableSampler())
{
ASSERT(samplerBinding.boundTextureUnits.size() == 1);
ASSERT(samplerBinding.textureUnitsCount == 1);
// In the case of samplerExternal2DY2YEXT, we need
// samplerYcbcrConversion object with IDENTITY conversion model

View File

@@ -5246,8 +5246,8 @@ void WriteDescriptorDescs::updateExecutableActiveTextures(
const ShaderInterfaceVariableInfo &info =
variableInfoMap.getVariableById(firstShaderType, samplerUniform.getId(firstShaderType));
uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
uint32_t descriptorCount = arraySize * samplerUniform.getOuterArraySizeProduct();
uint32_t arraySize = static_cast<uint32_t>(samplerBinding.textureUnitsCount);
uint32_t descriptorCount = arraySize * samplerUniform.getOuterArraySizeProduct();
VkDescriptorType descriptorType = (samplerBinding.textureType == gl::TextureType::Buffer)
? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
@@ -5533,7 +5533,7 @@ void UpdatePreCacheActiveTextures(const gl::ProgramExecutable &executable,
for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
{
const gl::SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
uint16_t arraySize = samplerBinding.textureUnitsCount;
bool isSamplerExternalY2Y = samplerBinding.samplerType == GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;
uint32_t uniformIndex = executable.getUniformIndexFromSamplerIndex(samplerIndex);
@@ -5548,9 +5548,10 @@ void UpdatePreCacheActiveTextures(const gl::ProgramExecutable &executable,
const ShaderInterfaceVariableInfo &info =
variableInfoMap.getVariableById(firstShaderType, samplerUniform.getId(firstShaderType));
for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
for (uint16_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
{
GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
GLuint textureUnit = samplerBinding.getTextureUnit(
executable.getSamplerBoundTextureUnits(), arrayElement);
if (!activeTextures.test(textureUnit))
continue;
TextureVk *textureVk = textures[textureUnit];
@@ -5606,8 +5607,9 @@ angle::Result DescriptorSetDescBuilder::updateFullActiveTextures(
const SharedDescriptorSetCacheKey &sharedCacheKey)
{
const std::vector<gl::SamplerBinding> &samplerBindings = executable.getSamplerBindings();
const std::vector<gl::LinkedUniform> &uniforms = executable.getUniforms();
const gl::ActiveTextureTypeArray &textureTypes = executable.getActiveSamplerTypes();
const std::vector<GLuint> &samplerBoundTextureUnits = executable.getSamplerBoundTextureUnits();
const std::vector<gl::LinkedUniform> &uniforms = executable.getUniforms();
const gl::ActiveTextureTypeArray &textureTypes = executable.getActiveSamplerTypes();
for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
{
@@ -5624,12 +5626,13 @@ angle::Result DescriptorSetDescBuilder::updateFullActiveTextures(
const ShaderInterfaceVariableInfo &info =
variableInfoMap.getVariableById(firstShaderType, samplerUniform.getId(firstShaderType));
uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
uint32_t arraySize = static_cast<uint32_t>(samplerBinding.textureUnitsCount);
bool isSamplerExternalY2Y = samplerBinding.samplerType == GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;
for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
{
GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
GLuint textureUnit =
samplerBinding.getTextureUnit(samplerBoundTextureUnits, arrayElement);
TextureVk *textureVk = textures[textureUnit];
uint32_t infoIndex = writeDescriptorDescs[info.binding].descriptorInfoIndex +