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