Commit e25b8006 by Jamie Madill Committed by Commit Bot

Move sampler sync out of syncProgramTextures.

We only need to call the syncState for samplers when they are dirty. Also includes changes to refactor out the sampler sync in GL. Adds observer bindings so sampler sync is handled correctly in resource sharing scenarios. Bug: angleproject:2763 Change-Id: I762f0738ee7572ae29ce6bd5384a30aa9588c848 Reviewed-on: https://chromium-review.googlesource.com/1227797Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent a977acc8
...@@ -306,7 +306,9 @@ enum SubjectIndexes : angle::SubjectIndex ...@@ -306,7 +306,9 @@ enum SubjectIndexes : angle::SubjectIndex
kUniformBuffer0SubjectIndex = kTextureMaxSubjectIndex, kUniformBuffer0SubjectIndex = kTextureMaxSubjectIndex,
kUniformBufferMaxSubjectIndex = kUniformBufferMaxSubjectIndex =
kUniformBuffer0SubjectIndex + gl::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS, kUniformBuffer0SubjectIndex + gl::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS,
kVertexArraySubjectIndex = kUniformBufferMaxSubjectIndex, kSampler0SubjectIndex = kUniformBufferMaxSubjectIndex,
kSamplerMaxSubjectIndex = kSampler0SubjectIndex + gl::IMPLEMENTATION_MAX_ACTIVE_TEXTURES,
kVertexArraySubjectIndex = kSamplerMaxSubjectIndex,
kReadFramebufferSubjectIndex, kReadFramebufferSubjectIndex,
kDrawFramebufferSubjectIndex kDrawFramebufferSubjectIndex
}; };
...@@ -376,6 +378,12 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -376,6 +378,12 @@ Context::Context(rx::EGLImplFactory *implFactory,
{ {
mUniformBufferObserverBindings.emplace_back(this, uboIndex); mUniformBufferObserverBindings.emplace_back(this, uboIndex);
} }
for (angle::SubjectIndex samplerIndex = kSampler0SubjectIndex;
samplerIndex < kSamplerMaxSubjectIndex; ++samplerIndex)
{
mSamplerObserverBindings.emplace_back(this, samplerIndex);
}
} }
void Context::initialize() void Context::initialize()
...@@ -480,10 +488,12 @@ void Context::initialize() ...@@ -480,10 +488,12 @@ void Context::initialize()
mDrawDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY); mDrawDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_TEXTURES); mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_TEXTURES);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM); mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS);
mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER); mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY); mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY);
mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_TEXTURES); mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_TEXTURES);
mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS);
mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_STATE); mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_STATE);
mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_BUFFER_BINDING); mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_BUFFER_BINDING);
...@@ -528,6 +538,7 @@ void Context::initialize() ...@@ -528,6 +538,7 @@ void Context::initialize()
mComputeDirtyBits.set(State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING); mComputeDirtyBits.set(State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_TEXTURES); mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_TEXTURES);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM); mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS);
mImplementation->setErrorSet(&mErrors); mImplementation->setErrorSet(&mErrors);
...@@ -1150,6 +1161,7 @@ void Context::bindSampler(GLuint textureUnit, GLuint samplerHandle) ...@@ -1150,6 +1161,7 @@ void Context::bindSampler(GLuint textureUnit, GLuint samplerHandle)
Sampler *sampler = Sampler *sampler =
mState.mSamplers->checkSamplerAllocation(mImplementation.get(), samplerHandle); mState.mSamplers->checkSamplerAllocation(mImplementation.get(), samplerHandle);
mGLState.setSamplerBinding(this, textureUnit, sampler); mGLState.setSamplerBinding(this, textureUnit, sampler);
mSamplerObserverBindings[textureUnit].bind(sampler);
} }
void Context::bindImageTexture(GLuint unit, void Context::bindImageTexture(GLuint unit,
...@@ -2835,16 +2847,14 @@ void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param) ...@@ -2835,16 +2847,14 @@ void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param)
{ {
Sampler *samplerObject = Sampler *samplerObject =
mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler); mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
SetSamplerParameteri(samplerObject, pname, param); SetSamplerParameteri(this, samplerObject, pname, param);
mGLState.setObjectDirty(GL_SAMPLER);
} }
void Context::samplerParameteriv(GLuint sampler, GLenum pname, const GLint *param) void Context::samplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
{ {
Sampler *samplerObject = Sampler *samplerObject =
mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler); mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
SetSamplerParameteriv(samplerObject, pname, param); SetSamplerParameteriv(this, samplerObject, pname, param);
mGLState.setObjectDirty(GL_SAMPLER);
} }
void Context::samplerParameterivRobust(GLuint sampler, void Context::samplerParameterivRobust(GLuint sampler,
...@@ -2875,16 +2885,14 @@ void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param) ...@@ -2875,16 +2885,14 @@ void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
{ {
Sampler *samplerObject = Sampler *samplerObject =
mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler); mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
SetSamplerParameterf(samplerObject, pname, param); SetSamplerParameterf(this, samplerObject, pname, param);
mGLState.setObjectDirty(GL_SAMPLER);
} }
void Context::samplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param) void Context::samplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
{ {
Sampler *samplerObject = Sampler *samplerObject =
mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler); mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
SetSamplerParameterfv(samplerObject, pname, param); SetSamplerParameterfv(this, samplerObject, pname, param);
mGLState.setObjectDirty(GL_SAMPLER);
} }
void Context::samplerParameterfvRobust(GLuint sampler, void Context::samplerParameterfvRobust(GLuint sampler,
...@@ -2900,7 +2908,6 @@ void Context::getSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params) ...@@ -2900,7 +2908,6 @@ void Context::getSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
const Sampler *samplerObject = const Sampler *samplerObject =
mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler); mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
QuerySamplerParameteriv(samplerObject, pname, params); QuerySamplerParameteriv(samplerObject, pname, params);
mGLState.setObjectDirty(GL_SAMPLER);
} }
void Context::getSamplerParameterivRobust(GLuint sampler, void Context::getSamplerParameterivRobust(GLuint sampler,
...@@ -2935,7 +2942,6 @@ void Context::getSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *param ...@@ -2935,7 +2942,6 @@ void Context::getSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *param
const Sampler *samplerObject = const Sampler *samplerObject =
mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler); mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
QuerySamplerParameterfv(samplerObject, pname, params); QuerySamplerParameterfv(samplerObject, pname, params);
mGLState.setObjectDirty(GL_SAMPLER);
} }
void Context::getSamplerParameterfvRobust(GLuint sampler, void Context::getSamplerParameterfvRobust(GLuint sampler,
...@@ -7752,12 +7758,16 @@ void Context::onSubjectStateChange(const Context *context, ...@@ -7752,12 +7758,16 @@ void Context::onSubjectStateChange(const Context *context,
mGLState.onActiveTextureStateChange(index); mGLState.onActiveTextureStateChange(index);
mStateCache.onActiveTextureChange(this); mStateCache.onActiveTextureChange(this);
} }
else else if (index < kUniformBufferMaxSubjectIndex)
{ {
ASSERT(index < kUniformBufferMaxSubjectIndex);
mGLState.onUniformBufferStateChange(index - kUniformBuffer0SubjectIndex); mGLState.onUniformBufferStateChange(index - kUniformBuffer0SubjectIndex);
mStateCache.onUniformBufferStateChange(this); mStateCache.onUniformBufferStateChange(this);
} }
else
{
ASSERT(index < kSamplerMaxSubjectIndex);
mGLState.setSamplerDirty(index - kSampler0SubjectIndex);
}
break; break;
} }
} }
......
...@@ -1766,6 +1766,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl ...@@ -1766,6 +1766,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
angle::ObserverBinding mDrawFramebufferObserverBinding; angle::ObserverBinding mDrawFramebufferObserverBinding;
angle::ObserverBinding mReadFramebufferObserverBinding; angle::ObserverBinding mReadFramebufferObserverBinding;
std::vector<angle::ObserverBinding> mUniformBufferObserverBindings; std::vector<angle::ObserverBinding> mUniformBufferObserverBindings;
std::vector<angle::ObserverBinding> mSamplerObserverBindings;
// Not really a property of context state. The size and contexts change per-api-call. // Not really a property of context state. The size and contexts change per-api-call.
mutable angle::ScratchBuffer mScratchBuffer; mutable angle::ScratchBuffer mScratchBuffer;
......
...@@ -10,9 +10,10 @@ ...@@ -10,9 +10,10 @@
#ifndef LIBANGLE_SAMPLER_H_ #ifndef LIBANGLE_SAMPLER_H_
#define LIBANGLE_SAMPLER_H_ #define LIBANGLE_SAMPLER_H_
#include "libANGLE/angletypes.h"
#include "libANGLE/Debug.h" #include "libANGLE/Debug.h"
#include "libANGLE/Observer.h"
#include "libANGLE/RefCountObject.h" #include "libANGLE/RefCountObject.h"
#include "libANGLE/angletypes.h"
namespace rx namespace rx
{ {
...@@ -23,7 +24,7 @@ class SamplerImpl; ...@@ -23,7 +24,7 @@ class SamplerImpl;
namespace gl namespace gl
{ {
class Sampler final : public RefCountObject, public LabeledObject class Sampler final : public RefCountObject, public LabeledObject, public angle::Subject
{ {
public: public:
Sampler(rx::GLImplFactory *factory, GLuint id); Sampler(rx::GLImplFactory *factory, GLuint id);
......
...@@ -1112,6 +1112,8 @@ void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sample ...@@ -1112,6 +1112,8 @@ void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sample
mSamplers[textureUnit].set(context, sampler); mSamplers[textureUnit].set(context, sampler);
mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS); mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS);
mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES); mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
// This is overly conservative as it assumes the sampler has never been bound.
setSamplerDirty(textureUnit);
} }
GLuint State::getSamplerId(GLuint textureUnit) const GLuint State::getSamplerId(GLuint textureUnit) const
...@@ -2679,6 +2681,9 @@ Error State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset ...@@ -2679,6 +2681,9 @@ Error State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset
ASSERT(mVertexArray); ASSERT(mVertexArray);
ANGLE_TRY(mVertexArray->syncState(context)); ANGLE_TRY(mVertexArray->syncState(context));
break; break;
case DIRTY_OBJECT_SAMPLERS:
syncSamplers(context);
break;
case DIRTY_OBJECT_PROGRAM_TEXTURES: case DIRTY_OBJECT_PROGRAM_TEXTURES:
ANGLE_TRY(syncProgramTextures(context)); ANGLE_TRY(syncProgramTextures(context));
break; break;
...@@ -2696,6 +2701,24 @@ Error State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset ...@@ -2696,6 +2701,24 @@ Error State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset
return NoError(); return NoError();
} }
void State::syncSamplers(const Context *context)
{
if (mDirtySamplers.none())
return;
// This could be optimized by tracking which samplers are dirty.
for (size_t samplerIndex : mDirtySamplers)
{
BindingPointer<Sampler> &sampler = mSamplers[samplerIndex];
if (sampler.get())
{
sampler->syncState(context);
}
}
mDirtySamplers.reset();
}
Error State::syncProgramTextures(const Context *context) Error State::syncProgramTextures(const Context *context)
{ {
// TODO(jmadill): Fine-grained updates. // TODO(jmadill): Fine-grained updates.
...@@ -2732,7 +2755,8 @@ Error State::syncProgramTextures(const Context *context) ...@@ -2732,7 +2755,8 @@ Error State::syncProgramTextures(const Context *context)
// Mark the texture binding bit as dirty if the texture completeness changes. // Mark the texture binding bit as dirty if the texture completeness changes.
// TODO(jmadill): Use specific dirty bit for completeness change. // TODO(jmadill): Use specific dirty bit for completeness change.
if (texture->isSamplerComplete(context, sampler) && if (texture->isSamplerComplete(context, sampler) &&
!mDrawFramebuffer->hasTextureAttachment(texture)) (mProgram->hasLinkedShaderStage(ShaderType::Compute) ||
!mDrawFramebuffer->hasTextureAttachment(texture)))
{ {
ANGLE_TRY(texture->syncState(context)); ANGLE_TRY(texture->syncState(context));
mActiveTexturesCache[textureUnitIndex] = texture; mActiveTexturesCache[textureUnitIndex] = texture;
...@@ -2746,11 +2770,6 @@ Error State::syncProgramTextures(const Context *context) ...@@ -2746,11 +2770,6 @@ Error State::syncProgramTextures(const Context *context)
mCompleteTextureBindings[textureUnitIndex].bind(texture->getSubject()); mCompleteTextureBindings[textureUnitIndex].bind(texture->getSubject());
newActiveTextures.set(textureUnitIndex); newActiveTextures.set(textureUnitIndex);
if (sampler != nullptr)
{
sampler->syncState(context);
}
if (texture->initState() == InitState::MayNeedInit) if (texture->initState() == InitState::MayNeedInit)
{ {
mCachedTexturesInitState = InitState::MayNeedInit; mCachedTexturesInitState = InitState::MayNeedInit;
...@@ -2808,8 +2827,11 @@ Error State::syncDirtyObject(const Context *context, GLenum target) ...@@ -2808,8 +2827,11 @@ Error State::syncDirtyObject(const Context *context, GLenum target)
localSet.set(DIRTY_OBJECT_VERTEX_ARRAY); localSet.set(DIRTY_OBJECT_VERTEX_ARRAY);
break; break;
case GL_TEXTURE: case GL_TEXTURE:
localSet.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
break;
case GL_SAMPLER: case GL_SAMPLER:
localSet.set(DIRTY_OBJECT_PROGRAM_TEXTURES); localSet.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
localSet.set(DIRTY_OBJECT_SAMPLERS);
break; break;
case GL_PROGRAM: case GL_PROGRAM:
localSet.set(DIRTY_OBJECT_PROGRAM_TEXTURES); localSet.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
...@@ -2838,7 +2860,6 @@ void State::setObjectDirty(GLenum target) ...@@ -2838,7 +2860,6 @@ void State::setObjectDirty(GLenum target)
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
break; break;
case GL_TEXTURE: case GL_TEXTURE:
case GL_SAMPLER:
mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES); mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS); mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
break; break;
...@@ -2864,6 +2885,12 @@ void State::onProgramExecutableChange(Program *program) ...@@ -2864,6 +2885,12 @@ void State::onProgramExecutableChange(Program *program)
} }
} }
void State::setSamplerDirty(size_t samplerIndex)
{
mDirtyObjects.set(DIRTY_OBJECT_SAMPLERS);
mDirtySamplers.set(samplerIndex);
}
void State::setImageUnit(const Context *context, void State::setImageUnit(const Context *context,
size_t unit, size_t unit,
Texture *texture, Texture *texture,
......
...@@ -193,6 +193,9 @@ class State : angle::NonCopyable ...@@ -193,6 +193,9 @@ class State : angle::NonCopyable
Sampler *getSampler(GLuint textureUnit) const { return mSamplers[textureUnit].get(); } Sampler *getSampler(GLuint textureUnit) const { return mSamplers[textureUnit].get(); }
using SamplerBindingVector = std::vector<BindingPointer<Sampler>>;
const SamplerBindingVector &getSamplers() const { return mSamplers; }
void detachSampler(const Context *context, GLuint sampler); void detachSampler(const Context *context, GLuint sampler);
// Renderbuffer binding manipulation // Renderbuffer binding manipulation
...@@ -441,6 +444,7 @@ class State : angle::NonCopyable ...@@ -441,6 +444,7 @@ class State : angle::NonCopyable
DIRTY_OBJECT_READ_FRAMEBUFFER, DIRTY_OBJECT_READ_FRAMEBUFFER,
DIRTY_OBJECT_DRAW_FRAMEBUFFER, DIRTY_OBJECT_DRAW_FRAMEBUFFER,
DIRTY_OBJECT_VERTEX_ARRAY, DIRTY_OBJECT_VERTEX_ARRAY,
DIRTY_OBJECT_SAMPLERS,
// Use a very coarse bit for any program or texture change. // Use a very coarse bit for any program or texture change.
// TODO(jmadill): Fine-grained dirty bits for each texture/sampler. // TODO(jmadill): Fine-grained dirty bits for each texture/sampler.
DIRTY_OBJECT_PROGRAM_TEXTURES, DIRTY_OBJECT_PROGRAM_TEXTURES,
...@@ -461,6 +465,7 @@ class State : angle::NonCopyable ...@@ -461,6 +465,7 @@ class State : angle::NonCopyable
Error syncDirtyObjects(const Context *context, const DirtyObjects &bitset); Error syncDirtyObjects(const Context *context, const DirtyObjects &bitset);
Error syncDirtyObject(const Context *context, GLenum target); Error syncDirtyObject(const Context *context, GLenum target);
void setObjectDirty(GLenum target); void setObjectDirty(GLenum target);
void setSamplerDirty(size_t samplerIndex);
// This actually clears the current value dirty bits. // This actually clears the current value dirty bits.
// TODO(jmadill): Pass mutable dirty bits into Impl. // TODO(jmadill): Pass mutable dirty bits into Impl.
...@@ -492,6 +497,7 @@ class State : angle::NonCopyable ...@@ -492,6 +497,7 @@ class State : angle::NonCopyable
const GLES1State &gles1() const { return mGLES1State; } const GLES1State &gles1() const { return mGLES1State; }
private: private:
void syncSamplers(const Context *context);
Error syncProgramTextures(const Context *context); Error syncProgramTextures(const Context *context);
// Cached values from Context's caps // Cached values from Context's caps
...@@ -569,7 +575,6 @@ class State : angle::NonCopyable ...@@ -569,7 +575,6 @@ class State : angle::NonCopyable
InitState mCachedImageTexturesInitState; InitState mCachedImageTexturesInitState;
using SamplerBindingVector = std::vector<BindingPointer<Sampler>>;
SamplerBindingVector mSamplers; SamplerBindingVector mSamplers;
using ImageUnitVector = std::vector<ImageUnit>; using ImageUnitVector = std::vector<ImageUnit>;
...@@ -628,6 +633,7 @@ class State : angle::NonCopyable ...@@ -628,6 +633,7 @@ class State : angle::NonCopyable
DirtyBits mDirtyBits; DirtyBits mDirtyBits;
DirtyObjects mDirtyObjects; DirtyObjects mDirtyObjects;
mutable AttributesMask mDirtyCurrentValues; mutable AttributesMask mDirtyCurrentValues;
ActiveTextureMask mDirtySamplers;
}; };
} // namespace gl } // namespace gl
......
...@@ -333,7 +333,10 @@ void QuerySamplerParameterBase(const Sampler *sampler, GLenum pname, ParamType * ...@@ -333,7 +333,10 @@ void QuerySamplerParameterBase(const Sampler *sampler, GLenum pname, ParamType *
} }
template <typename ParamType> template <typename ParamType>
void SetSamplerParameterBase(Sampler *sampler, GLenum pname, const ParamType *params) void SetSamplerParameterBase(Context *context,
Sampler *sampler,
GLenum pname,
const ParamType *params)
{ {
switch (pname) switch (pname)
{ {
...@@ -374,6 +377,8 @@ void SetSamplerParameterBase(Sampler *sampler, GLenum pname, const ParamType *pa ...@@ -374,6 +377,8 @@ void SetSamplerParameterBase(Sampler *sampler, GLenum pname, const ParamType *pa
UNREACHABLE(); UNREACHABLE();
break; break;
} }
sampler->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
} }
// Warning: you should ensure binding really matches attrib.bindingIndex before using this function. // Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
...@@ -1404,24 +1409,24 @@ void SetTexParameteriv(Context *context, Texture *texture, GLenum pname, const G ...@@ -1404,24 +1409,24 @@ void SetTexParameteriv(Context *context, Texture *texture, GLenum pname, const G
SetTexParameterBase(context, texture, pname, params); SetTexParameterBase(context, texture, pname, params);
} }
void SetSamplerParameterf(Sampler *sampler, GLenum pname, GLfloat param) void SetSamplerParameterf(Context *context, Sampler *sampler, GLenum pname, GLfloat param)
{ {
SetSamplerParameterBase(sampler, pname, &param); SetSamplerParameterBase(context, sampler, pname, &param);
} }
void SetSamplerParameterfv(Sampler *sampler, GLenum pname, const GLfloat *params) void SetSamplerParameterfv(Context *context, Sampler *sampler, GLenum pname, const GLfloat *params)
{ {
SetSamplerParameterBase(sampler, pname, params); SetSamplerParameterBase(context, sampler, pname, params);
} }
void SetSamplerParameteri(Sampler *sampler, GLenum pname, GLint param) void SetSamplerParameteri(Context *context, Sampler *sampler, GLenum pname, GLint param)
{ {
SetSamplerParameterBase(sampler, pname, &param); SetSamplerParameterBase(context, sampler, pname, &param);
} }
void SetSamplerParameteriv(Sampler *sampler, GLenum pname, const GLint *params) void SetSamplerParameteriv(Context *context, Sampler *sampler, GLenum pname, const GLint *params)
{ {
SetSamplerParameterBase(sampler, pname, params); SetSamplerParameterBase(context, sampler, pname, params);
} }
void SetFramebufferParameteri(const Context *context, void SetFramebufferParameteri(const Context *context,
......
...@@ -112,10 +112,10 @@ void SetTexParameterfv(Context *context, Texture *texture, GLenum pname, const G ...@@ -112,10 +112,10 @@ void SetTexParameterfv(Context *context, Texture *texture, GLenum pname, const G
void SetTexParameteri(Context *context, Texture *texture, GLenum pname, GLint param); void SetTexParameteri(Context *context, Texture *texture, GLenum pname, GLint param);
void SetTexParameteriv(Context *context, Texture *texture, GLenum pname, const GLint *params); void SetTexParameteriv(Context *context, Texture *texture, GLenum pname, const GLint *params);
void SetSamplerParameterf(Sampler *sampler, GLenum pname, GLfloat param); void SetSamplerParameterf(Context *context, Sampler *sampler, GLenum pname, GLfloat param);
void SetSamplerParameterfv(Sampler *sampler, GLenum pname, const GLfloat *params); void SetSamplerParameterfv(Context *context, Sampler *sampler, GLenum pname, const GLfloat *params);
void SetSamplerParameteri(Sampler *sampler, GLenum pname, GLint param); void SetSamplerParameteri(Context *context, Sampler *sampler, GLenum pname, GLint param);
void SetSamplerParameteriv(Sampler *sampler, GLenum pname, const GLint *params); void SetSamplerParameteriv(Context *context, Sampler *sampler, GLenum pname, const GLint *params);
void SetFramebufferParameteri(const Context *context, void SetFramebufferParameteri(const Context *context,
Framebuffer *framebuffer, Framebuffer *framebuffer,
......
...@@ -163,7 +163,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, ...@@ -163,7 +163,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mIsMultiviewEnabled(extensions.multiview), mIsMultiviewEnabled(extensions.multiview),
mLocalDirtyBits(), mLocalDirtyBits(),
mMultiviewDirtyBits(), mMultiviewDirtyBits(),
mProgramTexturesAndSamplersDirty(true), mProgramTexturesDirty(true),
mProgramStorageBuffersDirty(true), mProgramStorageBuffersDirty(true),
mProgramUniformBuffersDirty(true), mProgramUniformBuffersDirty(true),
mProgramAtomicCounterBuffersDirty(true), mProgramAtomicCounterBuffersDirty(true),
...@@ -874,10 +874,10 @@ void StateManagerGL::setGenericShaderState(const gl::Context *context) ...@@ -874,10 +874,10 @@ void StateManagerGL::setGenericShaderState(const gl::Context *context)
mProgramUniformBuffersDirty = false; mProgramUniformBuffersDirty = false;
} }
if (mProgramTexturesAndSamplersDirty) if (mProgramTexturesDirty)
{ {
updateProgramTextureAndSamplerBindings(context); updateProgramTextureBindings(context);
mProgramTexturesAndSamplersDirty = false; mProgramTexturesDirty = false;
} }
if (mProgramStorageBuffersDirty) if (mProgramStorageBuffersDirty)
...@@ -899,7 +899,7 @@ void StateManagerGL::setGenericShaderState(const gl::Context *context) ...@@ -899,7 +899,7 @@ void StateManagerGL::setGenericShaderState(const gl::Context *context)
} }
} }
void StateManagerGL::updateProgramTextureAndSamplerBindings(const gl::Context *context) void StateManagerGL::updateProgramTextureBindings(const gl::Context *context)
{ {
const gl::State &glState = context->getGLState(); const gl::State &glState = context->getGLState();
const gl::Program *program = glState.getProgram(); const gl::Program *program = glState.getProgram();
...@@ -920,30 +920,13 @@ void StateManagerGL::updateProgramTextureAndSamplerBindings(const gl::Context *c ...@@ -920,30 +920,13 @@ void StateManagerGL::updateProgramTextureAndSamplerBindings(const gl::Context *c
ASSERT(!texture->hasAnyDirtyBit()); ASSERT(!texture->hasAnyDirtyBit());
ASSERT(!textureGL->hasAnyDirtyBit()); ASSERT(!textureGL->hasAnyDirtyBit());
if (mTextures[textureType][textureUnitIndex] != textureGL->getTextureID()) activeTexture(textureUnitIndex);
{ bindTexture(textureType, textureGL->getTextureID());
activeTexture(textureUnitIndex);
bindTexture(textureType, textureGL->getTextureID());
}
} }
else else
{ {
if (mTextures[textureType][textureUnitIndex] != 0) activeTexture(textureUnitIndex);
{ bindTexture(textureType, 0);
activeTexture(textureUnitIndex);
bindTexture(textureType, 0);
}
}
const gl::Sampler *sampler = glState.getSampler(static_cast<GLuint>(textureUnitIndex));
if (sampler != nullptr)
{
SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
bindSampler(textureUnitIndex, samplerGL->getSamplerID());
}
else
{
bindSampler(textureUnitIndex, 0);
} }
} }
} }
...@@ -1996,10 +1979,10 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -1996,10 +1979,10 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt
break; break;
} }
case gl::State::DIRTY_BIT_TEXTURE_BINDINGS: case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
mProgramTexturesAndSamplersDirty = true; mProgramTexturesDirty = true;
break; break;
case gl::State::DIRTY_BIT_SAMPLER_BINDINGS: case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
mProgramTexturesAndSamplersDirty = true; syncSamplersState(context);
break; break;
case gl::State::DIRTY_BIT_IMAGE_BINDINGS: case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
mProgramImagesDirty = true; mProgramImagesDirty = true;
...@@ -2008,7 +1991,7 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -2008,7 +1991,7 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt
syncTransformFeedbackState(context); syncTransformFeedbackState(context);
break; break;
case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE: case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
mProgramTexturesAndSamplersDirty = true; mProgramTexturesDirty = true;
mProgramImagesDirty = true; mProgramImagesDirty = true;
mProgramStorageBuffersDirty = true; mProgramStorageBuffersDirty = true;
mProgramUniformBuffersDirty = true; mProgramUniformBuffersDirty = true;
...@@ -2318,6 +2301,26 @@ void StateManagerGL::updateMultiviewBaseViewLayerIndexUniform( ...@@ -2318,6 +2301,26 @@ void StateManagerGL::updateMultiviewBaseViewLayerIndexUniform(
} }
} }
void StateManagerGL::syncSamplersState(const gl::Context *context)
{
const gl::State::SamplerBindingVector &samplers = context->getGLState().getSamplers();
// This could be optimized by using a separate binding dirty bit per sampler.
for (size_t samplerIndex = 0; samplerIndex < samplers.size(); ++samplerIndex)
{
const gl::Sampler *sampler = samplers[samplerIndex].get();
if (sampler != nullptr)
{
SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
bindSampler(samplerIndex, samplerGL->getSamplerID());
}
else
{
bindSampler(samplerIndex, 0);
}
}
}
void StateManagerGL::syncTransformFeedbackState(const gl::Context *context) void StateManagerGL::syncTransformFeedbackState(const gl::Context *context)
{ {
// Set the current transform feedback state // Set the current transform feedback state
......
...@@ -195,7 +195,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -195,7 +195,7 @@ class StateManagerGL final : angle::NonCopyable
const gl::Framebuffer &drawFramebuffer); const gl::Framebuffer &drawFramebuffer);
void propagateProgramToVAO(const gl::Program *program, VertexArrayGL *vao); void propagateProgramToVAO(const gl::Program *program, VertexArrayGL *vao);
void updateProgramTextureAndSamplerBindings(const gl::Context *context); void updateProgramTextureBindings(const gl::Context *context);
void updateProgramStorageBufferBindings(const gl::Context *context); void updateProgramStorageBufferBindings(const gl::Context *context);
void updateProgramUniformBufferBindings(const gl::Context *context); void updateProgramUniformBufferBindings(const gl::Context *context);
void updateProgramAtomicCounterBufferBindings(const gl::Context *context); void updateProgramAtomicCounterBufferBindings(const gl::Context *context);
...@@ -204,6 +204,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -204,6 +204,7 @@ class StateManagerGL final : angle::NonCopyable
void updateDispatchIndirectBufferBinding(const gl::Context *context); void updateDispatchIndirectBufferBinding(const gl::Context *context);
void updateDrawIndirectBufferBinding(const gl::Context *context); void updateDrawIndirectBufferBinding(const gl::Context *context);
void syncSamplersState(const gl::Context *context);
void syncTransformFeedbackState(const gl::Context *context); void syncTransformFeedbackState(const gl::Context *context);
enum MultiviewDirtyBitType enum MultiviewDirtyBitType
...@@ -364,7 +365,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -364,7 +365,7 @@ class StateManagerGL final : angle::NonCopyable
// ANGLE_multiview dirty bits. // ANGLE_multiview dirty bits.
angle::BitSet<MULTIVIEW_DIRTY_BIT_MAX> mMultiviewDirtyBits; angle::BitSet<MULTIVIEW_DIRTY_BIT_MAX> mMultiviewDirtyBits;
bool mProgramTexturesAndSamplersDirty; bool mProgramTexturesDirty;
bool mProgramStorageBuffersDirty; bool mProgramStorageBuffersDirty;
bool mProgramUniformBuffersDirty; bool mProgramUniformBuffersDirty;
bool mProgramAtomicCounterBuffersDirty; bool mProgramAtomicCounterBuffersDirty;
......
...@@ -1077,10 +1077,12 @@ TEST_P(LineLoopStateChangeTest, DrawArraysThenDrawElements) ...@@ -1077,10 +1077,12 @@ TEST_P(LineLoopStateChangeTest, DrawArraysThenDrawElements)
class SimpleStateChangeTest : public ANGLETest class SimpleStateChangeTest : public ANGLETest
{ {
protected: protected:
static constexpr int kWindowSize = 64;
SimpleStateChangeTest() SimpleStateChangeTest()
{ {
setWindowWidth(64); setWindowWidth(kWindowSize);
setWindowHeight(64); setWindowHeight(kWindowSize);
setConfigRedBits(8); setConfigRedBits(8);
setConfigGreenBits(8); setConfigGreenBits(8);
setConfigBlueBits(8); setConfigBlueBits(8);
...@@ -1091,6 +1093,10 @@ class SimpleStateChangeTest : public ANGLETest ...@@ -1091,6 +1093,10 @@ class SimpleStateChangeTest : public ANGLETest
void simpleDrawWithColor(const GLColor &color); void simpleDrawWithColor(const GLColor &color);
}; };
class SimpleStateChangeTestES3 : public SimpleStateChangeTest
{
};
constexpr char kSimpleVertexShader[] = R"(attribute vec2 position; constexpr char kSimpleVertexShader[] = R"(attribute vec2 position;
attribute vec4 color; attribute vec4 color;
varying vec4 vColor; varying vec4 vColor;
...@@ -2050,6 +2056,70 @@ TEST_P(SimpleStateChangeTest, ReleaseShaderInUseThatReadsFromUniforms) ...@@ -2050,6 +2056,70 @@ TEST_P(SimpleStateChangeTest, ReleaseShaderInUseThatReadsFromUniforms)
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red); EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red);
} }
// Tests that sampler sync isn't masked by program textures.
TEST_P(SimpleStateChangeTestES3, SamplerSyncNotTiedToProgram)
{
// Create a sampler with NEAREST filtering.
GLSampler sampler;
glBindSampler(0, sampler);
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
// Draw with a program that uses no textures.
ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
// Create a simple texture with four colors and linear filtering.
constexpr GLsizei kSize = 2;
std::array<GLColor, 4> pixels = {
{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
GLTexture redTex;
glBindTexture(GL_TEXTURE_2D, redTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
pixels.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Create a program that uses the texture.
constexpr char kVS[] = R"(attribute vec4 position;
varying vec2 texCoord;
void main()
{
gl_Position = position;
texCoord = position.xy * 0.5 + vec2(0.5);
})";
constexpr char kFS[] = R"(precision mediump float;
varying vec2 texCoord;
uniform sampler2D tex;
void main()
{
gl_FragColor = texture2D(tex, texCoord);
})";
// Draw. The sampler should override the clamp wrap mode with nearest.
ANGLE_GL_PROGRAM(program2, kVS, kFS);
ASSERT_EQ(0, glGetUniformLocation(program2, "tex"));
drawQuad(program2, "position", 0.5f);
ASSERT_GL_NO_ERROR();
constexpr int kHalfSize = kWindowSize / 2;
EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
}
static constexpr char kColorVS[] = R"(attribute vec2 position; static constexpr char kColorVS[] = R"(attribute vec2 position;
attribute vec4 color; attribute vec4 color;
varying vec4 vColor; varying vec4 vColor;
...@@ -2798,6 +2868,7 @@ ANGLE_INSTANTIATE_TEST(StateChangeRenderTest, ...@@ -2798,6 +2868,7 @@ ANGLE_INSTANTIATE_TEST(StateChangeRenderTest,
ES2_VULKAN()); ES2_VULKAN());
ANGLE_INSTANTIATE_TEST(StateChangeTestES3, ES3_D3D11(), ES3_OPENGL()); ANGLE_INSTANTIATE_TEST(StateChangeTestES3, ES3_D3D11(), ES3_OPENGL());
ANGLE_INSTANTIATE_TEST(SimpleStateChangeTest, ES2_VULKAN(), ES2_OPENGL()); ANGLE_INSTANTIATE_TEST(SimpleStateChangeTest, ES2_VULKAN(), ES2_OPENGL());
ANGLE_INSTANTIATE_TEST(SimpleStateChangeTestES3, ES3_OPENGL(), ES3_D3D11());
ANGLE_INSTANTIATE_TEST(ValidationStateChangeTest, ES3_D3D11(), ES3_OPENGL()); ANGLE_INSTANTIATE_TEST(ValidationStateChangeTest, ES3_D3D11(), ES3_OPENGL());
ANGLE_INSTANTIATE_TEST(WebGL2ValidationStateChangeTest, ES3_D3D11(), ES3_OPENGL()); ANGLE_INSTANTIATE_TEST(WebGL2ValidationStateChangeTest, ES3_D3D11(), ES3_OPENGL());
ANGLE_INSTANTIATE_TEST(ValidationStateChangeTestES31, ES31_OPENGL()); ANGLE_INSTANTIATE_TEST(ValidationStateChangeTestES31, ES31_OPENGL());
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