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