Commit 1fc354fa by Jamie Madill Committed by Commit Bot

Re-land: "Vulkan: Forward RenderBuffer/Surface dirty messages."

Re-land fixes ASSERT on Android GLES. Previously we were only forwarding Texture staging changes to the Framebuffer for re-sync. We could miss out on clears that were staged in Surfaces and Renderbuffer attachments. Complete the chain by making the SurfaceVk and RenderbufferVk forward notifications from the VkImage. Bug: angleproject:4517 Change-Id: I91d31213b115a58546b574caa574eebbb098266c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2159294Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 0e1798d6
......@@ -195,7 +195,7 @@ class FramebufferAttachment final
};
// A base class for objects that FBO Attachments may point to.
class FramebufferAttachmentObject : public angle::Subject
class FramebufferAttachmentObject : public angle::Subject, public angle::ObserverInterface
{
public:
FramebufferAttachmentObject();
......
......@@ -49,6 +49,8 @@ const Display *DisplayFromContext(const gl::Context *context)
{
return (context ? context->getDisplay() : nullptr);
}
angle::SubjectIndex kExternalImageImplSubjectIndex = 0;
} // anonymous namespace
ImageSibling::ImageSibling() : FramebufferAttachmentObject(), mSourcesOf(), mTargetOf() {}
......@@ -145,8 +147,11 @@ ExternalImageSibling::ExternalImageSibling(rx::EGLImplFactory *factory,
EGLenum target,
EGLClientBuffer buffer,
const AttributeMap &attribs)
: mImplementation(factory->createExternalImageSibling(context, target, buffer, attribs))
{}
: mImplementation(factory->createExternalImageSibling(context, target, buffer, attribs)),
mImplObserverBinding(this, kExternalImageImplSubjectIndex)
{
mImplObserverBinding.bind(mImplementation.get());
}
ExternalImageSibling::~ExternalImageSibling() = default;
......@@ -211,6 +216,12 @@ rx::ExternalImageSiblingImpl *ExternalImageSibling::getImplementation() const
return mImplementation.get();
}
void ExternalImageSibling::onSubjectStateChange(angle::SubjectIndex index,
angle::SubjectMessage message)
{
onStateChange(message);
}
rx::FramebufferAttachmentObjectImpl *ExternalImageSibling::getAttachmentImpl() const
{
return mImplementation.get();
......
......@@ -38,7 +38,7 @@ class Display;
// Only currently Renderbuffers and Textures can be bound with images. This makes the relationship
// explicit, and also ensures that an image sibling can determine if it's been initialized or not,
// which is important for the robust resource init extension with Textures and EGLImages.
class ImageSibling : public gl::FramebufferAttachmentObject, public angle::ObserverInterface
class ImageSibling : public gl::FramebufferAttachmentObject
{
public:
ImageSibling();
......@@ -52,12 +52,6 @@ class ImageSibling : public gl::FramebufferAttachmentObject, public angle::Obser
GLenum binding,
const gl::ImageIndex &imageIndex) const override;
// ObserverInterface implementation
void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override
{
// default to no-op.
}
protected:
// Set the image target of this sibling
void setTargetImage(const gl::Context *context, egl::Image *imageTarget);
......@@ -117,7 +111,11 @@ class ExternalImageSibling : public ImageSibling
rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
private:
// ObserverInterface implementation.
void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
std::unique_ptr<rx::ExternalImageSiblingImpl> mImplementation;
angle::ObserverBinding mImplObserverBinding;
};
struct ImageState : private angle::NonCopyable
......
......@@ -22,6 +22,11 @@
namespace gl
{
namespace
{
angle::SubjectIndex kRenderbufferImplSubjectIndex = 0;
} // namespace
// RenderbufferState implementation.
RenderbufferState::RenderbufferState()
: mWidth(0), mHeight(0), mFormat(GL_RGBA4), mSamples(0), mInitState(InitState::MayNeedInit)
......@@ -67,8 +72,11 @@ Renderbuffer::Renderbuffer(rx::GLImplFactory *implFactory, RenderbufferID id)
: RefCountObject(implFactory->generateSerial(), id),
mState(),
mImplementation(implFactory->createRenderbuffer(mState)),
mLabel()
{}
mLabel(),
mImplObserverBinding(this, kRenderbufferImplSubjectIndex)
{
mImplObserverBinding.bind(mImplementation.get());
}
void Renderbuffer::onDestroy(const Context *context)
{
......@@ -305,4 +313,10 @@ angle::Result Renderbuffer::getRenderbufferImage(const Context *context,
return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type,
pixels);
}
void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
ASSERT(message == angle::SubjectMessage::SubjectChanged);
onStateChange(angle::SubjectMessage::ContentsChanged);
}
} // namespace gl
......@@ -127,12 +127,16 @@ class Renderbuffer final : public RefCountObject<RenderbufferID>,
void *pixels) const;
private:
// ObserverInterface implementation.
void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
RenderbufferState mState;
std::unique_ptr<rx::RenderbufferImpl> mImplementation;
std::string mLabel;
angle::ObserverBinding mImplObserverBinding;
};
} // namespace gl
......
......@@ -24,6 +24,10 @@
namespace egl
{
namespace
{
angle::SubjectIndex kSurfaceImplSubjectIndex = 0;
} // namespace
SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn)
: label(nullptr),
......@@ -74,7 +78,8 @@ Surface::Surface(EGLint surfaceType,
mTexture(nullptr),
mColorFormat(config->renderTargetFormat),
mDSFormat(config->depthStencilFormat),
mInitState(gl::InitState::Initialized)
mInitState(gl::InitState::Initialized),
mImplObserverBinding(this, kSurfaceImplSubjectIndex)
{
mPostSubBufferRequested =
(attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
......@@ -205,6 +210,8 @@ Error Surface::initialize(const Display *display)
mState.supportedTimestamps = mImplementation->getSupportedTimestamps();
}
mImplObserverBinding.bind(mImplementation);
return NoError();
}
......@@ -579,6 +586,12 @@ Error Surface::getFrameTimestamps(EGLuint64KHR frameId,
return mImplementation->getFrameTimestamps(frameId, numTimestamps, timestamps, values);
}
void Surface::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
ASSERT(message == angle::SubjectMessage::SubjectChanged && index == kSurfaceImplSubjectIndex);
onStateChange(angle::SubjectMessage::ContentsChanged);
}
WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
const egl::Config *config,
EGLNativeWindowType window,
......
......@@ -232,7 +232,11 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
void postSwap(const gl::Context *context);
Error releaseRef(const Display *display);
// ObserverInterface implementation.
void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
gl::InitState mInitState;
angle::ObserverBinding mImplObserverBinding;
};
class WindowSurface final : public Surface
......
......@@ -23,11 +23,11 @@ namespace rx
{
class FramebufferAttachmentRenderTarget;
class FramebufferAttachmentObjectImpl : angle::NonCopyable
class FramebufferAttachmentObjectImpl : public angle::Subject
{
public:
FramebufferAttachmentObjectImpl() {}
virtual ~FramebufferAttachmentObjectImpl() {}
~FramebufferAttachmentObjectImpl() override {}
virtual angle::Result getAttachmentRenderTarget(const gl::Context *context,
GLenum binding,
......
......@@ -41,7 +41,7 @@ namespace rx
{
class ContextImpl;
class TextureImpl : public FramebufferAttachmentObjectImpl, public angle::Subject
class TextureImpl : public FramebufferAttachmentObjectImpl
{
public:
TextureImpl(const gl::TextureState &state);
......
......@@ -17,8 +17,16 @@
namespace rx
{
namespace
{
angle::SubjectIndex kRenderbufferImageSubjectIndex = 0;
} // namespace
RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state)
: RenderbufferImpl(state), mOwnsImage(false), mImage(nullptr)
: RenderbufferImpl(state),
mOwnsImage(false),
mImage(nullptr),
mImageObserverBinding(this, kRenderbufferImageSubjectIndex)
{}
RenderbufferVk::~RenderbufferVk() {}
......@@ -61,6 +69,7 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context,
{
mImage = new vk::ImageHelper();
mOwnsImage = true;
mImageObserverBinding.bind(mImage);
}
const angle::Format &textureFormat = vkFormat.actualImageFormat();
......@@ -112,6 +121,7 @@ angle::Result RenderbufferVk::setStorageEGLImageTarget(const gl::Context *contex
ImageVk *imageVk = vk::GetImpl(image);
mImage = imageVk->getImage();
mOwnsImage = false;
mImageObserverBinding.bind(mImage);
const vk::Format &vkFormat = renderer->getFormat(image->getFormat().info->sizedInternalFormat);
const angle::Format &textureFormat = vkFormat.actualImageFormat();
......@@ -173,6 +183,7 @@ void RenderbufferVk::releaseAndDeleteImage(ContextVk *contextVk)
{
releaseImage(contextVk);
SafeDelete(mImage);
mImageObserverBinding.bind(nullptr);
}
void RenderbufferVk::releaseImage(ContextVk *contextVk)
......@@ -187,6 +198,7 @@ void RenderbufferVk::releaseImage(ContextVk *contextVk)
else
{
mImage = nullptr;
mImageObserverBinding.bind(nullptr);
}
mImageViews.release(renderer);
......@@ -226,4 +238,13 @@ angle::Result RenderbufferVk::getRenderbufferImage(const gl::Context *context,
return mImage->readPixelsForGetImage(contextVk, packState, packBuffer, 0, 0, format, type,
pixels);
}
void RenderbufferVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
ASSERT(index == kRenderbufferImageSubjectIndex &&
message == angle::SubjectMessage::SubjectChanged);
// Forward the notification to the parent class that the staging buffer changed.
onStateChange(angle::SubjectMessage::SubjectChanged);
}
} // namespace rx
......@@ -17,7 +17,7 @@
namespace rx
{
class RenderbufferVk : public RenderbufferImpl
class RenderbufferVk : public RenderbufferImpl, public angle::ObserverInterface
{
public:
RenderbufferVk(const gl::RenderbufferState &state);
......@@ -70,10 +70,15 @@ class RenderbufferVk : public RenderbufferImpl
const gl::InternalFormat &getImplementationSizedFormat() const;
// We monitor the staging buffer for changes. This handles staged data from outside this class.
void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
bool mOwnsImage;
vk::ImageHelper *mImage;
vk::ImageViewHelper mImageViews;
RenderTargetVk mRenderTarget;
angle::ObserverBinding mImageObserverBinding;
};
} // namespace rx
......
......@@ -27,6 +27,8 @@ namespace rx
namespace
{
angle::SubjectIndex kAnySurfaceImageSubjectIndex = 0;
GLint GetSampleCount(const egl::Config *config)
{
GLint samples = 1;
......@@ -137,7 +139,17 @@ angle::Result SurfaceVk::getAttachmentRenderTarget(const gl::Context *context,
return angle::Result::Continue;
}
OffscreenSurfaceVk::AttachmentImage::AttachmentImage() {}
void SurfaceVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
// Forward the notification to parent class that the staging buffer changed.
onStateChange(angle::SubjectMessage::SubjectChanged);
}
OffscreenSurfaceVk::AttachmentImage::AttachmentImage(SurfaceVk *surfaceVk)
: imageObserverBinding(surfaceVk, kAnySurfaceImageSubjectIndex)
{
imageObserverBinding.bind(&image);
}
OffscreenSurfaceVk::AttachmentImage::~AttachmentImage() = default;
......@@ -217,7 +229,9 @@ void OffscreenSurfaceVk::AttachmentImage::destroy(const egl::Display *display)
OffscreenSurfaceVk::OffscreenSurfaceVk(const egl::SurfaceState &surfaceState)
: SurfaceVk(surfaceState),
mWidth(mState.attributes.getAsInt(EGL_WIDTH, 0)),
mHeight(mState.attributes.getAsInt(EGL_HEIGHT, 0))
mHeight(mState.attributes.getAsInt(EGL_HEIGHT, 0)),
mColorAttachment(this),
mDepthStencilAttachment(this)
{
mColorRenderTarget.init(&mColorAttachment.image, &mColorAttachment.imageViews, 0, 0);
mDepthStencilRenderTarget.init(&mDepthStencilAttachment.image,
......@@ -451,12 +465,16 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState, EGLNativ
mPreTransform(VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR),
mCompositeAlpha(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR),
mCurrentSwapHistoryIndex(0),
mCurrentSwapchainImageIndex(0)
mCurrentSwapchainImageIndex(0),
mDepthStencilImageBinding(this, kAnySurfaceImageSubjectIndex),
mColorImageMSBinding(this, kAnySurfaceImageSubjectIndex)
{
// Initialize the color render target with the multisampled targets. If not multisampled, the
// render target will be updated to refer to a swapchain image on every acquire.
mColorRenderTarget.init(&mColorImageMS, &mColorImageMSViews, 0, 0);
mDepthStencilRenderTarget.init(&mDepthStencilImage, &mDepthStencilImageViews, 0, 0);
mDepthStencilImageBinding.bind(&mDepthStencilImage);
mColorImageMSBinding.bind(&mColorImageMS);
}
WindowSurfaceVk::~WindowSurfaceVk()
......@@ -781,7 +799,25 @@ static VkColorSpaceKHR MapEglColorSpaceToVkColorSpace(EGLenum EGLColorspace)
angle::Result WindowSurfaceVk::resizeSwapchainImages(vk::Context *context, uint32_t imageCount)
{
mSwapchainImages.resize(imageCount);
if (static_cast<size_t>(imageCount) != mSwapchainImages.size())
{
mSwapchainImageBindings.clear();
mSwapchainImages.resize(imageCount);
// Update the image bindings. Because the observer binding class uses raw pointers we
// need to first ensure the entire image vector is fully allocated before binding the
// subject and observer together.
for (uint32_t index = 0; index < imageCount; ++index)
{
mSwapchainImageBindings.push_back(
angle::ObserverBinding(this, kAnySurfaceImageSubjectIndex));
}
for (uint32_t index = 0; index < imageCount; ++index)
{
mSwapchainImageBindings[index].bind(&mSwapchainImages[index].image);
}
}
// At this point, if there was a previous swapchain, the previous present semaphores have all
// been moved to mOldSwapchains to be scheduled for destruction, so all semaphore handles in
......@@ -996,6 +1032,8 @@ void WindowSurfaceVk::releaseSwapchainImages(ContextVk *contextVk)
contextVk->addGarbage(&mFramebufferMS);
}
mSwapchainImageBindings.clear();
for (SwapchainImage &swapchainImage : mSwapchainImages)
{
// We don't own the swapchain image handles, so we just remove our reference to it.
......
......@@ -20,7 +20,7 @@ namespace rx
{
class RendererVk;
class SurfaceVk : public SurfaceImpl
class SurfaceVk : public SurfaceImpl, public angle::ObserverInterface
{
public:
angle::Result getAttachmentRenderTarget(const gl::Context *context,
......@@ -33,6 +33,9 @@ class SurfaceVk : public SurfaceImpl
SurfaceVk(const egl::SurfaceState &surfaceState);
~SurfaceVk() override;
// We monitor the staging buffer for changes. This handles staged data from outside this class.
void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
RenderTargetVk mColorRenderTarget;
RenderTargetVk mDepthStencilRenderTarget;
};
......@@ -78,7 +81,7 @@ class OffscreenSurfaceVk : public SurfaceVk
protected:
struct AttachmentImage final : angle::NonCopyable
{
AttachmentImage();
AttachmentImage(SurfaceVk *surfaceVk);
~AttachmentImage();
angle::Result initialize(DisplayVk *displayVk,
......@@ -98,6 +101,7 @@ class OffscreenSurfaceVk : public SurfaceVk
vk::ImageHelper image;
vk::ImageViewHelper imageViews;
angle::ObserverBinding imageObserverBinding;
};
virtual angle::Result initializeImpl(DisplayVk *displayVk);
......@@ -293,6 +297,7 @@ class WindowSurfaceVk : public SurfaceVk
std::vector<impl::SwapchainCleanupData> mOldSwapchains;
std::vector<impl::SwapchainImage> mSwapchainImages;
std::vector<angle::ObserverBinding> mSwapchainImageBindings;
vk::Semaphore mAcquireImageSemaphore;
uint32_t mCurrentSwapchainImageIndex;
......@@ -301,10 +306,12 @@ class WindowSurfaceVk : public SurfaceVk
// Depth/stencil image. Possibly multisampled.
vk::ImageHelper mDepthStencilImage;
vk::ImageViewHelper mDepthStencilImageViews;
angle::ObserverBinding mDepthStencilImageBinding;
// Multisample color image, view and framebuffer, if multisampling enabled.
vk::ImageHelper mColorImageMS;
vk::ImageViewHelper mColorImageMSViews;
angle::ObserverBinding mColorImageMSBinding;
vk::Framebuffer mFramebufferMS;
};
......
......@@ -40,7 +40,7 @@ constexpr VkImageUsageFlags kTransferStagingImageFlags =
constexpr VkFormatFeatureFlags kBlitFeatureFlags =
VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
constexpr angle::SubjectIndex kStagingBufferSubjectIndex = 0;
constexpr angle::SubjectIndex kTextureImageSubjectIndex = 0;
bool CanCopyWithTransfer(RendererVk *renderer,
const vk::Format &srcFormat,
......@@ -115,7 +115,7 @@ TextureVk::TextureVk(const gl::TextureState &state, RendererVk *renderer)
mImage(nullptr),
mStagingBufferInitialSize(vk::kStagingBufferSize),
mImageUsageFlags(0),
mStagingBufferObserverBinding(this, kStagingBufferSubjectIndex)
mImageObserverBinding(this, kTextureImageSubjectIndex)
{}
TextureVk::~TextureVk() = default;
......@@ -879,7 +879,7 @@ void TextureVk::releaseAndDeleteImage(ContextVk *contextVk)
{
releaseImage(contextVk);
releaseStagingBuffer(contextVk);
mStagingBufferObserverBinding.bind(nullptr);
mImageObserverBinding.bind(nullptr);
SafeDelete(mImage);
}
}
......@@ -924,7 +924,7 @@ void TextureVk::setImageHelper(ContextVk *contextVk,
{
ASSERT(mImage == nullptr);
mStagingBufferObserverBinding.bind(imageHelper);
mImageObserverBinding.bind(imageHelper);
mOwnsImage = selfOwned;
mImageNativeType = imageType;
......@@ -1686,7 +1686,7 @@ void TextureVk::releaseImage(ContextVk *contextVk)
}
else
{
mStagingBufferObserverBinding.bind(nullptr);
mImageObserverBinding.bind(nullptr);
mImage = nullptr;
}
}
......@@ -1852,9 +1852,9 @@ const vk::Format &TextureVk::getBaseLevelFormat(RendererVk *renderer) const
void TextureVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
ASSERT(index == kStagingBufferSubjectIndex && message == angle::SubjectMessage::SubjectChanged);
ASSERT(index == kTextureImageSubjectIndex && message == angle::SubjectMessage::SubjectChanged);
// Forward the notification to vk::Texture that the staging buffer changed.
// Forward the notification to the parent that the staging buffer changed.
onStateChange(angle::SubjectMessage::SubjectChanged);
}
} // namespace rx
......@@ -430,7 +430,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
// The created vkImage usage flag.
VkImageUsageFlags mImageUsageFlags;
angle::ObserverBinding mStagingBufferObserverBinding;
angle::ObserverBinding mImageObserverBinding;
};
} // 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