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);
}
......
......@@ -358,6 +358,7 @@ std::string GenerateTransformFeedbackVaryingOutput(const gl::TransformFeedbackVa
void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &options,
const gl::ProgramState &programState,
GlslangProgramInterfaceInfo *programInterfaceInfo,
std::string *vertexShader,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{
......@@ -368,15 +369,16 @@ void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &optio
programState.getTransformFeedbackBufferMode() == GL_INTERLEAVED_ATTRIBS;
const size_t bufferCount = isInterleaved ? 1 : varyings.size();
const std::string xfbSet = Str(options.uniformsAndXfbDescriptorSetIndex);
const std::string xfbSet = Str(programInterfaceInfo->uniformsAndXfbDescriptorSetIndex);
std::vector<std::string> xfbIndices(bufferCount);
std::string xfbDecl;
for (uint32_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
{
const std::string xfbBinding = Str(options.xfbBindingIndexStart + bufferIndex);
xfbIndices[bufferIndex] = Str(bufferIndex);
const std::string xfbBinding =
Str(programInterfaceInfo->xfbBindingIndexStart + bufferIndex);
xfbIndices[bufferIndex] = Str(bufferIndex);
std::string bufferName = "xfbBuffer" + xfbIndices[bufferIndex];
......@@ -385,8 +387,9 @@ void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &optio
// Add this entry to the info map, so we can easily assert that every resource has an entry
// in this map.
AddResourceInfo(variableInfoMapOut, bufferName, options.uniformsAndXfbDescriptorSetIndex,
options.xfbBindingIndexStart + bufferIndex);
AddResourceInfo(variableInfoMapOut, bufferName,
programInterfaceInfo->uniformsAndXfbDescriptorSetIndex,
programInterfaceInfo->xfbBindingIndexStart + bufferIndex);
}
std::string xfbOut =
......@@ -444,7 +447,6 @@ bool IsFirstRegisterOfVarying(const gl::PackedVaryingRegister &varyingReg)
void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources,
std::string *vertexShader,
ShaderInterfaceVariableInfoMap *variableInfoMapOut,
uint32_t *locationsUsedForXfbExtensionOut)
{
const std::vector<gl::TransformFeedbackVarying> &tfVaryings =
......@@ -543,10 +545,10 @@ void AssignOutputLocations(const gl::ProgramState &programState,
void AssignVaryingLocations(const GlslangSourceOptions &options,
const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources,
uint32_t locationsUsedForXfbExtension,
GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{
uint32_t locationsUsedForEmulation = locationsUsedForXfbExtension;
uint32_t locationsUsedForEmulation = programInterfaceInfo->locationsUsedForXfbExtension;
const gl::ProgramExecutable &glExecutable = programState.getProgramExecutable();
// Substitute layout and qualifier strings for the position varying added for line raster
......@@ -733,6 +735,7 @@ void AssignTransformFeedbackExtensionQualifiers(const gl::ProgramState &programS
void AssignUniformBindings(const GlslangSourceOptions &options,
gl::ShaderMap<std::string> *shaderSources,
GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{
// Assign binding to the default uniforms block of each shader stage.
......@@ -743,19 +746,20 @@ void AssignUniformBindings(const GlslangSourceOptions &options,
if (!shaderSource.empty())
{
AddResourceInfo(variableInfoMapOut, kDefaultUniformNames[shaderType],
options.uniformsAndXfbDescriptorSetIndex, bindingIndex);
programInterfaceInfo->uniformsAndXfbDescriptorSetIndex, bindingIndex);
++bindingIndex;
}
}
// Assign binding to the driver uniforms block
AddResourceInfo(variableInfoMapOut, sh::vk::kDriverUniformsBlockName,
options.driverUniformsDescriptorSetIndex, 0);
programInterfaceInfo->driverUniformsDescriptorSetIndex, 0);
}
uint32_t AssignInterfaceBlockBindings(const GlslangSourceOptions &options,
const std::vector<gl::InterfaceBlock> &blocks,
uint32_t bindingStart,
GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{
uint32_t bindingIndex = bindingStart;
......@@ -764,7 +768,7 @@ uint32_t AssignInterfaceBlockBindings(const GlslangSourceOptions &options,
if (!block.isArray || block.arrayElement == 0)
{
AddResourceInfo(variableInfoMapOut, block.mappedName,
options.shaderResourceDescriptorSetIndex, bindingIndex);
programInterfaceInfo->shaderResourceDescriptorSetIndex, bindingIndex);
++bindingIndex;
}
}
......@@ -775,6 +779,7 @@ uint32_t AssignInterfaceBlockBindings(const GlslangSourceOptions &options,
uint32_t AssignAtomicCounterBufferBindings(const GlslangSourceOptions &options,
const std::vector<gl::AtomicCounterBuffer> &buffers,
uint32_t bindingStart,
GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{
if (buffers.size() == 0)
......@@ -783,7 +788,7 @@ uint32_t AssignAtomicCounterBufferBindings(const GlslangSourceOptions &options,
}
AddResourceInfo(variableInfoMapOut, sh::vk::kAtomicCountersBlockName,
options.shaderResourceDescriptorSetIndex, bindingStart);
programInterfaceInfo->shaderResourceDescriptorSetIndex, bindingStart);
return bindingStart + 1;
}
......@@ -792,6 +797,7 @@ uint32_t AssignImageBindings(const GlslangSourceOptions &options,
const std::vector<gl::LinkedUniform> &uniforms,
const gl::RangeUI &imageUniformRange,
uint32_t bindingStart,
GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{
uint32_t bindingIndex = bindingStart;
......@@ -802,8 +808,8 @@ uint32_t AssignImageBindings(const GlslangSourceOptions &options,
std::string name = imageUniform.mappedName;
if (GetImageNameWithoutIndices(&name))
{
AddResourceInfo(variableInfoMapOut, name, options.shaderResourceDescriptorSetIndex,
bindingIndex);
AddResourceInfo(variableInfoMapOut, name,
programInterfaceInfo->shaderResourceDescriptorSetIndex, bindingIndex);
}
++bindingIndex;
}
......@@ -813,31 +819,33 @@ uint32_t AssignImageBindings(const GlslangSourceOptions &options,
void AssignNonTextureBindings(const GlslangSourceOptions &options,
const gl::ProgramState &programState,
GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{
uint32_t bindingStart = 0;
const std::vector<gl::InterfaceBlock> &uniformBlocks = programState.getUniformBlocks();
bindingStart =
AssignInterfaceBlockBindings(options, uniformBlocks, bindingStart, variableInfoMapOut);
bindingStart = AssignInterfaceBlockBindings(options, uniformBlocks, bindingStart,
programInterfaceInfo, variableInfoMapOut);
const std::vector<gl::InterfaceBlock> &storageBlocks = programState.getShaderStorageBlocks();
bindingStart =
AssignInterfaceBlockBindings(options, storageBlocks, bindingStart, variableInfoMapOut);
bindingStart = AssignInterfaceBlockBindings(options, storageBlocks, bindingStart,
programInterfaceInfo, variableInfoMapOut);
const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
programState.getAtomicCounterBuffers();
bindingStart = AssignAtomicCounterBufferBindings(options, atomicCounterBuffers, bindingStart,
variableInfoMapOut);
programInterfaceInfo, variableInfoMapOut);
const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms();
const gl::RangeUI &imageUniformRange = programState.getImageUniformRange();
bindingStart =
AssignImageBindings(options, uniforms, imageUniformRange, bindingStart, variableInfoMapOut);
bindingStart = AssignImageBindings(options, uniforms, imageUniformRange, bindingStart,
programInterfaceInfo, variableInfoMapOut);
}
void AssignTextureBindings(const GlslangSourceOptions &options,
const gl::ProgramState &programState,
GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{
// Assign textures to a descriptor set and binding.
......@@ -861,8 +869,8 @@ void AssignTextureBindings(const GlslangSourceOptions &options,
? GetMappedSamplerNameOld(samplerUniform.name)
: GlslangGetMappedSamplerName(samplerUniform.name);
AddResourceInfo(variableInfoMapOut, samplerName, options.textureDescriptorSetIndex,
bindingIndex);
AddResourceInfo(variableInfoMapOut, samplerName,
programInterfaceInfo->textureDescriptorSetIndex, bindingIndex);
}
++bindingIndex;
......@@ -1785,13 +1793,12 @@ 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)
{
variableInfoMapOut->clear();
uint32_t locationsUsedForXfbExtension = 0;
for (const gl::ShaderType shaderType : gl::AllShaderTypes())
{
gl::Shader *glShader = programState.getAttachedShader(shaderType);
......@@ -1813,14 +1820,14 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options,
{
if (options.supportsTransformFeedbackExtension)
{
GenerateTransformFeedbackExtensionOutputs(programState, resources, vertexSource,
variableInfoMapOut,
&locationsUsedForXfbExtension);
GenerateTransformFeedbackExtensionOutputs(
programState, resources, vertexSource,
&programInterfaceInfo->locationsUsedForXfbExtension);
}
else if (options.emulateTransformFeedback)
{
GenerateTransformFeedbackEmulationOutputs(options, programState, vertexSource,
variableInfoMapOut);
GenerateTransformFeedbackEmulationOutputs(
options, programState, programInterfaceInfo, vertexSource, variableInfoMapOut);
}
}
}
......@@ -1840,20 +1847,21 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options,
if (computeSource.empty())
{
// Assign varying locations.
AssignVaryingLocations(options, programState, resources, locationsUsedForXfbExtension,
AssignVaryingLocations(options, programState, resources, programInterfaceInfo,
variableInfoMapOut);
if (!programState.getLinkedTransformFeedbackVaryings().empty() &&
options.supportsTransformFeedbackExtension)
{
AssignTransformFeedbackExtensionQualifiers(
programState, resources, locationsUsedForXfbExtension, variableInfoMapOut);
programState, resources, programInterfaceInfo->locationsUsedForXfbExtension,
variableInfoMapOut);
}
}
AssignUniformBindings(options, shaderSourcesOut, variableInfoMapOut);
AssignTextureBindings(options, programState, variableInfoMapOut);
AssignNonTextureBindings(options, programState, variableInfoMapOut);
AssignUniformBindings(options, shaderSourcesOut, programInterfaceInfo, variableInfoMapOut);
AssignTextureBindings(options, programState, programInterfaceInfo, variableInfoMapOut);
AssignNonTextureBindings(options, programState, programInterfaceInfo, variableInfoMapOut);
}
angle::Result GlslangGetShaderSpirvCode(GlslangErrorCallback callback,
......
......@@ -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,
......
......@@ -1223,9 +1223,9 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
vk::CommandBuffer *commandBuffer,
CommandBufferHelper *commandBufferHelper)
{
const gl::State &glState = mState;
const gl::ProgramExecutable *programExecutable = glState.getProgramExecutable();
const gl::ActiveTextureMask &activeTextures = mProgram->getState().getActiveSamplersMask();
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
for (size_t textureUnit : activeTextures)
{
......@@ -1242,15 +1242,13 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
vk::ImageLayout textureLayout;
if (textureVk->isBoundAsImageTexture())
{
textureLayout = programExecutable->isCompute()
? vk::ImageLayout::ComputeShaderWrite
: vk::ImageLayout::AllGraphicsShadersWrite;
textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite
: vk::ImageLayout::AllGraphicsShadersWrite;
}
else
{
textureLayout = programExecutable->isCompute()
? vk::ImageLayout::ComputeShaderReadOnly
: vk::ImageLayout::AllGraphicsShadersReadOnly;
textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderReadOnly
: vk::ImageLayout::AllGraphicsShadersReadOnly;
}
commandBufferHelper->imageRead(&mResourceUseList, image.getAspectFlags(), textureLayout,
&image);
......@@ -1267,7 +1265,7 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
}
}
if (mProgram->hasTextures())
if (executable->hasTextures(mState))
{
ANGLE_TRY(mProgram->updateTexturesDescriptorSet(this));
}
......@@ -1336,13 +1334,16 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
vk::CommandBuffer *commandBuffer,
CommandBufferHelper *commandBufferHelper)
{
if (mProgram->hasImages())
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
if (executable->hasImages(mState))
{
ANGLE_TRY(updateActiveImages(context, commandBufferHelper));
}
if (mProgram->hasUniformBuffers() || mProgram->hasStorageBuffers() ||
mProgram->hasAtomicCounterBuffers() || mProgram->hasImages())
if (executable->hasUniformBuffers(mState) || executable->hasStorageBuffers(mState) ||
executable->hasAtomicCounterBuffers(mState) || executable->hasImages(mState))
{
ANGLE_TRY(mProgram->updateShaderResourcesDescriptorSet(this, &mResourceUseList,
commandBufferHelper));
......@@ -1366,9 +1367,12 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
const gl::Context *context,
vk::CommandBuffer *commandBuffer)
{
if (mProgram->hasTransformFeedbackOutput() && mState.isTransformFeedbackActive())
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
if (executable->hasTransformFeedbackOutput(mState) && mState.isTransformFeedbackActive())
{
size_t bufferCount = mProgram->getState().getTransformFeedbackBufferCount();
size_t bufferCount = executable->getTransformFeedbackBufferCount(mState);
const std::vector<gl::OffsetBindingPointer<gl::Buffer>> &xfbBuffers =
mState.getCurrentTransformFeedback()->getIndexedBuffers();
......@@ -1393,13 +1397,16 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
const gl::Context *context,
vk::CommandBuffer *commandBuffer)
{
if (!mProgram->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActive())
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
if (!executable->hasTransformFeedbackOutput(mState) || !mState.isTransformFeedbackActive())
return angle::Result::Continue;
size_t bufferIndex = 0;
TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
size_t bufferCount = mProgram->getState().getTransformFeedbackBufferCount();
size_t bufferCount = executable->getTransformFeedbackBufferCount(mState);
gl::TransformFeedbackBuffersArray<VkBuffer> bufferHandles;
const std::vector<gl::OffsetBindingPointer<gl::Buffer>> &xfbBuffers =
......@@ -1432,13 +1439,17 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
{
if (!mProgram->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActiveUnpaused())
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
if (!executable->hasTransformFeedbackOutput(mState) ||
!mState.isTransformFeedbackActiveUnpaused())
return angle::Result::Continue;
TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
// We should have same number of counter buffers as xfb buffers have
size_t bufferCount = mProgram->getState().getTransformFeedbackBufferCount();
size_t bufferCount = executable->getTransformFeedbackBufferCount(mState);
const gl::TransformFeedbackBuffersArray<VkBuffer> &counterBufferHandles =
transformFeedbackVk->getCounterBufferHandles();
......@@ -3058,8 +3069,10 @@ OverlayImpl *ContextVk::createOverlay(const gl::OverlayState &state)
void ContextVk::invalidateCurrentDefaultUniforms()
{
ASSERT(mProgram);
if (mProgram->hasDefaultUniforms())
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
if (executable->hasDefaultUniforms(mState))
{
mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
......@@ -3068,8 +3081,10 @@ void ContextVk::invalidateCurrentDefaultUniforms()
angle::Result ContextVk::invalidateCurrentTextures(const gl::Context *context)
{
ASSERT(mProgram);
if (mProgram->hasTextures())
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
if (executable->hasTextures(mState))
{
mGraphicsDirtyBits.set(DIRTY_BIT_TEXTURES);
mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
......@@ -3084,9 +3099,11 @@ angle::Result ContextVk::invalidateCurrentTextures(const gl::Context *context)
void ContextVk::invalidateCurrentShaderResources()
{
ASSERT(mProgram);
if (mProgram->hasUniformBuffers() || mProgram->hasStorageBuffers() ||
mProgram->hasAtomicCounterBuffers() || mProgram->hasImages())
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
if (executable->hasUniformBuffers(mState) || executable->hasStorageBuffers(mState) ||
executable->hasAtomicCounterBuffers(mState) || executable->hasImages(mState))
{
mGraphicsDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
......@@ -3368,7 +3385,7 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co
{
TransformFeedbackVk *transformFeedbackVk =
vk::GetImpl(mState.getCurrentTransformFeedback());
transformFeedbackVk->getBufferOffsets(this, mState.getProgram()->getState(), mXfbBaseVertex,
transformFeedbackVk->getBufferOffsets(this, mXfbBaseVertex,
driverUniforms->xfbBufferOffsets.data(),
driverUniforms->xfbBufferOffsets.size());
}
......@@ -3512,19 +3529,17 @@ void ContextVk::handleError(VkResult errorCode,
angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
{
const gl::State &glState = mState;
const gl::ProgramExecutable *programExecutable = glState.getProgramExecutable();
const gl::Program *program = glState.getProgram();
ASSERT(programExecutable);
ASSERT(program);
const gl::State &glState = mState;
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
ASSERT(executable);
uint32_t prevMaxIndex = mActiveTexturesDesc.getMaxIndex();
memset(mActiveTextures.data(), 0, sizeof(mActiveTextures[0]) * prevMaxIndex);
mActiveTexturesDesc.reset();
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 textureUnit : activeTextures)
{
......@@ -3566,15 +3581,13 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
angle::Result ContextVk::updateActiveImages(const gl::Context *context,
CommandBufferHelper *commandBufferHelper)
{
const gl::State &glState = mState;
const gl::ProgramExecutable *programExecutable = glState.getProgramExecutable();
const gl::Program *program = glState.getProgram();
ASSERT(programExecutable);
ASSERT(program);
const gl::State &glState = mState;
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
ASSERT(executable);
mActiveImages.fill(nullptr);
const gl::ActiveTextureMask &activeImages = program->getActiveImagesMask();
const gl::ActiveTextureMask &activeImages = executable->getActiveImagesMask();
// Note: currently, the image layout is transitioned entirely even if only one level or layer is
// used. This is an issue if one subresource of the image is used as framebuffer attachment and
......@@ -3609,7 +3622,7 @@ angle::Result ContextVk::updateActiveImages(const gl::Context *context,
// layers. Therefore we can't verify it has no staged updates right here.
vk::ImageLayout imageLayout = vk::ImageLayout::AllGraphicsShadersWrite;
if (programExecutable->isCompute())
if (executable->isCompute())
{
imageLayout = vk::ImageLayout::ComputeShaderWrite;
}
......
......@@ -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