Commit 68083e89 by Tim Van Patten Committed by Commit Bot

Vulkan: Move cached samplers/images and has*() to ProgramExecutable

The active samplers and images are being moved from Program into ProgramExecutable to unify interacting with them for Programs and ProgramPipelines Also, create some helper functions for gl::Program that ProgramExecutable can call to make it easier for ProgramPipeline to respond to similar queries for each of the Programs in the ProgramPipeline. Bug: angleproject:3570 Change-Id: I0b37f1a379e56b9659d82d92f6d7a546beee11cd Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2087648 Commit-Queue: Tim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent bd2bdf9f
......@@ -732,6 +732,7 @@ void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
LoadShaderVariableBuffer(stream, block);
}
// TODO(timvp): http://anglebug.com/3570: Remove when PPOs are supported
size_t CountUniqueBlocks(const std::vector<InterfaceBlock> &blocks)
{
size_t count = 0;
......@@ -1107,11 +1108,10 @@ ProgramState::ProgramState()
mBaseVertexLocation(-1),
mBaseInstanceLocation(-1),
mCachedBaseVertex(0),
mCachedBaseInstance(0),
mActiveSamplerRefCounts{}
mCachedBaseInstance(0)
{
mComputeShaderLocalSize.fill(1);
mActiveSamplerTypes.fill(TextureType::InvalidEnum);
mExecutable.setProgramState(this);
}
ProgramState::~ProgramState()
......@@ -1130,6 +1130,7 @@ Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
return mAttachedShaders[shaderType];
}
// TODO(timvp): http://anglebug.com/3570: Remove when PPOs are supported
size_t ProgramState::getUniqueUniformBlockCount() const
{
return CountUniqueBlocks(mUniformBlocks);
......@@ -1140,6 +1141,11 @@ size_t ProgramState::getUniqueStorageBlockCount() const
return CountUniqueBlocks(mShaderStorageBlocks);
}
size_t ProgramState::getTransformFeedbackBufferCount() const
{
return mTransformFeedbackStrides.size();
}
GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
{
return GetResourceIndexFromName(mUniforms, name);
......@@ -1672,48 +1678,13 @@ void ProgramState::updateTransformFeedbackStrides()
void ProgramState::updateActiveSamplers()
{
mActiveSamplerRefCounts.fill(0);
for (SamplerBinding &samplerBinding : mSamplerBindings)
{
if (samplerBinding.unreferenced)
continue;
for (GLint textureUnit : samplerBinding.boundTextureUnits)
{
if (++mActiveSamplerRefCounts[textureUnit] == 1)
{
mActiveSamplerTypes[textureUnit] = samplerBinding.textureType;
mActiveSamplerFormats[textureUnit] = samplerBinding.format;
}
else
{
if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType)
{
mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
}
if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
{
mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
}
}
mActiveSamplersMask.set(textureUnit);
}
}
mExecutable.mActiveSamplerRefCounts.fill(0);
mExecutable.updateActiveSamplers(mSamplerBindings);
}
void ProgramState::updateActiveImages()
{
for (ImageBinding &imageBinding : mImageBindings)
{
if (imageBinding.unreferenced)
continue;
for (GLint imageUnit : imageBinding.boundImageUnits)
{
mActiveImagesMask.set(imageUnit);
}
}
mExecutable.updateActiveImages(mImageBindings);
}
void ProgramState::updateProgramInterfaceInputs()
......@@ -1826,7 +1797,6 @@ void Program::unlink()
mState.mComputeShaderLocalSize.fill(1);
mState.mSamplerBindings.clear();
mState.mImageBindings.clear();
mState.mActiveImagesMask.reset();
mState.mNumViews = -1;
mState.mGeometryShaderInputPrimitiveType = PrimitiveMode::Triangles;
mState.mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
......@@ -2979,14 +2949,15 @@ void Program::validate(const Caps &caps)
bool Program::validateSamplersImpl(InfoLog *infoLog, const Caps &caps)
{
const ProgramExecutable &executable = mState.mExecutable;
ASSERT(mLinkResolved);
// if any two active samplers in a program are of different types, but refer to the same
// texture image unit, and this is the current program, then ValidateProgram will fail, and
// DrawArrays and DrawElements will issue the INVALID_OPERATION error.
for (size_t textureUnit : mState.mActiveSamplersMask)
for (size_t textureUnit : executable.mActiveSamplersMask)
{
if (mState.mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
if (executable.mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
{
if (infoLog)
{
......@@ -4895,24 +4866,24 @@ void Program::updateSamplerUniform(Context *context,
boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
// Update the reference counts.
uint32_t &oldRefCount = mState.mActiveSamplerRefCounts[oldTextureUnit];
uint32_t &newRefCount = mState.mActiveSamplerRefCounts[newTextureUnit];
uint32_t &oldRefCount = mState.mExecutable.mActiveSamplerRefCounts[oldTextureUnit];
uint32_t &newRefCount = mState.mExecutable.mActiveSamplerRefCounts[newTextureUnit];
ASSERT(oldRefCount > 0);
ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
oldRefCount--;
newRefCount++;
// Check for binding type change.
TextureType &newSamplerType = mState.mActiveSamplerTypes[newTextureUnit];
TextureType &oldSamplerType = mState.mActiveSamplerTypes[oldTextureUnit];
SamplerFormat &newSamplerFormat = mState.mActiveSamplerFormats[newTextureUnit];
SamplerFormat &oldSamplerFormat = mState.mActiveSamplerFormats[oldTextureUnit];
TextureType &newSamplerType = mState.mExecutable.mActiveSamplerTypes[newTextureUnit];
TextureType &oldSamplerType = mState.mExecutable.mActiveSamplerTypes[oldTextureUnit];
SamplerFormat &newSamplerFormat = mState.mExecutable.mActiveSamplerFormats[newTextureUnit];
SamplerFormat &oldSamplerFormat = mState.mExecutable.mActiveSamplerFormats[oldTextureUnit];
if (newRefCount == 1)
{
newSamplerType = samplerBinding.textureType;
newSamplerFormat = samplerBinding.format;
mState.mActiveSamplersMask.set(newTextureUnit);
mState.mExecutable.mActiveSamplersMask.set(newTextureUnit);
}
else
{
......@@ -4932,7 +4903,7 @@ void Program::updateSamplerUniform(Context *context,
{
oldSamplerType = TextureType::InvalidEnum;
oldSamplerFormat = SamplerFormat::InvalidEnum;
mState.mActiveSamplersMask.reset(oldTextureUnit);
mState.mExecutable.mActiveSamplersMask.reset(oldTextureUnit);
}
else
{
......@@ -4958,44 +4929,7 @@ void Program::updateSamplerUniform(Context *context,
void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
{
bool foundBinding = false;
TextureType foundType = TextureType::InvalidEnum;
SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
for (const SamplerBinding &binding : mSamplerBindings)
{
if (binding.unreferenced)
continue;
// 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)
{
if (textureUnit == textureUnitIndex)
{
if (!foundBinding)
{
foundBinding = true;
foundType = binding.textureType;
foundFormat = binding.format;
}
else
{
if (foundType != binding.textureType)
{
foundType = TextureType::InvalidEnum;
}
if (foundFormat != binding.format)
{
foundFormat = SamplerFormat::InvalidEnum;
}
}
}
}
}
mActiveSamplerTypes[textureUnitIndex] = foundType;
mActiveSamplerFormats[textureUnitIndex] = foundFormat;
mExecutable.setSamplerUniformTextureTypeAndFormat(textureUnitIndex, mSamplerBindings);
}
template <typename T>
......
......@@ -30,6 +30,7 @@
#include "libANGLE/Error.h"
#include "libANGLE/InfoLog.h"
#include "libANGLE/ProgramExecutable.h"
#include "libANGLE/ProgramLinkedResources.h"
#include "libANGLE/RefCountObject.h"
#include "libANGLE/Uniform.h"
#include "libANGLE/angletypes.h"
......@@ -150,28 +151,6 @@ struct BindingInfo
bool valid;
};
// This small structure encapsulates binding sampler uniforms to active GL textures.
struct SamplerBinding
{
SamplerBinding(TextureType textureTypeIn,
SamplerFormat formatIn,
size_t elementCount,
bool unreferenced);
SamplerBinding(const SamplerBinding &other);
~SamplerBinding();
// Necessary for retrieving active textures from the GL state.
TextureType textureType;
SamplerFormat format;
// List of all textures bound to this sampler, of type textureType.
std::vector<GLuint> boundTextureUnits;
// A note if this sampler is an unreferenced uniform.
bool unreferenced;
};
// 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
......@@ -211,19 +190,6 @@ struct TransformFeedbackVarying : public sh::ShaderVariable
GLuint arrayIndex;
};
struct ImageBinding
{
ImageBinding(size_t count);
ImageBinding(GLuint imageUnit, size_t count, bool unreferenced);
ImageBinding(const ImageBinding &other);
~ImageBinding();
std::vector<GLuint> boundImageUnits;
// A note if this image unit is an unreferenced uniform.
bool unreferenced;
};
struct ProgramBinding
{
ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {}
......@@ -333,7 +299,6 @@ class ProgramState final : angle::NonCopyable
{
return mTransformFeedbackStrides;
}
size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); }
const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
{
return mAtomicCounterBuffers;
......@@ -342,6 +307,7 @@ class ProgramState final : angle::NonCopyable
// Count the number of uniform and storage buffer declarations, counting arrays as one.
size_t getUniqueUniformBlockCount() const;
size_t getUniqueStorageBlockCount() const;
size_t getTransformFeedbackBufferCount() const;
GLuint getUniformIndexFromName(const std::string &name) const;
GLuint getUniformIndexFromLocation(UniformLocation location) const;
......@@ -361,11 +327,6 @@ class ProgramState final : angle::NonCopyable
bool hasAttachedShader() const;
const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const
{
return mActiveSamplerFormats[textureUnitIndex];
}
ShaderType getFirstAttachedShaderStageType() const;
ShaderType getLastAttachedShaderStageType() const;
......@@ -377,6 +338,17 @@ class ProgramState final : angle::NonCopyable
const ProgramExecutable &getProgramExecutable() const { return mExecutable; }
ProgramExecutable &getProgramExecutable() { return mExecutable; }
bool hasDefaultUniforms() const { return !getDefaultUniformRange().empty(); }
bool hasTextures() const { return !getSamplerBindings().empty(); }
bool hasUniformBuffers() const { return !getUniformBlocks().empty(); }
bool hasStorageBuffers() const { return !getShaderStorageBlocks().empty(); }
bool hasAtomicCounterBuffers() const { return !getAtomicCounterBuffers().empty(); }
bool hasImages() const { return !getImageBindings().empty(); }
bool hasTransformFeedbackOutput() const
{
return !getLinkedTransformFeedbackVaryings().empty();
}
private:
friend class MemoryProgramCache;
friend class Program;
......@@ -396,6 +368,7 @@ class ProgramState final : angle::NonCopyable
ShaderMap<Shader *> mAttachedShaders;
uint32_t mLocationsUsedForXfbExtension;
std::vector<std::string> mTransformFeedbackVaryingNames;
std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
GLenum mTransformFeedbackBufferMode;
......@@ -475,15 +448,6 @@ class ProgramState final : angle::NonCopyable
// The size of the data written to each transform feedback buffer per vertex.
std::vector<GLsizei> mTransformFeedbackStrides;
// Cached mask of active samplers and sampler types.
ActiveTextureMask mActiveSamplersMask;
ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
ActiveTextureArray<TextureType> mActiveSamplerTypes;
ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
// Cached mask of active images.
ActiveTextureMask mActiveImagesMask;
// 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.
ProgramAliasedBindings mUniformLocationBindings;
......@@ -845,14 +809,6 @@ class Program final : angle::NonCopyable, public LabeledObject
const std::vector<GLsizei> &getTransformFeedbackStrides() const;
const ActiveTextureMask &getActiveSamplersMask() const { return mState.mActiveSamplersMask; }
const ActiveTextureMask &getActiveImagesMask() const { return mState.mActiveImagesMask; }
const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
{
return mState.mActiveSamplerTypes;
}
// Program dirty bits.
enum DirtyBitType
{
......
......@@ -8,10 +8,24 @@
#include "libANGLE/ProgramExecutable.h"
#include "libANGLE/Context.h"
namespace gl
{
ProgramExecutable::ProgramExecutable() : mMaxActiveAttribLocation(0) {}
ProgramExecutable::ProgramExecutable()
: mProgramState(nullptr),
mProgramPipelineState(nullptr),
mMaxActiveAttribLocation(0),
mAttributesTypeMask(0),
mAttributesMask(0),
mActiveSamplersMask(0),
mActiveSamplerRefCounts{},
mActiveImagesMask(0)
{
mActiveSamplerTypes.fill(TextureType::InvalidEnum);
mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
}
ProgramExecutable::~ProgramExecutable() = default;
......@@ -22,6 +36,13 @@ void ProgramExecutable::reset()
mAttributesTypeMask.reset();
mAttributesMask.reset();
mMaxActiveAttribLocation = 0;
mActiveSamplersMask.reset();
mActiveSamplerRefCounts = {};
mActiveSamplerTypes.fill(TextureType::InvalidEnum);
mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
mActiveImagesMask.reset();
}
int ProgramExecutable::getInfoLogLength() const
......@@ -54,4 +75,196 @@ AttributesMask ProgramExecutable::getAttributesMask() const
return mAttributesMask;
}
bool ProgramExecutable::hasDefaultUniforms(const gl::State &glState) const
{
ASSERT(mProgramState || mProgramPipelineState);
if (mProgramState)
{
return mProgramState->hasDefaultUniforms();
}
// TODO(timvp): http://anglebug.com/3570: Support program pipelines
return false;
}
bool ProgramExecutable::hasTextures(const gl::State &glState) const
{
ASSERT(mProgramState || mProgramPipelineState);
if (mProgramState)
{
return mProgramState->hasTextures();
}
// TODO(timvp): http://anglebug.com/3570: Support program pipelines
return false;
}
bool ProgramExecutable::hasUniformBuffers(const gl::State &glState) const
{
ASSERT(mProgramState || mProgramPipelineState);
if (mProgramState)
{
return mProgramState->hasUniformBuffers();
}
// TODO(timvp): http://anglebug.com/3570: Support program pipelines
return false;
}
bool ProgramExecutable::hasStorageBuffers(const gl::State &glState) const
{
ASSERT(mProgramState || mProgramPipelineState);
if (mProgramState)
{
return mProgramState->hasStorageBuffers();
}
// TODO(timvp): http://anglebug.com/3570: Support program pipelines
return false;
}
bool ProgramExecutable::hasAtomicCounterBuffers(const gl::State &glState) const
{
ASSERT(mProgramState || mProgramPipelineState);
if (mProgramState)
{
return mProgramState->hasAtomicCounterBuffers();
}
// TODO(timvp): http://anglebug.com/3570: Support program pipelines
return false;
}
bool ProgramExecutable::hasImages(const gl::State &glState) const
{
ASSERT(mProgramState || mProgramPipelineState);
if (mProgramState)
{
return mProgramState->hasImages();
}
// TODO(timvp): http://anglebug.com/3570: Support program pipelines
return false;
}
bool ProgramExecutable::hasTransformFeedbackOutput(const gl::State &glState) const
{
ASSERT(mProgramState || mProgramPipelineState);
if (mProgramState)
{
return mProgramState->hasTransformFeedbackOutput();
}
// TODO(timvp): http://anglebug.com/3570: Support program pipelines
return false;
}
size_t ProgramExecutable::getTransformFeedbackBufferCount(const gl::State &glState) const
{
ASSERT(mProgramState || mProgramPipelineState);
if (mProgramState)
{
return mProgramState->getTransformFeedbackBufferCount();
}
// TODO(timvp): http://anglebug.com/3570: Support program pipelines
return 0;
}
void ProgramExecutable::updateActiveSamplers(const std::vector<SamplerBinding> &samplerBindings)
{
for (const SamplerBinding &samplerBinding : samplerBindings)
{
if (samplerBinding.unreferenced)
continue;
for (GLint textureUnit : samplerBinding.boundTextureUnits)
{
if (++mActiveSamplerRefCounts[textureUnit] == 1)
{
mActiveSamplerTypes[textureUnit] = samplerBinding.textureType;
mActiveSamplerFormats[textureUnit] = samplerBinding.format;
}
else
{
if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType)
{
mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
}
if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
{
mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
}
}
mActiveSamplersMask.set(textureUnit);
}
}
}
void ProgramExecutable::updateActiveImages(std::vector<ImageBinding> &imageBindings)
{
for (ImageBinding &imageBinding : imageBindings)
{
if (imageBinding.unreferenced)
continue;
for (GLint imageUnit : imageBinding.boundImageUnits)
{
mActiveImagesMask.set(imageUnit);
}
}
}
void ProgramExecutable::setSamplerUniformTextureTypeAndFormat(
size_t textureUnitIndex,
std::vector<SamplerBinding> &samplerBindings)
{
bool foundBinding = false;
TextureType foundType = TextureType::InvalidEnum;
SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
for (const SamplerBinding &binding : samplerBindings)
{
if (binding.unreferenced)
continue;
// 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)
{
if (textureUnit == textureUnitIndex)
{
if (!foundBinding)
{
foundBinding = true;
foundType = binding.textureType;
foundFormat = binding.format;
}
else
{
if (foundType != binding.textureType)
{
foundType = TextureType::InvalidEnum;
}
if (foundFormat != binding.format)
{
foundFormat = SamplerFormat::InvalidEnum;
}
}
}
}
}
mActiveSamplerTypes[textureUnitIndex] = foundType;
mActiveSamplerFormats[textureUnitIndex] = foundFormat;
}
} // namespace gl
......@@ -17,6 +17,44 @@
namespace gl
{
// This small structure encapsulates binding sampler uniforms to active GL textures.
struct SamplerBinding
{
SamplerBinding(TextureType textureTypeIn,
SamplerFormat formatIn,
size_t elementCount,
bool unreferenced);
SamplerBinding(const SamplerBinding &other);
~SamplerBinding();
// Necessary for retrieving active textures from the GL state.
TextureType textureType;
SamplerFormat format;
// List of all textures bound to this sampler, of type textureType.
std::vector<GLuint> boundTextureUnits;
// A note if this sampler is an unreferenced uniform.
bool unreferenced;
};
struct ImageBinding
{
ImageBinding(size_t count);
ImageBinding(GLuint imageUnit, size_t count, bool unreferenced);
ImageBinding(const ImageBinding &other);
~ImageBinding();
std::vector<GLuint> boundImageUnits;
// A note if this image unit is an unreferenced uniform.
bool unreferenced;
};
class ProgramState;
class ProgramPipelineState;
class ProgramExecutable
{
public:
......@@ -51,6 +89,41 @@ class ProgramExecutable
const ComponentTypeMask &getAttributesTypeMask() const { return mAttributesTypeMask; }
AttributesMask getAttributesMask() const;
const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const
{
return mActiveSamplerFormats[textureUnitIndex];
}
const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; }
const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
{
return mActiveSamplerTypes;
}
bool hasDefaultUniforms(const gl::State &glState) const;
bool hasTextures(const gl::State &glState) const;
bool hasUniformBuffers(const gl::State &glState) const;
bool hasStorageBuffers(const gl::State &glState) const;
bool hasAtomicCounterBuffers(const gl::State &glState) const;
bool hasImages(const gl::State &glState) const;
bool hasTransformFeedbackOutput(const gl::State &glState) const;
// Count the number of uniform and storage buffer declarations, counting arrays as one.
size_t getTransformFeedbackBufferCount(const gl::State &glState) const;
// TODO: http://anglebug.com/4520: Remove mProgramState/mProgramPipelineState
void setProgramState(ProgramState *state)
{
ASSERT(!mProgramState && !mProgramPipelineState);
mProgramState = state;
}
void setProgramPipelineState(ProgramPipelineState *state)
{
ASSERT(!mProgramState && !mProgramPipelineState);
mProgramPipelineState = state;
}
private:
// TODO(timvp): http://anglebug.com/3570: Investigate removing these friend
// class declarations and accessing the necessary members with getters/setters.
......@@ -58,6 +131,17 @@ class ProgramExecutable
friend class ProgramPipeline;
friend class ProgramState;
void updateActiveSamplers(const std::vector<SamplerBinding> &samplerBindings);
void updateActiveImages(std::vector<ImageBinding> &imageBindings);
// Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex,
std::vector<SamplerBinding> &samplerBindings);
// TODO: http://anglebug.com/4520: Remove mProgramState/mProgramPipelineState
ProgramState *mProgramState;
ProgramPipelineState *mProgramPipelineState;
InfoLog mInfoLog;
ShaderBitSet mLinkedShaderStages;
......@@ -67,6 +151,15 @@ class ProgramExecutable
ComponentTypeMask mAttributesTypeMask;
// mAttributesMask is identical to mActiveAttribLocationsMask with built-in attributes removed.
AttributesMask mAttributesMask;
// Cached mask of active samplers and sampler types.
ActiveTextureMask mActiveSamplersMask;
ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
ActiveTextureArray<TextureType> mActiveSamplerTypes;
ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
// Cached mask of active images.
ActiveTextureMask mActiveImagesMask;
};
} // namespace gl
......
......@@ -17,7 +17,10 @@
namespace gl
{
ProgramPipelineState::ProgramPipelineState() : mLabel() {}
ProgramPipelineState::ProgramPipelineState() : mLabel()
{
mExecutable.setProgramPipelineState(this);
}
ProgramPipelineState::~ProgramPipelineState() {}
......
......@@ -587,7 +587,7 @@ void State::reset(const Context *context)
ANGLE_INLINE void State::unsetActiveTextures(ActiveTextureMask textureMask)
{
// Unset any relevant bound textures.
for (size_t textureIndex : mProgram->getActiveSamplersMask())
for (size_t textureIndex : mExecutable->getActiveSamplersMask())
{
mActiveTexturesCache.reset(textureIndex);
mCompleteTextureBindings[textureIndex].reset();
......@@ -624,8 +624,7 @@ ANGLE_INLINE void State::updateActiveTextureState(const Context *context,
sampler ? sampler->getSamplerState() : texture->getSamplerState();
mTexturesIncompatibleWithSamplers[textureIndex] =
!texture->getTextureState().compatibleWithSamplerFormat(
mProgram->getState().getSamplerFormatForTextureUnitIndex(textureIndex),
samplerState);
mExecutable->getSamplerFormatForTextureUnitIndex(textureIndex), samplerState);
}
else
{
......@@ -1389,8 +1388,8 @@ void State::setSamplerTexture(const Context *context, TextureType type, Texture
{
mSamplerTextures[type][mActiveSampler].set(context, texture);
if (mProgram && mProgram->getActiveSamplersMask()[mActiveSampler] &&
IsTextureCompatibleWithSampler(type, mProgram->getActiveSamplerTypes()[mActiveSampler]))
if (mExecutable && mExecutable->getActiveSamplersMask()[mActiveSampler] &&
IsTextureCompatibleWithSampler(type, mExecutable->getActiveSamplerTypes()[mActiveSampler]))
{
updateActiveTexture(context, mActiveSampler, texture);
}
......@@ -1698,7 +1697,7 @@ angle::Result State::setProgram(const Context *context, Program *newProgram)
{
if (mProgram)
{
unsetActiveTextures(mProgram->getActiveSamplersMask());
unsetActiveTextures(mExecutable->getActiveSamplersMask());
mProgram->release(context);
}
......@@ -2908,7 +2907,7 @@ angle::Result State::syncTexturesInit(const Context *context)
if (!mProgram)
return angle::Result::Continue;
for (size_t textureUnitIndex : mProgram->getActiveSamplersMask())
for (size_t textureUnitIndex : mExecutable->getActiveSamplersMask())
{
Texture *texture = mActiveTexturesCache[textureUnitIndex];
if (texture)
......@@ -2923,7 +2922,7 @@ angle::Result State::syncImagesInit(const Context *context)
{
ASSERT(mRobustResourceInit);
ASSERT(mProgram);
for (size_t imageUnitIndex : mProgram->getActiveImagesMask())
for (size_t imageUnitIndex : mExecutable->getActiveImagesMask())
{
Texture *texture = mImageUnits[imageUnitIndex].texture.get();
if (texture)
......@@ -3100,8 +3099,9 @@ angle::Result State::onProgramExecutableChange(const Context *context, Program *
}
// Set any bound textures.
const ActiveTextureTypeArray &textureTypes = program->getActiveSamplerTypes();
for (size_t textureIndex : program->getActiveSamplersMask())
const ProgramExecutable &executable = program->getExecutable();
const ActiveTextureTypeArray &textureTypes = executable.getActiveSamplerTypes();
for (size_t textureIndex : executable.getActiveSamplersMask())
{
TextureType type = textureTypes[textureIndex];
......@@ -3113,7 +3113,7 @@ angle::Result State::onProgramExecutableChange(const Context *context, Program *
updateActiveTexture(context, textureIndex, texture);
}
for (size_t imageUnitIndex : program->getActiveImagesMask())
for (size_t imageUnitIndex : executable.getActiveImagesMask())
{
Texture *image = mImageUnits[imageUnitIndex].texture.get();
if (!image)
......@@ -3180,7 +3180,7 @@ void State::onActiveTextureChange(const Context *context, size_t textureUnit)
{
if (mProgram)
{
TextureType type = mProgram->getActiveSamplerTypes()[textureUnit];
TextureType type = mExecutable->getActiveSamplerTypes()[textureUnit];
if (type != TextureType::InvalidEnum)
{
Texture *activeTexture = getTextureForActiveSampler(type, textureUnit);
......@@ -3193,7 +3193,7 @@ void State::onActiveTextureStateChange(const Context *context, size_t textureUni
{
if (mProgram)
{
TextureType type = mProgram->getActiveSamplerTypes()[textureUnit];
TextureType type = mExecutable->getActiveSamplerTypes()[textureUnit];
if (type != TextureType::InvalidEnum)
{
Texture *activeTexture = getTextureForActiveSampler(type, textureUnit);
......
......@@ -717,7 +717,7 @@ class State : angle::NonCopyable
ANGLE_INLINE bool validateSamplerFormats() const
{
return (mTexturesIncompatibleWithSamplers & mProgram->getActiveSamplersMask()).none();
return (mTexturesIncompatibleWithSamplers & mExecutable->getActiveSamplersMask()).none();
}
ProvokingVertexConvention getProvokingVertex() const { return mProvokingVertex; }
......
......@@ -814,12 +814,16 @@ angle::Result StateManagerGL::onMakeCurrent(const gl::Context *context)
void StateManagerGL::updateProgramTextureBindings(const gl::Context *context)
{
const gl::State &glState = context->getState();
const gl::Program *program = glState.getProgram();
const gl::State &glState = context->getState();
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
// It is possible there is no active program during a path operation.
if (!executable)
return;
const gl::ActiveTexturesCache &textures = glState.getActiveTexturesCache();
const gl::ActiveTextureMask &activeTextures = program->getActiveSamplersMask();
const gl::ActiveTextureTypeArray &textureTypes = program->getActiveSamplerTypes();
const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
for (size_t textureUnitIndex : activeTextures)
{
......@@ -930,11 +934,16 @@ void StateManagerGL::updateProgramAtomicCounterBufferBindings(const gl::Context
void StateManagerGL::updateProgramImageBindings(const gl::Context *context)
{
const gl::State &glState = context->getState();
const gl::Program *program = glState.getProgram();
const gl::State &glState = context->getState();
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
const gl::Program *program = glState.getProgram();
ASSERT(context->getClientVersion() >= gl::ES_3_1 || program->getImageBindings().size() == 0);
for (size_t imageUnitIndex : program->getActiveImagesMask())
// It is possible there is no active program during a path operation.
if (!executable || !program)
return;
ASSERT(context->getClientVersion() >= gl::ES_3_1 || program->getImageBindings().empty());
for (size_t imageUnitIndex : executable->getActiveImagesMask())
{
const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
const TextureGL *textureGL = SafeGetImplAs<TextureGL>(imageUnit.texture.get());
......@@ -1755,12 +1764,14 @@ void StateManagerGL::syncState(const gl::Context *context,
}
case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
{
const gl::Program *program = state.getProgram();
if (program)
const gl::Program *program = state.getProgram();
const gl::ProgramExecutable *executable = state.getProgramExecutable();
if (program && executable)
{
iter.setLaterBit(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
if (program->getActiveImagesMask().any())
if (executable->getActiveImagesMask().any())
{
iter.setLaterBit(gl::State::DIRTY_BIT_IMAGE_BINDINGS);
}
......
......@@ -21,20 +21,25 @@ enum class GlslangError
InvalidSpirv,
};
struct GlslangSourceOptions
struct GlslangProgramInterfaceInfo
{
// Uniforms set index:
uint32_t uniformsAndXfbDescriptorSetIndex = 0;
uint32_t uniformsAndXfbDescriptorSetIndex;
// Textures set index:
uint32_t textureDescriptorSetIndex = 1;
uint32_t textureDescriptorSetIndex;
// Other shader resources set index:
uint32_t shaderResourceDescriptorSetIndex = 2;
uint32_t shaderResourceDescriptorSetIndex;
// ANGLE driver uniforms set index:
uint32_t driverUniformsDescriptorSetIndex = 3;
uint32_t driverUniformsDescriptorSetIndex;
// Binding index start for transform feedback buffers:
uint32_t xfbBindingIndexStart = 16;
uint32_t xfbBindingIndexStart;
uint32_t locationsUsedForXfbExtension;
};
struct GlslangSourceOptions
{
bool useOldRewriteStructSamplers = false;
bool supportsTransformFeedbackExtension = false;
bool emulateTransformFeedback = false;
......@@ -86,6 +91,7 @@ std::string GlslangGetMappedSamplerName(const std::string &originalName);
void GlslangGetShaderSource(const GlslangSourceOptions &options,
const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources,
GlslangProgramInterfaceInfo *programInterfaceInfo,
gl::ShaderMap<std::string> *shaderSourcesOut,
ShaderInterfaceVariableInfoMap *variableInfoMapOut);
......
......@@ -1538,7 +1538,7 @@ angle::Result ContextMtl::handleDirtyActiveTextures(const gl::Context *context)
const gl::Program *program = glState.getProgram();
const gl::ActiveTexturesCache &textures = glState.getActiveTexturesCache();
const gl::ActiveTextureMask &activeTextures = program->getActiveSamplersMask();
const gl::ActiveTextureMask &activeTextures = program->getExecutable().getActiveSamplersMask();
for (size_t textureUnit : activeTextures)
{
......
......@@ -22,21 +22,25 @@ angle::Result HandleError(ErrorHandler *context, GlslangError)
return angle::Result::Stop;
}
GlslangSourceOptions CreateSourceOptions()
void ResetGlslangProgramInterfaceInfo(GlslangProgramInterfaceInfo *programInterfaceInfo)
{
GlslangSourceOptions options;
// We don't actually use descriptor set for now, the actual binding will be done inside
// ProgramMtl using spirv-cross.
options.uniformsAndXfbDescriptorSetIndex = kDefaultUniformsBindingIndex;
options.textureDescriptorSetIndex = 0;
options.driverUniformsDescriptorSetIndex = kDriverUniformsBindingIndex;
programInterfaceInfo->uniformsAndXfbDescriptorSetIndex = kDefaultUniformsBindingIndex;
programInterfaceInfo->textureDescriptorSetIndex = 0;
programInterfaceInfo->driverUniformsDescriptorSetIndex = kDriverUniformsBindingIndex;
// NOTE(hqle): Unused for now, until we support ES 3.0
options.shaderResourceDescriptorSetIndex = -1;
options.xfbBindingIndexStart = -1;
programInterfaceInfo->shaderResourceDescriptorSetIndex = -1;
programInterfaceInfo->xfbBindingIndexStart = -1;
programInterfaceInfo->locationsUsedForXfbExtension = 0;
static_assert(kDefaultUniformsBindingIndex != 0, "kDefaultUniformsBindingIndex must not be 0");
static_assert(kDriverUniformsBindingIndex != 0, "kDriverUniformsBindingIndex must not be 0");
}
GlslangSourceOptions CreateSourceOptions()
{
GlslangSourceOptions options;
return options;
}
} // namespace
......@@ -46,8 +50,11 @@ void GlslangGetShaderSource(const gl::ProgramState &programState,
gl::ShaderMap<std::string> *shaderSourcesOut,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{
rx::GlslangGetShaderSource(CreateSourceOptions(), programState, resources, shaderSourcesOut,
variableInfoMapOut);
GlslangProgramInterfaceInfo programInterfaceInfo;
ResetGlslangProgramInterfaceInfo(&programInterfaceInfo);
rx::GlslangGetShaderSource(CreateSourceOptions(), programState, resources,
&programInterfaceInfo, shaderSourcesOut, variableInfoMapOut);
}
angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
......
......@@ -24,29 +24,43 @@ angle::Result ErrorHandler(vk::Context *context, GlslangError)
GlslangSourceOptions CreateSourceOptions(const angle::FeaturesVk &features)
{
GlslangSourceOptions options;
options.uniformsAndXfbDescriptorSetIndex = kUniformsAndXfbDescriptorSetIndex;
options.textureDescriptorSetIndex = kTextureDescriptorSetIndex;
options.shaderResourceDescriptorSetIndex = kShaderResourceDescriptorSetIndex;
options.driverUniformsDescriptorSetIndex = kDriverUniformsDescriptorSetIndex;
options.xfbBindingIndexStart = kXfbBindingIndexStart;
options.useOldRewriteStructSamplers = features.forceOldRewriteStructSamplers.enabled;
options.useOldRewriteStructSamplers = features.forceOldRewriteStructSamplers.enabled;
options.supportsTransformFeedbackExtension =
features.supportsTransformFeedbackExtension.enabled;
options.emulateTransformFeedback = features.emulateTransformFeedback.enabled;
options.emulateBresenhamLines = features.basicGLLineRasterization.enabled;
return options;
}
} // namespace
// static
void GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(
GlslangProgramInterfaceInfo *glslangProgramInterfaceInfo)
{
glslangProgramInterfaceInfo->uniformsAndXfbDescriptorSetIndex =
kUniformsAndXfbDescriptorSetIndex;
glslangProgramInterfaceInfo->textureDescriptorSetIndex = kTextureDescriptorSetIndex;
glslangProgramInterfaceInfo->shaderResourceDescriptorSetIndex =
kShaderResourceDescriptorSetIndex;
glslangProgramInterfaceInfo->driverUniformsDescriptorSetIndex =
kDriverUniformsDescriptorSetIndex;
glslangProgramInterfaceInfo->xfbBindingIndexStart = kXfbBindingIndexStart;
glslangProgramInterfaceInfo->locationsUsedForXfbExtension = 0;
}
// static
void GlslangWrapperVk::GetShaderSource(const angle::FeaturesVk &features,
const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources,
GlslangProgramInterfaceInfo *programInterfaceInfo,
gl::ShaderMap<std::string> *shaderSourcesOut,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{
GlslangGetShaderSource(CreateSourceOptions(features), programState, resources, shaderSourcesOut,
variableInfoMapOut);
GlslangGetShaderSource(CreateSourceOptions(features), programState, resources,
programInterfaceInfo, shaderSourcesOut, variableInfoMapOut);
}
// static
......
......@@ -25,9 +25,13 @@ namespace rx
class GlslangWrapperVk
{
public:
static void ResetGlslangProgramInterfaceInfo(
GlslangProgramInterfaceInfo *glslangProgramInterfaceInfo);
static void GetShaderSource(const angle::FeaturesVk &features,
const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources,
GlslangProgramInterfaceInfo *programInterfaceInfo,
gl::ShaderMap<std::string> *shaderSourcesOut,
ShaderInterfaceVariableInfoMap *variableInfoMapOut);
......
......@@ -470,7 +470,9 @@ ProgramVk::ProgramVk(const gl::ProgramState &state)
mStorageBlockBindingsOffset(0),
mAtomicCounterBufferBindingsOffset(0),
mImageBindingsOffset(0)
{}
{
GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&mGlslangProgramInterfaceInfo);
}
ProgramVk::~ProgramVk() = default;
......@@ -516,6 +518,8 @@ void ProgramVk::reset(ContextVk *contextVk)
mTextureDescriptorsCache.clear();
mDescriptorBuffersCache.clear();
GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&mGlslangProgramInterfaceInfo);
}
std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context,
......@@ -607,7 +611,8 @@ std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context,
gl::ShaderMap<std::string> shaderSources;
ShaderInterfaceVariableInfoMap variableInfoMap;
GlslangWrapperVk::GetShaderSource(contextVk->getRenderer()->getFeatures(), mState, resources,
&shaderSources, &variableInfoMap);
&mGlslangProgramInterfaceInfo, &shaderSources,
&variableInfoMap);
// Compile the shaders.
angle::Result status = mShaderInfo.initShaders(contextVk, shaderSources, variableInfoMap);
......@@ -652,8 +657,10 @@ angle::Result ProgramVk::linkImpl(const gl::Context *glContext, gl::InfoLog &inf
if (glExecutable.hasLinkedShaderStage(gl::ShaderType::Vertex) && transformFeedback &&
!mState.getLinkedTransformFeedbackVaryings().empty())
{
size_t xfbBufferCount = mState.getTransformFeedbackBufferCount();
TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
transformFeedbackVk->updateDescriptorSetLayout(contextVk, mState, &uniformsAndXfbSetDesc);
transformFeedbackVk->updateDescriptorSetLayout(contextVk, xfbBufferCount,
&uniformsAndXfbSetDesc);
}
ANGLE_TRY(renderer->getDescriptorSetLayout(
......
......@@ -352,6 +352,8 @@ class ProgramVk : public ProgramImpl
// cache management. It can also allow fewer descriptors for shaders which use fewer
// textures/buffers.
vk::DescriptorSetLayoutArray<vk::DynamicDescriptorPool> mDynamicDescriptorPools;
GlslangProgramInterfaceInfo mGlslangProgramInterfaceInfo;
};
} // namespace rx
......
......@@ -161,14 +161,12 @@ angle::Result TransformFeedbackVk::bindIndexedBuffer(
void TransformFeedbackVk::updateDescriptorSetLayout(
ContextVk *contextVk,
const gl::ProgramState &programState,
size_t xfbBufferCount,
vk::DescriptorSetLayoutDesc *descSetLayoutOut) const
{
if (!contextVk->getFeatures().emulateTransformFeedback.enabled)
return;
size_t xfbBufferCount = programState.getTransformFeedbackBufferCount();
for (uint32_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
{
descSetLayoutOut->update(kXfbBindingIndexStart + bufferIndex,
......@@ -207,7 +205,9 @@ void TransformFeedbackVk::updateDescriptorSet(ContextVk *contextVk,
const std::vector<gl::OffsetBindingPointer<gl::Buffer>> &xfbBuffers =
mState.getIndexedBuffers();
size_t xfbBufferCount = programState.getTransformFeedbackBufferCount();
const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
ASSERT(executable);
size_t xfbBufferCount = executable->getTransformFeedbackBufferCount(contextVk->getState());
ASSERT(xfbBufferCount > 0);
ASSERT(programState.getTransformFeedbackBufferMode() != GL_INTERLEAVED_ATTRIBS ||
......@@ -239,7 +239,6 @@ void TransformFeedbackVk::updateDescriptorSet(ContextVk *contextVk,
}
void TransformFeedbackVk::getBufferOffsets(ContextVk *contextVk,
const gl::ProgramState &programState,
GLint drawCallFirstVertex,
int32_t *offsetsOut,
size_t offsetsSize) const
......@@ -250,7 +249,9 @@ void TransformFeedbackVk::getBufferOffsets(ContextVk *contextVk,
GLsizeiptr verticesDrawn = mState.getVerticesDrawn();
const std::vector<GLsizei> &bufferStrides =
mState.getBoundProgram()->getTransformFeedbackStrides();
size_t xfbBufferCount = programState.getTransformFeedbackBufferCount();
const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
ASSERT(executable);
size_t xfbBufferCount = executable->getTransformFeedbackBufferCount(contextVk->getState());
ASSERT(xfbBufferCount > 0);
......
......@@ -54,7 +54,7 @@ class TransformFeedbackVk : public TransformFeedbackImpl
const gl::OffsetBindingPointer<gl::Buffer> &binding) override;
void updateDescriptorSetLayout(ContextVk *contextVk,
const gl::ProgramState &programState,
size_t xfbBufferCount,
vk::DescriptorSetLayoutDesc *descSetLayoutOut) const;
void initDescriptorSet(ContextVk *contextVk,
size_t xfbBufferCount,
......@@ -64,7 +64,6 @@ class TransformFeedbackVk : public TransformFeedbackImpl
const gl::ProgramState &programState,
VkDescriptorSet descSet) const;
void getBufferOffsets(ContextVk *contextVk,
const gl::ProgramState &programState,
GLint drawCallFirstVertex,
int32_t *offsetsOut,
size_t offsetsSize) const;
......
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