Vulkan: Fix EGL Surface robust init.

The error here was related to using a single cache variable for the
robust init setting for all the surfaces in a DisplayVk. Fix this by
passing down the robust init setting from the SurfaceVk to image init.

Bug: angleproject:5274
Change-Id: I9bc9c20990268d1d5166411fb53f8f2593fd1971
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2510694
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Jamie Madill
2020-10-30 17:03:36 -04:00
committed by Commit Bot
parent 6c618ce31c
commit 97843bda84
20 changed files with 267 additions and 129 deletions

View File

@@ -44,6 +44,11 @@ SurfaceState::~SurfaceState()
delete config;
}
bool SurfaceState::isRobustResourceInitEnabled() const
{
return attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE;
}
Surface::Surface(EGLint surfaceType,
const egl::Config *config,
const AttributeMap &attributes,

View File

@@ -48,6 +48,8 @@ struct SurfaceState final : private angle::NonCopyable
SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn);
~SurfaceState();
bool isRobustResourceInitEnabled() const;
EGLLabelKHR label;
const egl::Config *config;
AttributeMap attributes;

View File

@@ -469,12 +469,6 @@ CommandProcessor::CommandProcessor(RendererVk *renderer)
CommandProcessor::~CommandProcessor() = default;
bool CommandProcessor::isRobustResourceInitEnabled() const
{
// Unused for worker thread, just return false.
return false;
}
vk::Error CommandProcessor::getAndClearPendingError()
{
std::lock_guard<std::mutex> queueLock(mErrorMutex);

View File

@@ -215,8 +215,6 @@ class CommandProcessor : public vk::Context
const char *function,
unsigned int line) override;
bool isRobustResourceInitEnabled() const override;
// Entry point for command processor thread, calls processTasksImpl to do the
// work. called by RendererVk::initialization on main thread
void processTasks();

View File

@@ -641,7 +641,7 @@ class ContextVk : public ContextImpl, public vk::Context
const ProgramExecutableVk *getExecutable() const { return mExecutable; }
ProgramExecutableVk *getExecutable() { return mExecutable; }
bool isRobustResourceInitEnabled() const override;
bool isRobustResourceInitEnabled() const;
// occlusion query
void beginOcclusionQuery(QueryVk *queryVk);

View File

@@ -26,8 +26,7 @@ DisplayVk::DisplayVk(const egl::DisplayState &state)
: DisplayImpl(state),
vk::Context(new RendererVk()),
mScratchBuffer(1000u),
mSavedError({VK_SUCCESS, "", "", 0}),
mHasSurfaceWithRobustInit(false)
mSavedError({VK_SUCCESS, "", "", 0})
{}
DisplayVk::~DisplayVk()
@@ -114,22 +113,12 @@ SurfaceImpl *DisplayVk::createWindowSurface(const egl::SurfaceState &state,
EGLNativeWindowType window,
const egl::AttributeMap &attribs)
{
if (attribs.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE)
{
mHasSurfaceWithRobustInit = true;
}
return createWindowSurfaceVk(state, window);
}
SurfaceImpl *DisplayVk::createPbufferSurface(const egl::SurfaceState &state,
const egl::AttributeMap &attribs)
{
if (attribs.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE)
{
mHasSurfaceWithRobustInit = true;
}
ASSERT(mRenderer);
return new OffscreenSurfaceVk(state, mRenderer);
}
@@ -299,12 +288,6 @@ void DisplayVk::populateFeatureList(angle::FeatureList *features)
mRenderer->getFeatures().populateFeatureList(features);
}
bool DisplayVk::isRobustResourceInitEnabled() const
{
// We return true if any surface was created with robust resource init enabled.
return mHasSurfaceWithRobustInit;
}
void ShareGroupVk::onDestroy(const egl::Display *display)
{
DisplayVk *displayVk = vk::GetImpl(display);

View File

@@ -124,8 +124,6 @@ class DisplayVk : public DisplayImpl, public vk::Context
void populateFeatureList(angle::FeatureList *features) override;
bool isRobustResourceInitEnabled() const override;
ShareGroupImpl *createShareGroup() override;
protected:
@@ -141,7 +139,6 @@ class DisplayVk : public DisplayImpl, public vk::Context
mutable angle::ScratchBuffer mScratchBuffer;
vk::Error mSavedError;
bool mHasSurfaceWithRobustInit;
};
} // namespace rx

View File

@@ -1575,9 +1575,9 @@ angle::Result FramebufferVk::updateColorAttachment(const gl::Context *context,
updateActiveColorMasks(colorIndexGL, actualFormat.redBits > 0, actualFormat.greenBits > 0,
actualFormat.blueBits > 0, actualFormat.alphaBits > 0);
const angle::Format &sourceFormat = renderTarget->getImageFormat().intendedFormat();
mEmulatedAlphaAttachmentMask.set(colorIndexGL,
sourceFormat.alphaBits == 0 && actualFormat.alphaBits > 0);
const angle::Format &intendedFormat = renderTarget->getImageFormat().intendedFormat();
mEmulatedAlphaAttachmentMask.set(
colorIndexGL, intendedFormat.alphaBits == 0 && actualFormat.alphaBits > 0);
contextVk->updateColorMasks(context->getState().getBlendStateExt());

View File

@@ -204,11 +204,11 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk,
// ANGLE_external_objects_flags allows create flags to be specified by the application instead
// of getting defaulted to zero. Note that the GL enum values constituting the bits of
// |createFlags| are identical to their corresponding Vulkan value.
ANGLE_TRY(image->initExternal(contextVk, type, vkExtents, vkFormat, 1, imageUsageFlags,
createFlags, vk::ImageLayout::Undefined,
&externalMemoryImageCreateInfo, gl::LevelIndex(0),
gl::LevelIndex(static_cast<uint32_t>(levels) - 1),
static_cast<uint32_t>(levels), layerCount));
ANGLE_TRY(image->initExternal(
contextVk, type, vkExtents, vkFormat, 1, imageUsageFlags, createFlags,
vk::ImageLayout::Undefined, &externalMemoryImageCreateInfo, gl::LevelIndex(0),
gl::LevelIndex(static_cast<uint32_t>(levels) - 1), static_cast<uint32_t>(levels),
layerCount, contextVk->isRobustResourceInitEnabled()));
VkMemoryRequirements externalMemoryRequirements;
image->getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements);

View File

@@ -105,13 +105,16 @@ angle::Result OverlayVk::createFont(ContextVk *contextVk)
ANGLE_TRY(fontDataBuffer.get().flush(renderer, 0, fontDataBuffer.get().getSize()));
fontDataBuffer.get().unmap(renderer);
// Don't use robust resource init for overlay widgets.
bool useRobustInit = false;
// Create the font image.
ANGLE_TRY(
mFontImage.init(contextVk, gl::TextureType::_2D,
VkExtent3D{gl::overlay::kFontImageWidth, gl::overlay::kFontImageHeight, 1},
renderer->getFormat(angle::FormatID::R8_UNORM), 1,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
gl::LevelIndex(0), gl::LevelIndex(0), 1, gl::overlay::kFontCount));
ANGLE_TRY(mFontImage.init(
contextVk, gl::TextureType::_2D,
VkExtent3D{gl::overlay::kFontImageWidth, gl::overlay::kFontImageHeight, 1},
renderer->getFormat(angle::FormatID::R8_UNORM), 1,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, gl::LevelIndex(0),
gl::LevelIndex(0), 1, gl::overlay::kFontCount, useRobustInit));
ANGLE_TRY(mFontImage.initMemory(contextVk, renderer->getMemoryProperties(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
ANGLE_TRY(mFontImage.initImageView(contextVk, gl::TextureType::_2DArray,
@@ -176,10 +179,13 @@ angle::Result OverlayVk::cullWidgets(ContextVk *contextVk)
UnsignedCeilDivide(mPresentImageExtent.width, mSubgroupSize[0]),
UnsignedCeilDivide(mPresentImageExtent.height, mSubgroupSize[1]), 1};
// Don't use robust resource init for overlay widgets.
bool useRobustInit = false;
ANGLE_TRY(mCulledWidgets.init(contextVk, gl::TextureType::_2D, culledWidgetsExtent,
renderer->getFormat(angle::FormatID::R32G32_UINT), 1,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
gl::LevelIndex(0), gl::LevelIndex(0), 1, 1));
gl::LevelIndex(0), gl::LevelIndex(0), 1, 1, useRobustInit));
ANGLE_TRY(mCulledWidgets.initMemory(contextVk, renderer->getMemoryProperties(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
ANGLE_TRY(mCulledWidgets.initImageView(contextVk, gl::TextureType::_2D,

View File

@@ -97,9 +97,11 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context,
const uint32_t imageSamples = isRenderToTexture ? 1 : samples;
bool robustInit = contextVk->isRobustResourceInitEnabled();
VkExtent3D extents = {static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1u};
ANGLE_TRY(mImage->init(contextVk, gl::TextureType::_2D, extents, vkFormat, imageSamples, usage,
gl::LevelIndex(0), gl::LevelIndex(0), 1, 1));
gl::LevelIndex(0), gl::LevelIndex(0), 1, 1, robustInit));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(mImage->initMemory(contextVk, renderer->getMemoryProperties(), flags));
@@ -112,7 +114,8 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context,
mMultisampledImageViews.init(renderer);
ANGLE_TRY(mMultisampledImage.initImplicitMultisampledRenderToTexture(
contextVk, renderer->getMemoryProperties(), gl::TextureType::_2D, samples, *mImage));
contextVk, renderer->getMemoryProperties(), gl::TextureType::_2D, samples, *mImage,
robustInit));
mRenderTarget.init(&mMultisampledImage, &mMultisampledImageViews, mImage, &mImageViews,
gl::LevelIndex(0), 0, RenderTargetTransience::MultisampledTransient);

View File

@@ -160,7 +160,8 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initialize(DisplayVk *display
EGLint width,
EGLint height,
const vk::Format &vkFormat,
GLint samples)
GLint samples,
bool isRobustResourceInitEnabled)
{
RendererVk *renderer = displayVk->getRenderer();
@@ -172,7 +173,7 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initialize(DisplayVk *display
VkExtent3D extents = {std::max(static_cast<uint32_t>(width), 1u),
std::max(static_cast<uint32_t>(height), 1u), 1u};
ANGLE_TRY(image.init(displayVk, gl::TextureType::_2D, extents, vkFormat, samples, usage,
gl::LevelIndex(0), gl::LevelIndex(0), 1, 1));
gl::LevelIndex(0), gl::LevelIndex(0), 1, 1, isRobustResourceInitEnabled));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(image.initMemory(displayVk, renderer->getMemoryProperties(), flags));
@@ -188,7 +189,8 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initializeWithExternalMemory(
EGLint height,
const vk::Format &vkFormat,
GLint samples,
void *buffer)
void *buffer,
bool isRobustResourceInitEnabled)
{
RendererVk *renderer = displayVk->getRenderer();
@@ -202,7 +204,7 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initializeWithExternalMemory(
VkExtent3D extents = {std::max(static_cast<uint32_t>(width), 1u),
std::max(static_cast<uint32_t>(height), 1u), 1u};
ANGLE_TRY(image.init(displayVk, gl::TextureType::_2D, extents, vkFormat, samples, usage,
gl::LevelIndex(0), gl::LevelIndex(0), 1, 1));
gl::LevelIndex(0), gl::LevelIndex(0), 1, 1, isRobustResourceInitEnabled));
VkImportMemoryHostPointerInfoEXT importMemoryHostPointerInfo = {};
importMemoryHostPointerInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT;
@@ -267,10 +269,13 @@ angle::Result OffscreenSurfaceVk::initializeImpl(DisplayVk *displayVk)
GLint samples = GetSampleCount(mState.config);
ANGLE_VK_CHECK(displayVk, samples > 0, VK_ERROR_INITIALIZATION_FAILED);
bool robustInit = mState.isRobustResourceInitEnabled();
if (config->renderTargetFormat != GL_NONE)
{
ANGLE_TRY(mColorAttachment.initialize(
displayVk, mWidth, mHeight, renderer->getFormat(config->renderTargetFormat), samples));
ANGLE_TRY(mColorAttachment.initialize(displayVk, mWidth, mHeight,
renderer->getFormat(config->renderTargetFormat),
samples, robustInit));
mColorRenderTarget.init(&mColorAttachment.image, &mColorAttachment.imageViews, nullptr,
nullptr, gl::LevelIndex(0), 0, RenderTargetTransience::Default);
}
@@ -278,7 +283,8 @@ angle::Result OffscreenSurfaceVk::initializeImpl(DisplayVk *displayVk)
if (config->depthStencilFormat != GL_NONE)
{
ANGLE_TRY(mDepthStencilAttachment.initialize(
displayVk, mWidth, mHeight, renderer->getFormat(config->depthStencilFormat), samples));
displayVk, mWidth, mHeight, renderer->getFormat(config->depthStencilFormat), samples,
robustInit));
mDepthStencilRenderTarget.init(&mDepthStencilAttachment.image,
&mDepthStencilAttachment.imageViews, nullptr, nullptr,
gl::LevelIndex(0), 0, RenderTargetTransience::Default);
@@ -994,12 +1000,15 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
VkExtent3D vkExtents;
gl_vk::GetExtent(rotatedExtents, &vkExtents);
bool robustInit = mState.isRobustResourceInitEnabled();
if (samples > 1)
{
const VkImageUsageFlags usage = kSurfaceVkColorImageUsageFlags;
ANGLE_TRY(mColorImageMS.init(context, gl::TextureType::_2D, vkExtents, format, samples,
usage, gl::LevelIndex(0), gl::LevelIndex(0), 1, 1));
usage, gl::LevelIndex(0), gl::LevelIndex(0), 1, 1,
robustInit));
ANGLE_TRY(mColorImageMS.initMemory(context, renderer->getMemoryProperties(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
@@ -1014,7 +1023,8 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
for (uint32_t imageIndex = 0; imageIndex < imageCount; ++imageIndex)
{
SwapchainImage &member = mSwapchainImages[imageIndex];
member.image.init2DWeakReference(context, swapchainImages[imageIndex], extents, format, 1);
member.image.init2DWeakReference(context, swapchainImages[imageIndex], extents, format, 1,
robustInit);
member.imageViews.init(renderer);
}
@@ -1027,7 +1037,7 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
ANGLE_TRY(mDepthStencilImage.init(context, gl::TextureType::_2D, vkExtents, dsFormat,
samples, dsUsage, gl::LevelIndex(0), gl::LevelIndex(0), 1,
1));
1, robustInit));
ANGLE_TRY(mDepthStencilImage.initMemory(context, renderer->getMemoryProperties(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));

View File

@@ -87,14 +87,16 @@ class OffscreenSurfaceVk : public SurfaceVk
EGLint width,
EGLint height,
const vk::Format &vkFormat,
GLint samples);
GLint samples,
bool isRobustResourceInitEnabled);
angle::Result initializeWithExternalMemory(DisplayVk *displayVk,
EGLint width,
EGLint height,
const vk::Format &vkFormat,
GLint samples,
void *buffer);
void *buffer,
bool isRobustResourceInitEnabled);
void destroy(const egl::Display *display);

View File

@@ -1920,9 +1920,13 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
RendererVk *renderer = contextVk->getRenderer();
mMultisampledImageViews[renderToTextureIndex].init(renderer);
// The MSAA image always comes from the single sampled one, so disable robust init.
bool useRobustInit = false;
// Create the implicit multisampled image.
ANGLE_TRY(multisampledImage->initImplicitMultisampledRenderToTexture(
contextVk, renderer->getMemoryProperties(), mState.getType(), samples, *mImage));
contextVk, renderer->getMemoryProperties(), mState.getType(), samples, *mImage,
useRobustInit));
}
// Don't flush staged updates here. We'll handle that in FramebufferVk so it can defer clears.
@@ -2382,10 +2386,11 @@ angle::Result TextureVk::initImage(ContextVk *contextVk,
gl_vk::GetExtentsAndLayerCount(mState.getType(), extents, &vkExtent, &layerCount);
GLint samples = mState.getBaseLevelDesc().samples ? mState.getBaseLevelDesc().samples : 1;
ANGLE_TRY(mImage->initExternal(
contextVk, mState.getType(), vkExtent, format, samples, mImageUsageFlags, mImageCreateFlags,
vk::ImageLayout::Undefined, nullptr, gl::LevelIndex(mState.getEffectiveBaseLevel()),
gl::LevelIndex(mState.getEffectiveMaxLevel()), levelCount, layerCount));
ANGLE_TRY(mImage->initExternal(contextVk, mState.getType(), vkExtent, format, samples,
mImageUsageFlags, mImageCreateFlags, vk::ImageLayout::Undefined,
nullptr, gl::LevelIndex(mState.getEffectiveBaseLevel()),
gl::LevelIndex(mState.getEffectiveMaxLevel()), levelCount,
layerCount, contextVk->isRobustResourceInitEnabled()));
const VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;

View File

@@ -202,12 +202,16 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
mImage = new vk::ImageHelper();
// disable robust init for this external image.
bool robustInitEnabled = false;
mImage->setTilingMode(imageTilingMode);
ANGLE_TRY(mImage->initExternal(
displayVk, gl::TextureType::_2D, vkExtents,
bufferFormatProperties.format == VK_FORMAT_UNDEFINED ? externalVkFormat : vkFormat, 1,
usage, vk::kVkImageCreateFlagsNone, vk::ImageLayout::ExternalPreInitialized,
&externalMemoryImageCreateInfo, gl::LevelIndex(0), gl::LevelIndex(0), 1, 1));
&externalMemoryImageCreateInfo, gl::LevelIndex(0), gl::LevelIndex(0), 1, 1,
robustInitEnabled));
VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {};
importHardwareBufferInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;

View File

@@ -117,7 +117,7 @@ angle::Result IOSurfaceSurfaceVkMac::initializeImpl(DisplayVk *displayVk)
ANGLE_TRY(mColorAttachment.initializeWithExternalMemory(
displayVk, mWidth, mHeight,
renderer->getFormat(kIOSurfaceFormats[mFormatIndex].nativeSizedInternalFormat), samples,
IOSurfaceGetBaseAddressOfPlane(mIOSurface, mPlane)));
IOSurfaceGetBaseAddressOfPlane(mIOSurface, mPlane), mState.isRobustResourceInitEnabled()));
mColorRenderTarget.init(&mColorAttachment.image, &mColorAttachment.imageViews, nullptr, nullptr,
gl::LevelIndex(0), 0, RenderTargetTransience::Default);

View File

@@ -3230,11 +3230,12 @@ angle::Result ImageHelper::init(Context *context,
gl::LevelIndex baseLevel,
gl::LevelIndex maxLevel,
uint32_t mipLevels,
uint32_t layerCount)
uint32_t layerCount,
bool isRobustResourceInitEnabled)
{
return initExternal(context, textureType, extents, format, samples, usage,
kVkImageCreateFlagsNone, ImageLayout::Undefined, nullptr, baseLevel,
maxLevel, mipLevels, layerCount);
maxLevel, mipLevels, layerCount, isRobustResourceInitEnabled);
}
angle::Result ImageHelper::initExternal(Context *context,
@@ -3249,7 +3250,8 @@ angle::Result ImageHelper::initExternal(Context *context,
gl::LevelIndex baseLevel,
gl::LevelIndex maxLevel,
uint32_t mipLevels,
uint32_t layerCount)
uint32_t layerCount,
bool isRobustResourceInitEnabled)
{
ASSERT(!valid());
ASSERT(!IsAnySubresourceContentDefined(mContentDefined));
@@ -3297,7 +3299,7 @@ angle::Result ImageHelper::initExternal(Context *context,
ANGLE_VK_TRY(context, mImage.init(context->getDevice(), imageInfo));
stageClearIfEmulatedFormat(context);
stageClearIfEmulatedFormat(isRobustResourceInitEnabled);
if (initialLayout != ImageLayout::Undefined)
{
@@ -3625,7 +3627,8 @@ void ImageHelper::init2DWeakReference(Context *context,
VkImage handle,
const gl::Extents &glExtents,
const Format &format,
GLint samples)
GLint samples,
bool isRobustResourceInitEnabled)
{
ASSERT(!valid());
ASSERT(!IsAnySubresourceContentDefined(mContentDefined));
@@ -3641,7 +3644,7 @@ void ImageHelper::init2DWeakReference(Context *context,
mImage.setHandle(handle);
stageClearIfEmulatedFormat(context);
stageClearIfEmulatedFormat(isRobustResourceInitEnabled);
}
angle::Result ImageHelper::init2DStaging(Context *context,
@@ -3695,7 +3698,8 @@ angle::Result ImageHelper::initImplicitMultisampledRenderToTexture(
const MemoryProperties &memoryProperties,
gl::TextureType textureType,
GLint samples,
const ImageHelper &resolveImage)
const ImageHelper &resolveImage,
bool isRobustResourceInitEnabled)
{
ASSERT(!valid());
ASSERT(samples > 1);
@@ -3721,11 +3725,11 @@ angle::Result ImageHelper::initImplicitMultisampledRenderToTexture(
: VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
constexpr VkImageCreateFlags kMultisampledCreateFlags = 0;
ANGLE_TRY(initExternal(context, textureType, resolveImage.getExtents(),
resolveImage.getFormat(), samples, kMultisampledUsageFlags,
kMultisampledCreateFlags, ImageLayout::Undefined, nullptr,
resolveImage.getBaseLevel(), resolveImage.getMaxLevel(),
resolveImage.getLevelCount(), resolveImage.getLayerCount()));
ANGLE_TRY(initExternal(
context, textureType, resolveImage.getExtents(), resolveImage.getFormat(), samples,
kMultisampledUsageFlags, kMultisampledCreateFlags, ImageLayout::Undefined, nullptr,
resolveImage.getBaseLevel(), resolveImage.getMaxLevel(), resolveImage.getLevelCount(),
resolveImage.getLayerCount(), isRobustResourceInitEnabled));
const VkMemoryPropertyFlags kMultisampledMemoryFlags =
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
@@ -4851,10 +4855,10 @@ angle::Result ImageHelper::stageRobustResourceClearWithFormat(ContextVk *context
return angle::Result::Continue;
}
void ImageHelper::stageClearIfEmulatedFormat(Context *context)
void ImageHelper::stageClearIfEmulatedFormat(bool isRobustResourceInitEnabled)
{
// Skip staging extra clears if robust resource init is enabled.
if (!mFormat->hasEmulatedImageChannels() || context->isRobustResourceInitEnabled())
if (!mFormat->hasEmulatedImageChannels() || isRobustResourceInitEnabled)
return;
VkClearValue clearValue;

View File

@@ -1276,7 +1276,8 @@ class ImageHelper final : public Resource, public angle::Subject
gl::LevelIndex baseLevel,
gl::LevelIndex maxLevel,
uint32_t mipLevels,
uint32_t layerCount);
uint32_t layerCount,
bool isRobustResourceInitEnabled);
angle::Result initExternal(Context *context,
gl::TextureType textureType,
const VkExtent3D &extents,
@@ -1289,7 +1290,8 @@ class ImageHelper final : public Resource, public angle::Subject
gl::LevelIndex baseLevel,
gl::LevelIndex maxLevel,
uint32_t mipLevels,
uint32_t layerCount);
uint32_t layerCount,
bool isRobustResourceInitEnabled);
angle::Result initMemory(Context *context,
const MemoryProperties &memoryProperties,
VkMemoryPropertyFlags flags);
@@ -1345,7 +1347,8 @@ class ImageHelper final : public Resource, public angle::Subject
const MemoryProperties &memoryProperties,
gl::TextureType textureType,
GLint samples,
const ImageHelper &resolveImage);
const ImageHelper &resolveImage,
bool isRobustResourceInitEnabled);
// Release the underlining VkImage object for garbage collection.
void releaseImage(RendererVk *renderer);
// Similar to releaseImage, but also notify all contexts in the same share group to stop
@@ -1365,7 +1368,8 @@ class ImageHelper final : public Resource, public angle::Subject
VkImage handle,
const gl::Extents &glExtents,
const Format &format,
GLint samples);
GLint samples,
bool isRobustResourceInitEnabled);
void resetImageWeakReference();
const Image &getImage() const { return mImage; }
@@ -1743,7 +1747,7 @@ class ImageHelper final : public Resource, public angle::Subject
// If the image has emulated channels, we clear them once so as not to leave garbage on those
// channels.
void stageClearIfEmulatedFormat(Context *context);
void stageClearIfEmulatedFormat(bool isRobustResourceInitEnabled);
void clearColor(const VkClearColorValue &color,
LevelIndex baseMipLevelVk,

View File

@@ -174,10 +174,6 @@ class Context : angle::NonCopyable
VkDevice getDevice() const;
RendererVk *getRenderer() const { return mRenderer; }
// This is a special override needed so we can determine if we need to initialize images.
// It corresponds to the EGL or GL extensions depending on the vk::Context type.
virtual bool isRobustResourceInitEnabled() const = 0;
protected:
RendererVk *const mRenderer;
};

View File

@@ -50,37 +50,47 @@ class EGLSurfaceTest : public ANGLETest
mOSWindow->initialize("EGLSurfaceTest", 64, 64);
}
void tearDownContextAndSurface()
{
if (mDisplay == EGL_NO_DISPLAY)
{
return;
}
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (mWindowSurface != EGL_NO_SURFACE)
{
eglDestroySurface(mDisplay, mWindowSurface);
mWindowSurface = EGL_NO_SURFACE;
}
if (mPbufferSurface != EGL_NO_SURFACE)
{
eglDestroySurface(mDisplay, mPbufferSurface);
mPbufferSurface = EGL_NO_SURFACE;
}
if (mContext != EGL_NO_CONTEXT)
{
eglDestroyContext(mDisplay, mContext);
mContext = EGL_NO_CONTEXT;
}
if (mSecondContext != EGL_NO_CONTEXT)
{
eglDestroyContext(mDisplay, mSecondContext);
mSecondContext = EGL_NO_CONTEXT;
}
}
// Release any resources created in the test body
void testTearDown() override
{
tearDownContextAndSurface();
if (mDisplay != EGL_NO_DISPLAY)
{
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (mWindowSurface != EGL_NO_SURFACE)
{
eglDestroySurface(mDisplay, mWindowSurface);
mWindowSurface = EGL_NO_SURFACE;
}
if (mPbufferSurface != EGL_NO_SURFACE)
{
eglDestroySurface(mDisplay, mPbufferSurface);
mPbufferSurface = EGL_NO_SURFACE;
}
if (mContext != EGL_NO_CONTEXT)
{
eglDestroyContext(mDisplay, mContext);
mContext = EGL_NO_CONTEXT;
}
if (mSecondContext != EGL_NO_CONTEXT)
{
eglDestroyContext(mDisplay, mSecondContext);
mSecondContext = EGL_NO_CONTEXT;
}
eglTerminate(mDisplay);
mDisplay = EGL_NO_DISPLAY;
}
@@ -119,29 +129,33 @@ class EGLSurfaceTest : public ANGLETest
ASSERT_EGL_SUCCESS();
}
void initializeContext()
void initializeSingleContext(EGLContext *context)
{
EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, GetParam().majorVersion, EGL_NONE};
mContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
ASSERT_EGL_SUCCESS();
mSecondContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
*context = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
ASSERT_EGL_SUCCESS();
}
void initializeSurface(EGLConfig config)
void initializeContext()
{
initializeSingleContext(&mContext);
initializeSingleContext(&mSecondContext);
}
void initializeSurfaceWithAttribs(EGLConfig config,
const std::vector<EGLint> &additionalAttributes)
{
mConfig = config;
EGLint surfaceType = EGL_NONE;
eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);
std::vector<EGLint> windowAttributes;
windowAttributes.push_back(EGL_NONE);
if (surfaceType & EGL_WINDOW_BIT)
{
std::vector<EGLint> windowAttributes = additionalAttributes;
windowAttributes.push_back(EGL_NONE);
// Create first window surface
mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(),
windowAttributes.data());
@@ -150,8 +164,9 @@ class EGLSurfaceTest : public ANGLETest
if (surfaceType & EGL_PBUFFER_BIT)
{
std::vector<EGLint> pbufferAttributes = additionalAttributes;
// Give pbuffer non-zero dimensions.
std::vector<EGLint> pbufferAttributes;
pbufferAttributes.push_back(EGL_WIDTH);
pbufferAttributes.push_back(64);
pbufferAttributes.push_back(EGL_HEIGHT);
@@ -165,7 +180,13 @@ class EGLSurfaceTest : public ANGLETest
initializeContext();
}
void initializeSurfaceWithDefaultConfig(bool requireWindowSurface)
void initializeSurface(EGLConfig config)
{
std::vector<EGLint> additionalAttributes;
initializeSurfaceWithAttribs(config, additionalAttributes);
}
EGLConfig chooseDefaultConfig(bool requireWindowSurface) const
{
const EGLint configAttributes[] = {EGL_RED_SIZE,
EGL_DONT_CARE,
@@ -187,10 +208,18 @@ class EGLSurfaceTest : public ANGLETest
EGLint configCount;
EGLConfig config;
ASSERT_TRUE(eglChooseConfig(mDisplay, configAttributes, &config, 1, &configCount) ||
(configCount != 1) == EGL_TRUE);
if (eglChooseConfig(mDisplay, configAttributes, &config, 1, &configCount) != EGL_TRUE)
return nullptr;
if (configCount != 1)
return nullptr;
return config;
}
initializeSurface(config);
void initializeSurfaceWithDefaultConfig(bool requireWindowSurface)
{
EGLConfig defaultConfig = chooseDefaultConfig(requireWindowSurface);
ASSERT_NE(defaultConfig, nullptr);
initializeSurface(defaultConfig);
}
GLuint createProgram()
@@ -1162,6 +1191,102 @@ TEST_P(EGLSurfaceTestD3D11, CreateSurfaceWithMSAA)
#endif // ANGLE_ENABLE_D3D11
// Verify switching between a surface with robust resource init and one without still clears alpha.
TEST_P(EGLSurfaceTest, RobustResourceInitAndEmulatedAlpha)
{
// http://anglebug.com/5279
ANGLE_SKIP_TEST_IF(IsNVIDIA() && isGLRenderer() && IsLinux());
// http://anglebug.com/5280
ANGLE_SKIP_TEST_IF(IsAndroid() && IsNexus5X() && isGLESRenderer());
initializeDisplay();
ASSERT_NE(mDisplay, EGL_NO_DISPLAY);
ANGLE_SKIP_TEST_IF(
!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_robust_resource_initialization"));
// Initialize and draw red to a Surface with robust resource init enabled.
constexpr EGLint kRGBAAttributes[] = {EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE};
EGLint configCount = 0;
EGLConfig rgbaConfig = nullptr;
ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kRGBAAttributes, &rgbaConfig, 1, &configCount));
ASSERT_EQ(configCount, 1);
ASSERT_NE(rgbaConfig, nullptr);
std::vector<EGLint> robustInitAttribs;
robustInitAttribs.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE);
robustInitAttribs.push_back(EGL_TRUE);
initializeSurfaceWithAttribs(rgbaConfig, robustInitAttribs);
ASSERT_EGL_SUCCESS();
ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
initializeSingleContext(&mContext);
ASSERT_EGL_SUCCESS();
ASSERT_NE(mContext, EGL_NO_CONTEXT);
eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
ASSERT_EGL_SUCCESS();
eglSwapBuffers(mDisplay, mWindowSurface);
// RGBA robust init setup complete. Draw red and verify.
{
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
glUseProgram(program);
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
eglSwapBuffers(mDisplay, mWindowSurface);
}
tearDownContextAndSurface();
// Create second RGB surface with robust resource disabled.
constexpr EGLint kRGBAttributes[] = {EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 0,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE};
configCount = 0;
EGLConfig rgbConfig = nullptr;
ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kRGBAttributes, &rgbConfig, 1, &configCount));
ASSERT_EQ(configCount, 1);
ASSERT_NE(rgbConfig, nullptr);
initializeSurface(rgbConfig);
ASSERT_EGL_SUCCESS();
ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
initializeSingleContext(&mContext);
ASSERT_EGL_SUCCESS();
ASSERT_NE(mContext, EGL_NO_CONTEXT);
eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
ASSERT_EGL_SUCCESS();
// RGB non-robust init setup complete. Draw red and verify.
{
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
glUseProgram(program);
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
eglSwapBuffers(mDisplay, mWindowSurface);
}
}
} // anonymous namespace
ANGLE_INSTANTIATE_TEST(EGLSurfaceTest,