Commit 2274b652 by Jamie Madill Committed by Commit Bot

StateManager11: Cache impl objects.

Also requires putting the Framebuffer ID in the shared state object. Bug: angleproject:2575 Change-Id: I68e3af839a85798e01050560a67624a165d3ed2c Reviewed-on: https://chromium-review.googlesource.com/1067119 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 683d65f8
...@@ -252,7 +252,8 @@ bool IsClearBufferMaskedOut(const Context *context, GLenum buffer) ...@@ -252,7 +252,8 @@ bool IsClearBufferMaskedOut(const Context *context, GLenum buffer)
// This constructor is only used for default framebuffers. // This constructor is only used for default framebuffers.
FramebufferState::FramebufferState() FramebufferState::FramebufferState()
: mLabel(), : mId(0),
mLabel(),
mColorAttachments(1), mColorAttachments(1),
mDrawBufferStates(1, GL_BACK), mDrawBufferStates(1, GL_BACK),
mReadBufferState(GL_BACK), mReadBufferState(GL_BACK),
...@@ -268,8 +269,9 @@ FramebufferState::FramebufferState() ...@@ -268,8 +269,9 @@ FramebufferState::FramebufferState()
mEnabledDrawBuffers.set(0); mEnabledDrawBuffers.set(0);
} }
FramebufferState::FramebufferState(const Caps &caps) FramebufferState::FramebufferState(const Caps &caps, GLuint id)
: mLabel(), : mId(id),
mLabel(),
mColorAttachments(caps.maxColorAttachments), mColorAttachments(caps.maxColorAttachments),
mDrawBufferStates(caps.maxDrawBuffers, GL_NONE), mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
mReadBufferState(GL_COLOR_ATTACHMENT0_EXT), mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
...@@ -281,6 +283,7 @@ FramebufferState::FramebufferState(const Caps &caps) ...@@ -281,6 +283,7 @@ FramebufferState::FramebufferState(const Caps &caps)
mDefaultLayers(0), mDefaultLayers(0),
mWebGLDepthStencilConsistent(true) mWebGLDepthStencilConsistent(true)
{ {
ASSERT(mId != 0);
ASSERT(mDrawBufferStates.size() > 0); ASSERT(mDrawBufferStates.size() > 0);
mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
} }
...@@ -613,14 +616,12 @@ Box FramebufferState::getDimensions() const ...@@ -613,14 +616,12 @@ Box FramebufferState::getDimensions() const
} }
Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id) Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
: mState(caps), : mState(caps, id),
mImpl(factory->createFramebuffer(mState)), mImpl(factory->createFramebuffer(mState)),
mId(id),
mCachedStatus(), mCachedStatus(),
mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT), mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT) mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
{ {
ASSERT(mId != 0);
ASSERT(mImpl != nullptr); ASSERT(mImpl != nullptr);
ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments)); ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
...@@ -634,7 +635,6 @@ Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id ...@@ -634,7 +635,6 @@ Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id
Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface) Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
: mState(), : mState(),
mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)), mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
mId(0),
mCachedStatus(GL_FRAMEBUFFER_COMPLETE), mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT), mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT) mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
...@@ -673,7 +673,6 @@ Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface) ...@@ -673,7 +673,6 @@ Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
Framebuffer::Framebuffer(rx::GLImplFactory *factory) Framebuffer::Framebuffer(rx::GLImplFactory *factory)
: mState(), : mState(),
mImpl(factory->createFramebuffer(mState)), mImpl(factory->createFramebuffer(mState)),
mId(0),
mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES), mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT), mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT) mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
...@@ -972,7 +971,7 @@ bool Framebuffer::usingExtendedDrawBuffers() const ...@@ -972,7 +971,7 @@ bool Framebuffer::usingExtendedDrawBuffers() const
void Framebuffer::invalidateCompletenessCache() void Framebuffer::invalidateCompletenessCache()
{ {
if (mId != 0) if (mState.mId != 0)
{ {
mCachedStatus.reset(); mCachedStatus.reset();
} }
...@@ -983,7 +982,7 @@ GLenum Framebuffer::checkStatus(const Context *context) ...@@ -983,7 +982,7 @@ GLenum Framebuffer::checkStatus(const Context *context)
// The default framebuffer is always complete except when it is surfaceless in which // The default framebuffer is always complete except when it is surfaceless in which
// case it is always unsupported. We return early because the default framebuffer may // case it is always unsupported. We return early because the default framebuffer may
// not be subject to the same rules as application FBOs. ie, it could have 0x0 size. // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
if (mId == 0) if (mState.mId == 0)
{ {
ASSERT(mCachedStatus.valid()); ASSERT(mCachedStatus.valid());
ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE || ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
...@@ -1017,7 +1016,7 @@ GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context) ...@@ -1017,7 +1016,7 @@ GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context)
{ {
const ContextState &state = context->getContextState(); const ContextState &state = context->getContextState();
ASSERT(mId != 0); ASSERT(mState.mId != 0);
bool hasAttachments = false; bool hasAttachments = false;
Optional<unsigned int> colorbufferSize; Optional<unsigned int> colorbufferSize;
...@@ -1762,7 +1761,7 @@ void Framebuffer::onSubjectStateChange(const Context *context, ...@@ -1762,7 +1761,7 @@ void Framebuffer::onSubjectStateChange(const Context *context,
// Only reset the cached status if this is not the default framebuffer. The default framebuffer // Only reset the cached status if this is not the default framebuffer. The default framebuffer
// will still use this channel to mark itself dirty. // will still use this channel to mark itself dirty.
if (mId != 0) if (mState.mId != 0)
{ {
// TOOD(jmadill): Make this only update individual attachments to do less work. // TOOD(jmadill): Make this only update individual attachments to do less work.
mCachedStatus.reset(); mCachedStatus.reset();
...@@ -1799,7 +1798,7 @@ bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const ...@@ -1799,7 +1798,7 @@ bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
const Program *program = state.getProgram(); const Program *program = state.getProgram();
// TODO(jmadill): Default framebuffer feedback loops. // TODO(jmadill): Default framebuffer feedback loops.
if (mId == 0) if (mState.mId == 0)
{ {
return false; return false;
} }
...@@ -1861,7 +1860,7 @@ bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID, ...@@ -1861,7 +1860,7 @@ bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
GLint copyTextureLevel, GLint copyTextureLevel,
GLint copyTextureLayer) const GLint copyTextureLayer) const
{ {
if (mId == 0) if (mState.mId == 0)
{ {
// It seems impossible to form a texture copying feedback loop with the default FBO. // It seems impossible to form a texture copying feedback loop with the default FBO.
return false; return false;
......
...@@ -53,7 +53,7 @@ class FramebufferState final : angle::NonCopyable ...@@ -53,7 +53,7 @@ class FramebufferState final : angle::NonCopyable
{ {
public: public:
FramebufferState(); FramebufferState();
explicit FramebufferState(const Caps &caps); explicit FramebufferState(const Caps &caps, GLuint id);
~FramebufferState(); ~FramebufferState();
const std::string &getLabel(); const std::string &getLabel();
...@@ -99,6 +99,8 @@ class FramebufferState final : angle::NonCopyable ...@@ -99,6 +99,8 @@ class FramebufferState final : angle::NonCopyable
const std::vector<Offset> *getViewportOffsets() const; const std::vector<Offset> *getViewportOffsets() const;
GLint getBaseViewIndex() const; GLint getBaseViewIndex() const;
GLuint id() const { return mId; }
private: private:
const FramebufferAttachment *getWebGLDepthStencilAttachment() const; const FramebufferAttachment *getWebGLDepthStencilAttachment() const;
const FramebufferAttachment *getWebGLDepthAttachment() const; const FramebufferAttachment *getWebGLDepthAttachment() const;
...@@ -106,6 +108,7 @@ class FramebufferState final : angle::NonCopyable ...@@ -106,6 +108,7 @@ class FramebufferState final : angle::NonCopyable
friend class Framebuffer; friend class Framebuffer;
GLuint mId;
std::string mLabel; std::string mLabel;
std::vector<FramebufferAttachment> mColorAttachments; std::vector<FramebufferAttachment> mColorAttachments;
...@@ -152,7 +155,7 @@ class Framebuffer final : public angle::ObserverInterface, public LabeledObject ...@@ -152,7 +155,7 @@ class Framebuffer final : public angle::ObserverInterface, public LabeledObject
rx::FramebufferImpl *getImplementation() const { return mImpl; } rx::FramebufferImpl *getImplementation() const { return mImpl; }
GLuint id() const { return mId; } GLuint id() const { return mState.mId; }
void setAttachment(const Context *context, void setAttachment(const Context *context,
GLenum type, GLenum type,
...@@ -386,7 +389,6 @@ class Framebuffer final : public angle::ObserverInterface, public LabeledObject ...@@ -386,7 +389,6 @@ class Framebuffer final : public angle::ObserverInterface, public LabeledObject
FramebufferState mState; FramebufferState mState;
rx::FramebufferImpl *mImpl; rx::FramebufferImpl *mImpl;
GLuint mId;
Optional<GLenum> mCachedStatus; Optional<GLenum> mCachedStatus;
std::vector<angle::ObserverBinding> mDirtyColorAttachmentBindings; std::vector<angle::ObserverBinding> mDirtyColorAttachmentBindings;
......
...@@ -98,6 +98,8 @@ class ProgramImpl : angle::NonCopyable ...@@ -98,6 +98,8 @@ class ProgramImpl : angle::NonCopyable
{ {
} }
const gl::ProgramState &getState() const { return mState; }
protected: protected:
const gl::ProgramState &mState; const gl::ProgramState &mState;
}; };
......
...@@ -43,6 +43,8 @@ class VertexArrayImpl : angle::NonCopyable ...@@ -43,6 +43,8 @@ class VertexArrayImpl : angle::NonCopyable
virtual void destroy(const gl::Context *context) {} virtual void destroy(const gl::Context *context) {}
virtual ~VertexArrayImpl() {} virtual ~VertexArrayImpl() {}
const gl::VertexArrayState &getState() const { return mState; }
protected: protected:
const gl::VertexArrayState &mState; const gl::VertexArrayState &mState;
}; };
......
...@@ -44,11 +44,10 @@ void RenderStateCache::clear() ...@@ -44,11 +44,10 @@ void RenderStateCache::clear()
// static // static
d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *context, d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *context,
const gl::Framebuffer *framebuffer, FramebufferD3D *framebufferD3D,
const gl::BlendState &blendState) const gl::BlendState &blendState)
{ {
d3d11::BlendStateKey key; d3d11::BlendStateKey key;
FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer);
const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(context); const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(context);
const UINT8 blendStateMask = const UINT8 blendStateMask =
gl_d3d11::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, gl_d3d11::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
......
...@@ -61,6 +61,7 @@ struct hash<gl::SamplerState> ...@@ -61,6 +61,7 @@ struct hash<gl::SamplerState>
namespace rx namespace rx
{ {
class FramebufferD3D;
class Renderer11; class Renderer11;
class RenderStateCache : angle::NonCopyable class RenderStateCache : angle::NonCopyable
...@@ -72,7 +73,7 @@ class RenderStateCache : angle::NonCopyable ...@@ -72,7 +73,7 @@ class RenderStateCache : angle::NonCopyable
void clear(); void clear();
static d3d11::BlendStateKey GetBlendStateKey(const gl::Context *context, static d3d11::BlendStateKey GetBlendStateKey(const gl::Context *context,
const gl::Framebuffer *framebuffer, FramebufferD3D *framebufferD3D,
const gl::BlendState &blendState); const gl::BlendState &blendState);
gl::Error getBlendState(Renderer11 *renderer, gl::Error getBlendState(Renderer11 *renderer,
const d3d11::BlendStateKey &key, const d3d11::BlendStateKey &key,
......
...@@ -139,7 +139,7 @@ Optional<size_t> FindFirstNonInstanced( ...@@ -139,7 +139,7 @@ Optional<size_t> FindFirstNonInstanced(
return Optional<size_t>::Invalid(); return Optional<size_t>::Invalid();
} }
void SortAttributesByLayout(const gl::Program *program, void SortAttributesByLayout(const ProgramD3D &programD3D,
const std::vector<TranslatedAttribute> &vertexArrayAttribs, const std::vector<TranslatedAttribute> &vertexArrayAttribs,
const std::vector<TranslatedAttribute> &currentValueAttribs, const std::vector<TranslatedAttribute> &currentValueAttribs,
AttribIndexArray *sortedD3DSemanticsOut, AttribIndexArray *sortedD3DSemanticsOut,
...@@ -147,10 +147,9 @@ void SortAttributesByLayout(const gl::Program *program, ...@@ -147,10 +147,9 @@ void SortAttributesByLayout(const gl::Program *program,
{ {
sortedAttributesOut->clear(); sortedAttributesOut->clear();
const auto &locationToSemantic = const AttribIndexArray &locationToSemantic = programD3D.getAttribLocationToD3DSemantics();
GetImplAs<ProgramD3D>(program)->getAttribLocationToD3DSemantics();
for (auto locationIndex : program->getActiveAttribLocationsMask()) for (auto locationIndex : programD3D.getState().getActiveAttribLocationsMask())
{ {
int d3dSemantic = locationToSemantic[locationIndex]; int d3dSemantic = locationToSemantic[locationIndex];
if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic)) if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic))
...@@ -591,7 +590,10 @@ StateManager11::StateManager11(Renderer11 *renderer) ...@@ -591,7 +590,10 @@ StateManager11::StateManager11(Renderer11 *renderer)
mVertexDataManager(renderer), mVertexDataManager(renderer),
mIndexDataManager(renderer), mIndexDataManager(renderer),
mIsMultiviewEnabled(false), mIsMultiviewEnabled(false),
mEmptySerial(mRenderer->generateSerial()) mEmptySerial(mRenderer->generateSerial()),
mProgramD3D(nullptr),
mVertexArray11(nullptr),
mFramebuffer11(nullptr)
{ {
mCurBlendState.blend = false; mCurBlendState.blend = false;
mCurBlendState.sourceBlendRGB = GL_ONE; mCurBlendState.sourceBlendRGB = GL_ONE;
...@@ -745,9 +747,7 @@ gl::Error StateManager11::updateStateForCompute(const gl::Context *context, ...@@ -745,9 +747,7 @@ gl::Error StateManager11::updateStateForCompute(const gl::Context *context,
mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ); mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ);
// TODO(jmadill): Use dirty bits. // TODO(jmadill): Use dirty bits.
const auto &glState = context->getGLState(); mProgramD3D->updateSamplerMapping();
auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
programD3D->updateSamplerMapping();
// TODO(jmadill): Use dirty bits. // TODO(jmadill): Use dirty bits.
ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Compute)); ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Compute));
...@@ -997,6 +997,7 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -997,6 +997,7 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt
{ {
handleMultiviewDrawFramebufferChange(context); handleMultiviewDrawFramebufferChange(context);
} }
mFramebuffer11 = GetImplAs<Framebuffer11>(state.getDrawFramebuffer());
break; break;
case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING: case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
invalidateVertexBuffer(); invalidateVertexBuffer();
...@@ -1006,6 +1007,7 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -1006,6 +1007,7 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt
mDirtyCurrentValueAttribs.set(); mDirtyCurrentValueAttribs.set();
// Invalidate the cached index buffer. // Invalidate the cached index buffer.
invalidateIndexBuffer(); invalidateIndexBuffer();
mVertexArray11 = GetImplAs<VertexArray11>(state.getVertexArray());
break; break;
case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS: case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
invalidateProgramUniformBuffers(); invalidateProgramUniformBuffers();
...@@ -1019,6 +1021,9 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -1019,6 +1021,9 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt
case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING: case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
invalidateTransformFeedback(); invalidateTransformFeedback();
break; break;
case gl::State::DIRTY_BIT_PROGRAM_BINDING:
mProgramD3D = GetImplAs<ProgramD3D>(state.getProgram());
break;
case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE: case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
{ {
mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY); mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
...@@ -1029,17 +1034,14 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -1029,17 +1034,14 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt
invalidateProgramUniforms(); invalidateProgramUniforms();
invalidateProgramUniformBuffers(); invalidateProgramUniformBuffers();
invalidateDriverUniforms(); invalidateDriverUniforms();
if (mIsMultiviewEnabled) // If ANGLE_multiview is enabled, the attribute divisor has to be updated for each
// binding. When using compute, there could be no vertex array.
if (mIsMultiviewEnabled && mVertexArray11)
{ {
gl::VertexArray *vao = state.getVertexArray(); ASSERT(mProgramD3D);
ASSERT(vao); const gl::ProgramState &programState = mProgramD3D->getState();
// If ANGLE_multiview is enabled, the attribute divisor has to be updated for int numViews = programState.usesMultiview() ? programState.getNumViews() : 1;
// each binding. mVertexArray11->markAllAttributeDivisorsForAdjustment(numViews);
VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao);
const gl::Program *program = state.getProgram();
ASSERT(program);
int numViews = program->usesMultiview() ? program->getNumViews() : 1;
vao11->markAllAttributeDivisorsForAdjustment(numViews);
} }
break; break;
} }
...@@ -1100,14 +1102,13 @@ void StateManager11::handleMultiviewDrawFramebufferChange(const gl::Context *con ...@@ -1100,14 +1102,13 @@ void StateManager11::handleMultiviewDrawFramebufferChange(const gl::Context *con
} }
gl::Error StateManager11::syncBlendState(const gl::Context *context, gl::Error StateManager11::syncBlendState(const gl::Context *context,
const gl::Framebuffer *framebuffer,
const gl::BlendState &blendState, const gl::BlendState &blendState,
const gl::ColorF &blendColor, const gl::ColorF &blendColor,
unsigned int sampleMask) unsigned int sampleMask)
{ {
const d3d11::BlendState *dxBlendState = nullptr; const d3d11::BlendState *dxBlendState = nullptr;
const d3d11::BlendStateKey &key = const d3d11::BlendStateKey &key =
RenderStateCache::GetBlendStateKey(context, framebuffer, blendState); RenderStateCache::GetBlendStateKey(context, mFramebuffer11, blendState);
ANGLE_TRY(mRenderer->getBlendState(key, &dxBlendState)); ANGLE_TRY(mRenderer->getBlendState(key, &dxBlendState));
...@@ -1381,14 +1382,9 @@ void StateManager11::invalidateRenderTarget() ...@@ -1381,14 +1382,9 @@ void StateManager11::invalidateRenderTarget()
void StateManager11::processFramebufferInvalidation(const gl::Context *context) void StateManager11::processFramebufferInvalidation(const gl::Context *context)
{ {
if (!mRenderTargetIsDirty) ASSERT(mRenderTargetIsDirty);
{
return;
}
ASSERT(context); ASSERT(context);
mRenderTargetIsDirty = false;
mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET); mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
// The pixel shader is dependent on the output layout. // The pixel shader is dependent on the output layout.
...@@ -1709,20 +1705,20 @@ bool StateManager11::unsetConflictingSRVs(gl::ShaderType shaderType, ...@@ -1709,20 +1705,20 @@ bool StateManager11::unsetConflictingSRVs(gl::ShaderType shaderType,
} }
void StateManager11::unsetConflictingAttachmentResources( void StateManager11::unsetConflictingAttachmentResources(
const gl::FramebufferAttachment *attachment, const gl::FramebufferAttachment &attachment,
ID3D11Resource *resource) ID3D11Resource *resource)
{ {
// Unbind render target SRVs from the shader here to prevent D3D11 warnings. // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
if (attachment->type() == GL_TEXTURE) if (attachment.type() == GL_TEXTURE)
{ {
uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource); uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource);
const gl::ImageIndex &index = attachment->getTextureImageIndex(); const gl::ImageIndex &index = attachment.getTextureImageIndex();
// The index doesn't need to be corrected for the small compressed texture workaround // The index doesn't need to be corrected for the small compressed texture workaround
// because a rendertarget is never compressed. // because a rendertarget is never compressed.
unsetConflictingSRVs(gl::ShaderType::Vertex, resourcePtr, &index); unsetConflictingSRVs(gl::ShaderType::Vertex, resourcePtr, &index);
unsetConflictingSRVs(gl::ShaderType::Fragment, resourcePtr, &index); unsetConflictingSRVs(gl::ShaderType::Fragment, resourcePtr, &index);
} }
else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT) else if (attachment.type() == GL_FRAMEBUFFER_DEFAULT)
{ {
uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource); uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource);
unsetConflictingSRVs(gl::ShaderType::Vertex, resourcePtr, nullptr); unsetConflictingSRVs(gl::ShaderType::Vertex, resourcePtr, nullptr);
...@@ -1785,36 +1781,32 @@ void StateManager11::deinitialize() ...@@ -1785,36 +1781,32 @@ void StateManager11::deinitialize()
mPointSpriteIndexBuffer.reset(); mPointSpriteIndexBuffer.reset();
} }
gl::Error StateManager11::syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer) // Applies the render target surface, depth stencil surface, viewport rectangle and
// scissor rectangle to the renderer
gl::Error StateManager11::syncFramebuffer(const gl::Context *context)
{ {
Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
// Applies the render target surface, depth stencil surface, viewport rectangle and
// scissor rectangle to the renderer
ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit());
// Check for zero-sized default framebuffer, which is a special case. // Check for zero-sized default framebuffer, which is a special case.
// in this case we do not wish to modify any state and just silently return false. // in this case we do not wish to modify any state and just silently return false.
// this will not report any gl error but will cause the calling method to return. // this will not report any gl error but will cause the calling method to return.
if (framebuffer->id() == 0) if (mFramebuffer11->getState().id() == 0)
{ {
const gl::Extents &size = framebuffer->getFirstColorbuffer()->getSize(); RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
if (size.width == 0 || size.height == 0) const gl::Extents &size = firstRT->getExtents();
if (size.empty())
{ {
return gl::NoError(); return gl::NoError();
} }
} }
RTVArray framebufferRTVs = {{}}; RTVArray framebufferRTVs = {{}};
const auto &colorRTs = mFramebuffer11->getCachedColorRenderTargets();
const auto &colorRTs = framebuffer11->getCachedColorRenderTargets();
size_t appliedRTIndex = 0; size_t appliedRTIndex = 0;
bool skipInactiveRTs = mRenderer->getWorkarounds().mrtPerfWorkaround; bool skipInactiveRTs = mRenderer->getWorkarounds().mrtPerfWorkaround;
const auto &drawStates = framebuffer->getDrawBufferStates(); const auto &drawStates = mFramebuffer11->getState().getDrawBufferStates();
gl::DrawBufferMask activeProgramOutputs = gl::DrawBufferMask activeProgramOutputs = mProgramD3D->getState().getActiveOutputVariables();
context->getContextState().getState().getProgram()->getActiveOutputVariables();
UINT maxExistingRT = 0; UINT maxExistingRT = 0;
const auto &colorAttachments = mFramebuffer11->getState().getColorAttachments();
for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex) for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex)
{ {
...@@ -1834,8 +1826,8 @@ gl::Error StateManager11::syncFramebuffer(const gl::Context *context, gl::Frameb ...@@ -1834,8 +1826,8 @@ gl::Error StateManager11::syncFramebuffer(const gl::Context *context, gl::Frameb
maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1; maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1;
// Unset conflicting texture SRVs // Unset conflicting texture SRVs
const auto *attachment = framebuffer->getColorbuffer(rtIndex); const gl::FramebufferAttachment &attachment = colorAttachments[rtIndex];
ASSERT(attachment); ASSERT(attachment.isAttached());
unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get()); unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get());
} }
...@@ -1844,16 +1836,17 @@ gl::Error StateManager11::syncFramebuffer(const gl::Context *context, gl::Frameb ...@@ -1844,16 +1836,17 @@ gl::Error StateManager11::syncFramebuffer(const gl::Context *context, gl::Frameb
// Get the depth stencil buffers // Get the depth stencil buffers
ID3D11DepthStencilView *framebufferDSV = nullptr; ID3D11DepthStencilView *framebufferDSV = nullptr;
const auto *depthStencilRenderTarget = framebuffer11->getCachedDepthStencilRenderTarget(); const auto *depthStencilRenderTarget = mFramebuffer11->getCachedDepthStencilRenderTarget();
if (depthStencilRenderTarget) if (depthStencilRenderTarget)
{ {
framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get(); framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get();
ASSERT(framebufferDSV); ASSERT(framebufferDSV);
// Unset conflicting texture SRVs // Unset conflicting texture SRVs
const auto *attachment = framebuffer->getDepthOrStencilbuffer(); const gl::FramebufferAttachment *attachment =
mFramebuffer11->getState().getDepthOrStencilAttachment();
ASSERT(attachment); ASSERT(attachment);
unsetConflictingAttachmentResources(attachment, unsetConflictingAttachmentResources(*attachment,
depthStencilRenderTarget->getTexture().get()); depthStencilRenderTarget->getTexture().get());
} }
...@@ -1875,9 +1868,10 @@ void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex) ...@@ -1875,9 +1868,10 @@ void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex)
invalidateShaders(); invalidateShaders();
} }
gl::Error StateManager11::syncCurrentValueAttribs(const gl::State &glState) gl::Error StateManager11::syncCurrentValueAttribs(
const std::vector<gl::VertexAttribCurrentValueData> &currentValues)
{ {
const auto &activeAttribsMask = glState.getProgram()->getActiveAttribLocationsMask(); const auto &activeAttribsMask = mProgramD3D->getState().getActiveAttribLocationsMask();
const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs); const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
if (!dirtyActiveAttribs.any()) if (!dirtyActiveAttribs.any())
...@@ -1885,8 +1879,8 @@ gl::Error StateManager11::syncCurrentValueAttribs(const gl::State &glState) ...@@ -1885,8 +1879,8 @@ gl::Error StateManager11::syncCurrentValueAttribs(const gl::State &glState)
return gl::NoError(); return gl::NoError();
} }
const auto &vertexAttributes = glState.getVertexArray()->getVertexAttributes(); const auto &vertexAttributes = mVertexArray11->getState().getVertexAttributes();
const auto &vertexBindings = glState.getVertexArray()->getVertexBindings(); const auto &vertexBindings = mVertexArray11->getState().getVertexBindings();
mDirtyCurrentValueAttribs = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs); mDirtyCurrentValueAttribs = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs);
for (auto attribIndex : dirtyActiveAttribs) for (auto attribIndex : dirtyActiveAttribs)
...@@ -1895,7 +1889,7 @@ gl::Error StateManager11::syncCurrentValueAttribs(const gl::State &glState) ...@@ -1895,7 +1889,7 @@ gl::Error StateManager11::syncCurrentValueAttribs(const gl::State &glState)
continue; continue;
const auto *attrib = &vertexAttributes[attribIndex]; const auto *attrib = &vertexAttributes[attribIndex];
const auto &currentValue = glState.getVertexAttribCurrentValue(attribIndex); const auto &currentValue = currentValues[attribIndex];
TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex]; TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex];
currentValueAttrib->currentValueType = currentValue.Type; currentValueAttrib->currentValueType = currentValue.Type;
currentValueAttrib->attribute = attrib; currentValueAttrib->attribute = attrib;
...@@ -1993,19 +1987,22 @@ gl::Error StateManager11::updateState(const gl::Context *context, ...@@ -1993,19 +1987,22 @@ gl::Error StateManager11::updateState(const gl::Context *context,
const gl::DrawCallParams &drawCallParams) const gl::DrawCallParams &drawCallParams)
{ {
const gl::State &glState = context->getGLState(); const gl::State &glState = context->getGLState();
auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
// TODO(jmadill): Use dirty bits. // TODO(jmadill): Use dirty bits.
processFramebufferInvalidation(context); if (mRenderTargetIsDirty)
{
processFramebufferInvalidation(context);
mRenderTargetIsDirty = false;
}
// TODO(jmadill): Use dirty bits. // TODO(jmadill): Use dirty bits.
if (programD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty) if (mProgramD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty)
{ {
invalidateTexturesAndSamplers(); invalidateTexturesAndSamplers();
} }
// TODO(jmadill): Use dirty bits. // TODO(jmadill): Use dirty bits.
if (programD3D->anyShaderUniformsDirty()) if (mProgramD3D->anyShaderUniformsDirty())
{ {
mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS); mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
} }
...@@ -2017,13 +2014,11 @@ gl::Error StateManager11::updateState(const gl::Context *context, ...@@ -2017,13 +2014,11 @@ gl::Error StateManager11::updateState(const gl::Context *context,
mDirtySwizzles = false; mDirtySwizzles = false;
} }
gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); ANGLE_TRY(mFramebuffer11->markAttachmentsDirty(context));
Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
ANGLE_TRY(framebuffer11->markAttachmentsDirty(context));
// TODO(jiawei.shao@intel.com): This can be recomputed only on framebuffer or multisample mask // TODO(jiawei.shao@intel.com): This can be recomputed only on framebuffer or multisample mask
// state changes. // state changes.
RenderTarget11 *firstRT = framebuffer11->getFirstRenderTarget(); RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
int samples = (firstRT ? firstRT->getSamples() : 0); int samples = (firstRT ? firstRT->getSamples() : 0);
unsigned int sampleMask = GetBlendSampleMask(glState, samples); unsigned int sampleMask = GetBlendSampleMask(glState, samples);
if (sampleMask != mCurSampleMask) if (sampleMask != mCurSampleMask)
...@@ -2031,8 +2026,7 @@ gl::Error StateManager11::updateState(const gl::Context *context, ...@@ -2031,8 +2026,7 @@ gl::Error StateManager11::updateState(const gl::Context *context,
mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
} }
VertexArray11 *vao11 = GetImplAs<VertexArray11>(glState.getVertexArray()); ANGLE_TRY(mVertexArray11->syncStateForDraw(context, drawCallParams));
ANGLE_TRY(vao11->syncStateForDraw(context, drawCallParams));
// Changes in the draw call can affect the vertex buffer translations. // Changes in the draw call can affect the vertex buffer translations.
if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != drawCallParams.firstVertex()) if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != drawCallParams.firstVertex())
...@@ -2069,7 +2063,7 @@ gl::Error StateManager11::updateState(const gl::Context *context, ...@@ -2069,7 +2063,7 @@ gl::Error StateManager11::updateState(const gl::Context *context,
switch (dirtyBit) switch (dirtyBit)
{ {
case DIRTY_BIT_RENDER_TARGET: case DIRTY_BIT_RENDER_TARGET:
ANGLE_TRY(syncFramebuffer(context, framebuffer)); ANGLE_TRY(syncFramebuffer(context));
break; break;
case DIRTY_BIT_VIEWPORT_STATE: case DIRTY_BIT_VIEWPORT_STATE:
syncViewport(context); syncViewport(context);
...@@ -2081,8 +2075,8 @@ gl::Error StateManager11::updateState(const gl::Context *context, ...@@ -2081,8 +2075,8 @@ gl::Error StateManager11::updateState(const gl::Context *context,
ANGLE_TRY(syncRasterizerState(context, drawCallParams)); ANGLE_TRY(syncRasterizerState(context, drawCallParams));
break; break;
case DIRTY_BIT_BLEND_STATE: case DIRTY_BIT_BLEND_STATE:
ANGLE_TRY(syncBlendState(context, framebuffer, glState.getBlendState(), ANGLE_TRY(syncBlendState(context, glState.getBlendState(), glState.getBlendColor(),
glState.getBlendColor(), sampleMask)); sampleMask));
break; break;
case DIRTY_BIT_DEPTH_STENCIL_STATE: case DIRTY_BIT_DEPTH_STENCIL_STATE:
ANGLE_TRY(syncDepthStencilState(glState)); ANGLE_TRY(syncDepthStencilState(glState));
...@@ -2092,20 +2086,20 @@ gl::Error StateManager11::updateState(const gl::Context *context, ...@@ -2092,20 +2086,20 @@ gl::Error StateManager11::updateState(const gl::Context *context,
ANGLE_TRY(syncTextures(context)); ANGLE_TRY(syncTextures(context));
break; break;
case DIRTY_BIT_PROGRAM_UNIFORMS: case DIRTY_BIT_PROGRAM_UNIFORMS:
ANGLE_TRY(applyUniforms(programD3D)); ANGLE_TRY(applyUniforms());
break; break;
case DIRTY_BIT_DRIVER_UNIFORMS: case DIRTY_BIT_DRIVER_UNIFORMS:
// This must happen after viewport sync; the viewport affects builtin uniforms. // This must happen after viewport sync; the viewport affects builtin uniforms.
ANGLE_TRY(applyDriverUniforms(*programD3D)); ANGLE_TRY(applyDriverUniforms());
break; break;
case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS: case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
ANGLE_TRY(syncUniformBuffers(context, programD3D)); ANGLE_TRY(syncUniformBuffers(context));
break; break;
case DIRTY_BIT_SHADERS: case DIRTY_BIT_SHADERS:
ANGLE_TRY(syncProgram(context, drawCallParams.mode())); ANGLE_TRY(syncProgram(context, drawCallParams.mode()));
break; break;
case DIRTY_BIT_CURRENT_VALUE_ATTRIBS: case DIRTY_BIT_CURRENT_VALUE_ATTRIBS:
ANGLE_TRY(syncCurrentValueAttribs(glState)); ANGLE_TRY(syncCurrentValueAttribs(glState.getVertexAttribCurrentValues()));
break; break;
case DIRTY_BIT_TRANSFORM_FEEDBACK: case DIRTY_BIT_TRANSFORM_FEEDBACK:
ANGLE_TRY(syncTransformFeedbackBuffers(context)); ANGLE_TRY(syncTransformFeedbackBuffers(context));
...@@ -2114,7 +2108,7 @@ gl::Error StateManager11::updateState(const gl::Context *context, ...@@ -2114,7 +2108,7 @@ gl::Error StateManager11::updateState(const gl::Context *context,
ANGLE_TRY(syncVertexBuffersAndInputLayout(context, drawCallParams)); ANGLE_TRY(syncVertexBuffersAndInputLayout(context, drawCallParams));
break; break;
case DIRTY_BIT_PRIMITIVE_TOPOLOGY: case DIRTY_BIT_PRIMITIVE_TOPOLOGY:
syncPrimitiveTopology(glState, programD3D, drawCallParams.mode()); syncPrimitiveTopology(glState, drawCallParams.mode());
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -2394,17 +2388,16 @@ gl::Error StateManager11::applyTextures(const gl::Context *context, gl::ShaderTy ...@@ -2394,17 +2388,16 @@ gl::Error StateManager11::applyTextures(const gl::Context *context, gl::ShaderTy
ASSERT(shaderType != gl::ShaderType::Compute); ASSERT(shaderType != gl::ShaderType::Compute);
const auto &glState = context->getGLState(); const auto &glState = context->getGLState();
const auto &caps = context->getCaps(); const auto &caps = context->getCaps();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
ASSERT(!programD3D->isSamplerMappingDirty()); ASSERT(!mProgramD3D->isSamplerMappingDirty());
// TODO(jmadill): Use the Program's sampler bindings. // TODO(jmadill): Use the Program's sampler bindings.
const auto &completeTextures = glState.getCompleteTextureCache(); const auto &completeTextures = glState.getCompleteTextureCache();
unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType); unsigned int samplerRange = mProgramD3D->getUsedSamplerRange(shaderType);
for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
{ {
GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps); GLint textureUnit = mProgramD3D->getSamplerMapping(shaderType, samplerIndex, caps);
ASSERT(textureUnit != -1); ASSERT(textureUnit != -1);
gl::Texture *texture = completeTextures[textureUnit]; gl::Texture *texture = completeTextures[textureUnit];
...@@ -2422,7 +2415,7 @@ gl::Error StateManager11::applyTextures(const gl::Context *context, gl::ShaderTy ...@@ -2422,7 +2415,7 @@ gl::Error StateManager11::applyTextures(const gl::Context *context, gl::ShaderTy
else else
{ {
gl::TextureType textureType = gl::TextureType textureType =
programD3D->getSamplerTextureType(shaderType, samplerIndex); mProgramD3D->getSamplerTextureType(shaderType, samplerIndex);
// Texture is not sampler complete or it is in use by the framebuffer. Bind the // Texture is not sampler complete or it is in use by the framebuffer. Bind the
// incomplete texture. // incomplete texture.
...@@ -2578,26 +2571,25 @@ gl::Error StateManager11::syncTexturesForCompute(const gl::Context *context) ...@@ -2578,26 +2571,25 @@ gl::Error StateManager11::syncTexturesForCompute(const gl::Context *context)
{ {
const auto &glState = context->getGLState(); const auto &glState = context->getGLState();
const auto &caps = context->getCaps(); const auto &caps = context->getCaps();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
// TODO(xinghua.cao@intel.com): Implement sampler feature in compute shader. // TODO(xinghua.cao@intel.com): Implement sampler feature in compute shader.
unsigned int readonlyImageRange = programD3D->getUsedImageRange(gl::ShaderType::Compute, true); unsigned int readonlyImageRange = mProgramD3D->getUsedImageRange(gl::ShaderType::Compute, true);
for (unsigned int readonlyImageIndex = 0; readonlyImageIndex < readonlyImageRange; for (unsigned int readonlyImageIndex = 0; readonlyImageIndex < readonlyImageRange;
readonlyImageIndex++) readonlyImageIndex++)
{ {
GLint imageUnitIndex = GLint imageUnitIndex =
programD3D->getImageMapping(gl::ShaderType::Compute, readonlyImageIndex, true, caps); mProgramD3D->getImageMapping(gl::ShaderType::Compute, readonlyImageIndex, true, caps);
ASSERT(imageUnitIndex != -1); ASSERT(imageUnitIndex != -1);
const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex); const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
ANGLE_TRY(setTextureForImage(context, gl::ShaderType::Compute, readonlyImageIndex, true, ANGLE_TRY(setTextureForImage(context, gl::ShaderType::Compute, readonlyImageIndex, true,
imageUnit)); imageUnit));
} }
unsigned int imageRange = programD3D->getUsedImageRange(gl::ShaderType::Compute, false); unsigned int imageRange = mProgramD3D->getUsedImageRange(gl::ShaderType::Compute, false);
for (unsigned int imageIndex = 0; imageIndex < imageRange; imageIndex++) for (unsigned int imageIndex = 0; imageIndex < imageRange; imageIndex++)
{ {
GLint imageUnitIndex = GLint imageUnitIndex =
programD3D->getImageMapping(gl::ShaderType::Compute, imageIndex, false, caps); mProgramD3D->getImageMapping(gl::ShaderType::Compute, imageIndex, false, caps);
ASSERT(imageUnitIndex != -1); ASSERT(imageUnitIndex != -1);
const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex); const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
ANGLE_TRY( ANGLE_TRY(
...@@ -2672,25 +2664,23 @@ gl::Error StateManager11::syncProgram(const gl::Context *context, gl::PrimitiveM ...@@ -2672,25 +2664,23 @@ gl::Error StateManager11::syncProgram(const gl::Context *context, gl::PrimitiveM
ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode)); ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode));
const auto &glState = context->getGLState(); const auto &glState = context->getGLState();
const auto *va11 = GetImplAs<VertexArray11>(glState.getVertexArray());
auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState); mProgramD3D->updateCachedInputLayout(mVertexArray11->getCurrentStateSerial(), glState);
// Binaries must be compiled before the sync. // Binaries must be compiled before the sync.
ASSERT(programD3D->hasVertexExecutableForCachedInputLayout()); ASSERT(mProgramD3D->hasVertexExecutableForCachedInputLayout());
ASSERT(programD3D->hasGeometryExecutableForPrimitiveType(drawMode)); ASSERT(mProgramD3D->hasGeometryExecutableForPrimitiveType(drawMode));
ASSERT(programD3D->hasPixelExecutableForCachedOutputLayout()); ASSERT(mProgramD3D->hasPixelExecutableForCachedOutputLayout());
ShaderExecutableD3D *vertexExe = nullptr; ShaderExecutableD3D *vertexExe = nullptr;
ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&vertexExe, nullptr)); ANGLE_TRY(mProgramD3D->getVertexExecutableForCachedInputLayout(&vertexExe, nullptr));
ShaderExecutableD3D *pixelExe = nullptr; ShaderExecutableD3D *pixelExe = nullptr;
ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr)); ANGLE_TRY(mProgramD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr));
ShaderExecutableD3D *geometryExe = nullptr; ShaderExecutableD3D *geometryExe = nullptr;
ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe, ANGLE_TRY(mProgramD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe,
nullptr)); nullptr));
const d3d11::VertexShader *vertexShader = const d3d11::VertexShader *vertexShader =
(vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr); (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);
...@@ -2725,16 +2715,11 @@ gl::Error StateManager11::syncProgram(const gl::Context *context, gl::PrimitiveM ...@@ -2725,16 +2715,11 @@ gl::Error StateManager11::syncProgram(const gl::Context *context, gl::PrimitiveM
gl::Error StateManager11::syncVertexBuffersAndInputLayout(const gl::Context *context, gl::Error StateManager11::syncVertexBuffersAndInputLayout(const gl::Context *context,
const gl::DrawCallParams &drawCallParams) const gl::DrawCallParams &drawCallParams)
{ {
const gl::State &state = context->getGLState(); const auto &vertexArrayAttribs = mVertexArray11->getTranslatedAttribs();
const gl::VertexArray *vertexArray = state.getVertexArray();
VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(vertexArray);
const auto &vertexArrayAttribs = vertexArray11->getTranslatedAttribs();
gl::Program *program = state.getProgram();
// Sort the attributes according to ensure we re-use similar input layouts. // Sort the attributes according to ensure we re-use similar input layouts.
AttribIndexArray sortedSemanticIndices; AttribIndexArray sortedSemanticIndices;
SortAttributesByLayout(program, vertexArrayAttribs, mCurrentValueAttribs, SortAttributesByLayout(*mProgramD3D, vertexArrayAttribs, mCurrentValueAttribs,
&sortedSemanticIndices, &mCurrentAttributes); &sortedSemanticIndices, &mCurrentAttributes);
D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel; D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
...@@ -2755,6 +2740,7 @@ gl::Error StateManager11::syncVertexBuffersAndInputLayout(const gl::Context *con ...@@ -2755,6 +2740,7 @@ gl::Error StateManager11::syncVertexBuffersAndInputLayout(const gl::Context *con
} }
// Update the applied input layout by querying the cache. // Update the applied input layout by querying the cache.
const gl::State &state = context->getGLState();
const d3d11::InputLayout *inputLayout = nullptr; const d3d11::InputLayout *inputLayout = nullptr;
ANGLE_TRY(mInputLayoutCache.getInputLayout( ANGLE_TRY(mInputLayoutCache.getInputLayout(
mRenderer, state, mCurrentAttributes, sortedSemanticIndices, drawCallParams, &inputLayout)); mRenderer, state, mCurrentAttributes, sortedSemanticIndices, drawCallParams, &inputLayout));
...@@ -2769,12 +2755,8 @@ gl::Error StateManager11::syncVertexBuffersAndInputLayout(const gl::Context *con ...@@ -2769,12 +2755,8 @@ gl::Error StateManager11::syncVertexBuffersAndInputLayout(const gl::Context *con
gl::Error StateManager11::applyVertexBuffers(const gl::Context *context, gl::Error StateManager11::applyVertexBuffers(const gl::Context *context,
const gl::DrawCallParams &drawCallParams) const gl::DrawCallParams &drawCallParams)
{ {
const gl::State &state = context->getGLState();
gl::Program *program = state.getProgram();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
bool programUsesInstancedPointSprites = bool programUsesInstancedPointSprites =
programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); mProgramD3D->usesPointSize() && mProgramD3D->usesInstancedPointSpriteEmulation();
bool instancedPointSpritesActive = bool instancedPointSpritesActive =
programUsesInstancedPointSprites && (drawCallParams.mode() == gl::PrimitiveMode::Points); programUsesInstancedPointSprites && (drawCallParams.mode() == gl::PrimitiveMode::Points);
...@@ -2805,9 +2787,8 @@ gl::Error StateManager11::applyVertexBuffers(const gl::Context *context, ...@@ -2805,9 +2787,8 @@ gl::Error StateManager11::applyVertexBuffers(const gl::Context *context,
} }
else if (instancedPointSpritesActive && drawCallParams.isDrawElements()) else if (instancedPointSpritesActive && drawCallParams.isDrawElements())
{ {
VertexArray11 *vao11 = GetImplAs<VertexArray11>(state.getVertexArray()); ASSERT(mVertexArray11->isCachedIndexInfoValid());
ASSERT(vao11->isCachedIndexInfoValid()); TranslatedIndexData indexInfo = mVertexArray11->getCachedIndexInfo();
TranslatedIndexData indexInfo = vao11->getCachedIndexInfo();
if (indexInfo.srcIndexData.srcBuffer != nullptr) if (indexInfo.srcIndexData.srcBuffer != nullptr)
{ {
const uint8_t *bufferData = nullptr; const uint8_t *bufferData = nullptr;
...@@ -2825,7 +2806,7 @@ gl::Error StateManager11::applyVertexBuffers(const gl::Context *context, ...@@ -2825,7 +2806,7 @@ gl::Error StateManager11::applyVertexBuffers(const gl::Context *context,
attrib, drawCallParams.firstVertex()), attrib, drawCallParams.firstVertex()),
buffer); buffer);
vao11->updateCachedIndexInfo(indexInfo); mVertexArray11->updateCachedIndexInfo(indexInfo);
} }
else else
{ {
...@@ -2921,18 +2902,14 @@ gl::Error StateManager11::applyVertexBuffers(const gl::Context *context, ...@@ -2921,18 +2902,14 @@ gl::Error StateManager11::applyVertexBuffers(const gl::Context *context,
gl::Error StateManager11::applyIndexBuffer(const gl::Context *context, gl::Error StateManager11::applyIndexBuffer(const gl::Context *context,
const gl::DrawCallParams &params) const gl::DrawCallParams &params)
{ {
const auto &glState = context->getGLState();
gl::VertexArray *vao = glState.getVertexArray();
VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao);
if (!mIndexBufferIsDirty) if (!mIndexBufferIsDirty)
{ {
// No streaming or index buffer application necessary. // No streaming or index buffer application necessary.
return gl::NoError(); return gl::NoError();
} }
GLenum destElementType = vao11->getCachedDestinationIndexType(); GLenum destElementType = mVertexArray11->getCachedDestinationIndexType();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); gl::Buffer *elementArrayBuffer = mVertexArray11->getState().getElementArrayBuffer().get();
TranslatedIndexData indexInfo; TranslatedIndexData indexInfo;
ANGLE_TRY(mIndexDataManager.prepareIndexData(context, params.type(), destElementType, ANGLE_TRY(mIndexDataManager.prepareIndexData(context, params.type(), destElementType,
...@@ -2960,7 +2937,7 @@ gl::Error StateManager11::applyIndexBuffer(const gl::Context *context, ...@@ -2960,7 +2937,7 @@ gl::Error StateManager11::applyIndexBuffer(const gl::Context *context,
mIndexBufferIsDirty = false; mIndexBufferIsDirty = false;
vao11->updateCachedIndexInfo(indexInfo); mVertexArray11->updateCachedIndexInfo(indexInfo);
return gl::NoError(); return gl::NoError();
} }
...@@ -3044,15 +3021,13 @@ gl::Error StateManager11::generateSwizzle(const gl::Context *context, gl::Textur ...@@ -3044,15 +3021,13 @@ gl::Error StateManager11::generateSwizzle(const gl::Context *context, gl::Textur
gl::Error StateManager11::generateSwizzlesForShader(const gl::Context *context, gl::ShaderType type) gl::Error StateManager11::generateSwizzlesForShader(const gl::Context *context, gl::ShaderType type)
{ {
const auto &glState = context->getGLState(); const gl::State &glState = context->getGLState();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); unsigned int samplerRange = mProgramD3D->getUsedSamplerRange(type);
unsigned int samplerRange = programD3D->getUsedSamplerRange(type);
for (unsigned int i = 0; i < samplerRange; i++) for (unsigned int i = 0; i < samplerRange; i++)
{ {
gl::TextureType textureType = programD3D->getSamplerTextureType(type, i); gl::TextureType textureType = mProgramD3D->getSamplerTextureType(type, i);
GLint textureUnit = programD3D->getSamplerMapping(type, i, context->getCaps()); GLint textureUnit = mProgramD3D->getSamplerMapping(type, i, context->getCaps());
if (textureUnit != -1) if (textureUnit != -1)
{ {
gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType); gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
...@@ -3074,12 +3049,12 @@ gl::Error StateManager11::generateSwizzles(const gl::Context *context) ...@@ -3074,12 +3049,12 @@ gl::Error StateManager11::generateSwizzles(const gl::Context *context)
return gl::NoError(); return gl::NoError();
} }
gl::Error StateManager11::applyUniforms(ProgramD3D *programD3D) gl::Error StateManager11::applyUniforms()
{ {
UniformStorage11 *vertexUniformStorage = UniformStorage11 *vertexUniformStorage =
GetAs<UniformStorage11>(programD3D->getShaderUniformStorage(gl::ShaderType::Vertex)); GetAs<UniformStorage11>(mProgramD3D->getShaderUniformStorage(gl::ShaderType::Vertex));
UniformStorage11 *fragmentUniformStorage = UniformStorage11 *fragmentUniformStorage =
GetAs<UniformStorage11>(programD3D->getShaderUniformStorage(gl::ShaderType::Fragment)); GetAs<UniformStorage11>(mProgramD3D->getShaderUniformStorage(gl::ShaderType::Fragment));
ASSERT(vertexUniformStorage); ASSERT(vertexUniformStorage);
ASSERT(fragmentUniformStorage); ASSERT(fragmentUniformStorage);
...@@ -3091,13 +3066,13 @@ gl::Error StateManager11::applyUniforms(ProgramD3D *programD3D) ...@@ -3091,13 +3066,13 @@ gl::Error StateManager11::applyUniforms(ProgramD3D *programD3D)
ANGLE_TRY(fragmentUniformStorage->getConstantBuffer(mRenderer, &pixelConstantBuffer)); ANGLE_TRY(fragmentUniformStorage->getConstantBuffer(mRenderer, &pixelConstantBuffer));
if (vertexUniformStorage->size() > 0 && if (vertexUniformStorage->size() > 0 &&
programD3D->areShaderUniformsDirty(gl::ShaderType::Vertex)) mProgramD3D->areShaderUniformsDirty(gl::ShaderType::Vertex))
{ {
UpdateUniformBuffer(deviceContext, vertexUniformStorage, vertexConstantBuffer); UpdateUniformBuffer(deviceContext, vertexUniformStorage, vertexConstantBuffer);
} }
if (fragmentUniformStorage->size() > 0 && if (fragmentUniformStorage->size() > 0 &&
programD3D->areShaderUniformsDirty(gl::ShaderType::Fragment)) mProgramD3D->areShaderUniformsDirty(gl::ShaderType::Fragment))
{ {
UpdateUniformBuffer(deviceContext, fragmentUniformStorage, pixelConstantBuffer); UpdateUniformBuffer(deviceContext, fragmentUniformStorage, pixelConstantBuffer);
} }
...@@ -3120,12 +3095,12 @@ gl::Error StateManager11::applyUniforms(ProgramD3D *programD3D) ...@@ -3120,12 +3095,12 @@ gl::Error StateManager11::applyUniforms(ProgramD3D *programD3D)
mCurrentConstantBufferPSSize[slot] = 0; mCurrentConstantBufferPSSize[slot] = 0;
} }
programD3D->markUniformsClean(); mProgramD3D->markUniformsClean();
return gl::NoError(); return gl::NoError();
} }
gl::Error StateManager11::applyDriverUniforms(const ProgramD3D &programD3D) gl::Error StateManager11::applyDriverUniforms()
{ {
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
...@@ -3157,9 +3132,9 @@ gl::Error StateManager11::applyDriverUniforms(const ProgramD3D &programD3D) ...@@ -3157,9 +3132,9 @@ gl::Error StateManager11::applyDriverUniforms(const ProgramD3D &programD3D)
// Sampler metadata and driver constants need to coexist in the same constant buffer to conserve // Sampler metadata and driver constants need to coexist in the same constant buffer to conserve
// constant buffer slots. We update both in the constant buffer if needed. // constant buffer slots. We update both in the constant buffer if needed.
ANGLE_TRY(mShaderConstants.updateBuffer(mRenderer, gl::ShaderType::Vertex, programD3D, ANGLE_TRY(mShaderConstants.updateBuffer(mRenderer, gl::ShaderType::Vertex, *mProgramD3D,
mDriverConstantBufferVS)); mDriverConstantBufferVS));
ANGLE_TRY(mShaderConstants.updateBuffer(mRenderer, gl::ShaderType::Fragment, programD3D, ANGLE_TRY(mShaderConstants.updateBuffer(mRenderer, gl::ShaderType::Fragment, *mProgramD3D,
mDriverConstantBufferPS)); mDriverConstantBufferPS));
// needed for the point sprite geometry shader // needed for the point sprite geometry shader
...@@ -3221,15 +3196,15 @@ gl::Error StateManager11::applyComputeUniforms(ProgramD3D *programD3D) ...@@ -3221,15 +3196,15 @@ gl::Error StateManager11::applyComputeUniforms(ProgramD3D *programD3D)
return gl::NoError(); return gl::NoError();
} }
gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D) gl::Error StateManager11::syncUniformBuffers(const gl::Context *context)
{ {
gl::ShaderMap<unsigned int> shaderReservedUBOs = mRenderer->getReservedShaderUniformBuffers(); gl::ShaderMap<unsigned int> shaderReservedUBOs = mRenderer->getReservedShaderUniformBuffers();
programD3D->updateUniformBufferCache(context->getCaps(), shaderReservedUBOs); mProgramD3D->updateUniformBufferCache(context->getCaps(), shaderReservedUBOs);
const auto &vertexUniformBuffers = const auto &vertexUniformBuffers =
programD3D->getShaderUniformBufferCache(gl::ShaderType::Vertex); mProgramD3D->getShaderUniformBufferCache(gl::ShaderType::Vertex);
const auto &fragmentUniformBuffers = const auto &fragmentUniformBuffers =
programD3D->getShaderUniformBufferCache(gl::ShaderType::Fragment); mProgramD3D->getShaderUniformBufferCache(gl::ShaderType::Fragment);
const auto &glState = context->getGLState(); const auto &glState = context->getGLState();
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
...@@ -3449,7 +3424,6 @@ void StateManager11::ConstantBufferObserver::reset() ...@@ -3449,7 +3424,6 @@ void StateManager11::ConstantBufferObserver::reset()
} }
void StateManager11::syncPrimitiveTopology(const gl::State &glState, void StateManager11::syncPrimitiveTopology(const gl::State &glState,
ProgramD3D *programD3D,
gl::PrimitiveMode currentDrawMode) gl::PrimitiveMode currentDrawMode)
{ {
D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
...@@ -3458,7 +3432,7 @@ void StateManager11::syncPrimitiveTopology(const gl::State &glState, ...@@ -3458,7 +3432,7 @@ void StateManager11::syncPrimitiveTopology(const gl::State &glState,
{ {
case gl::PrimitiveMode::Points: case gl::PrimitiveMode::Points:
{ {
bool usesPointSize = programD3D->usesPointSize(); bool usesPointSize = mProgramD3D->usesPointSize();
// ProgramBinary assumes non-point rendering if gl_PointSize isn't written, // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
// which affects varying interpolation. Since the value of gl_PointSize is // which affects varying interpolation. Since the value of gl_PointSize is
......
...@@ -18,14 +18,15 @@ ...@@ -18,14 +18,15 @@
#include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" #include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
#include "libANGLE/renderer/d3d/d3d11/Query11.h" #include "libANGLE/renderer/d3d/d3d11/Query11.h"
#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace rx namespace rx
{ {
class Buffer11; class Buffer11;
class Framebuffer11;
struct RenderTargetDesc; struct RenderTargetDesc;
struct Renderer11DeviceCaps; struct Renderer11DeviceCaps;
class VertexArray11;
class ShaderConstants11 : angle::NonCopyable class ShaderConstants11 : angle::NonCopyable
{ {
...@@ -261,11 +262,10 @@ class StateManager11 final : angle::NonCopyable ...@@ -261,11 +262,10 @@ class StateManager11 final : angle::NonCopyable
bool unsetConflictingSRVs(gl::ShaderType shaderType, bool unsetConflictingSRVs(gl::ShaderType shaderType,
uintptr_t resource, uintptr_t resource,
const gl::ImageIndex *index); const gl::ImageIndex *index);
void unsetConflictingAttachmentResources(const gl::FramebufferAttachment *attachment, void unsetConflictingAttachmentResources(const gl::FramebufferAttachment &attachment,
ID3D11Resource *resource); ID3D11Resource *resource);
gl::Error syncBlendState(const gl::Context *context, gl::Error syncBlendState(const gl::Context *context,
const gl::Framebuffer *framebuffer,
const gl::BlendState &blendState, const gl::BlendState &blendState,
const gl::ColorF &blendColor, const gl::ColorF &blendColor,
unsigned int sampleMask); unsigned int sampleMask);
...@@ -281,7 +281,7 @@ class StateManager11 final : angle::NonCopyable ...@@ -281,7 +281,7 @@ class StateManager11 final : angle::NonCopyable
void checkPresentPath(const gl::Context *context); void checkPresentPath(const gl::Context *context);
gl::Error syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer); gl::Error syncFramebuffer(const gl::Context *context);
gl::Error syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode); gl::Error syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode);
gl::Error syncTextures(const gl::Context *context); gl::Error syncTextures(const gl::Context *context);
...@@ -308,16 +308,17 @@ class StateManager11 final : angle::NonCopyable ...@@ -308,16 +308,17 @@ class StateManager11 final : angle::NonCopyable
gl::Error clearUAVs(gl::ShaderType shaderType, size_t rangeStart, size_t rangeEnd); gl::Error clearUAVs(gl::ShaderType shaderType, size_t rangeStart, size_t rangeEnd);
void handleMultiviewDrawFramebufferChange(const gl::Context *context); void handleMultiviewDrawFramebufferChange(const gl::Context *context);
gl::Error syncCurrentValueAttribs(const gl::State &glState); gl::Error syncCurrentValueAttribs(
const std::vector<gl::VertexAttribCurrentValueData> &currentValues);
gl::Error generateSwizzle(const gl::Context *context, gl::Texture *texture); gl::Error generateSwizzle(const gl::Context *context, gl::Texture *texture);
gl::Error generateSwizzlesForShader(const gl::Context *context, gl::ShaderType type); gl::Error generateSwizzlesForShader(const gl::Context *context, gl::ShaderType type);
gl::Error generateSwizzles(const gl::Context *context); gl::Error generateSwizzles(const gl::Context *context);
gl::Error applyDriverUniforms(const ProgramD3D &programD3D); gl::Error applyDriverUniforms();
gl::Error applyUniforms(ProgramD3D *programD3D); gl::Error applyUniforms();
gl::Error syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D); gl::Error syncUniformBuffers(const gl::Context *context);
gl::Error syncTransformFeedbackBuffers(const gl::Context *context); gl::Error syncTransformFeedbackBuffers(const gl::Context *context);
// These are currently only called internally. // These are currently only called internally.
...@@ -344,9 +345,7 @@ class StateManager11 final : angle::NonCopyable ...@@ -344,9 +345,7 @@ class StateManager11 final : angle::NonCopyable
UINT offset); UINT offset);
void applyVertexBufferChanges(); void applyVertexBufferChanges();
bool setPrimitiveTopologyInternal(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology); bool setPrimitiveTopologyInternal(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology);
void syncPrimitiveTopology(const gl::State &glState, void syncPrimitiveTopology(const gl::State &glState, gl::PrimitiveMode currentDrawMode);
ProgramD3D *programD3D,
gl::PrimitiveMode currentDrawMode);
// Not handled by an internal dirty bit because it isn't synced on drawArrays calls. // Not handled by an internal dirty bit because it isn't synced on drawArrays calls.
gl::Error applyIndexBuffer(const gl::Context *context, gl::Error applyIndexBuffer(const gl::Context *context,
...@@ -575,6 +574,11 @@ class StateManager11 final : angle::NonCopyable ...@@ -575,6 +574,11 @@ class StateManager11 final : angle::NonCopyable
Serial mAppliedTFSerial; Serial mAppliedTFSerial;
Serial mEmptySerial; Serial mEmptySerial;
// These objects are cached to avoid having to query the impls.
ProgramD3D *mProgramD3D;
VertexArray11 *mVertexArray11;
Framebuffer11 *mFramebuffer11;
}; };
} // namespace rx } // namespace rx
......
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