Commit 9379eed3 by Geoff Lang

GL/D3D: Use texture uploads instead of clearing for robust init.

Chrome uses regular texture uploads on all platforms except OpenGL on Mac to do robust resource init for textures because multiple bugs have been observed with texture corruption. BUG=883276 BUG=882580 BUG=941620 Change-Id: Ie37224e237b8c41bef7f1e557af6d44b7bc26b07 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1682746Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent aed672f7
......@@ -204,6 +204,14 @@ struct WorkaroundsD3D : FeatureSetBase
"On an NVIDIA D3D driver, the return value from RWByteAddressBuffer.InterlockedAdd does "
"not resolve when used in the .yzw components of a RWByteAddressBuffer.Store operation",
&members, "http://anglebug.com/3246"};
// Match chromium's robust resource init behaviour by always prefering to upload texture data
// instead of clearing. Clear calls have been observed to cause texture corruption for some
// formats.
Feature allowClearForRobustResourceInit = {
"allow_clear_for_robust_resource_init", FeatureCategory::D3DWorkarounds,
"Some drivers corrupt texture data when clearing for robust resource initialization.",
&members, "http://crbug.com/941620"};
};
inline WorkaroundsD3D::WorkaroundsD3D() = default;
......
......@@ -732,8 +732,10 @@ angle::Result TextureD3D::initializeContents(const gl::Context *context,
// Fast path: can use a render target clear.
// We don't use the fast path with the zero max lod workaround because it would introduce a race
// between the rendertarget and the staging images.
if (canCreateRenderTargetForImage(index) &&
!mRenderer->getWorkarounds().zeroMaxLodWorkaround.enabled)
const angle::WorkaroundsD3D &workarounds = mRenderer->getWorkarounds();
bool shouldUseClear = (image == nullptr);
if (canCreateRenderTargetForImage(index) && !workarounds.zeroMaxLodWorkaround.enabled &&
(shouldUseClear || workarounds.allowClearForRobustResourceInit.enabled))
{
ANGLE_TRY(ensureRenderTarget(context));
ASSERT(mTexStorage);
......@@ -743,6 +745,8 @@ angle::Result TextureD3D::initializeContents(const gl::Context *context,
return angle::Result::Continue;
}
ASSERT(image != nullptr);
// Slow path: non-renderable texture or the texture levels aren't set up.
const auto &formatInfo = gl::GetSizedInternalFormatInfo(image->getInternalFormat());
......
......@@ -2448,6 +2448,9 @@ void GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
workarounds->selectViewInGeometryShader.enabled =
(deviceCaps.supportsVpRtIndexWriteFromVertexShader == false);
// Never clear for robust resource init. This matches Chrome's texture clearning behaviour.
workarounds->allowClearForRobustResourceInit.enabled = false;
// Call platform hooks for testing overrides.
auto *platform = ANGLEPlatformCurrent();
platform->overrideWorkaroundsD3D(platform, workarounds);
......
......@@ -808,6 +808,9 @@ void GenerateWorkarounds(angle::WorkaroundsD3D *workarounds)
// TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
workarounds->expandIntegerPowExpressions.enabled = true;
// Never clear for robust resource init. This matches Chrome's texture clearning behaviour.
workarounds->allowClearForRobustResourceInit.enabled = false;
// Call platform hooks for testing overrides.
auto *platform = ANGLEPlatformCurrent();
platform->overrideWorkaroundsD3D(platform, workarounds);
......
......@@ -1559,9 +1559,11 @@ angle::Result TextureGL::initializeContents(const gl::Context *context,
StateManagerGL *stateManager = GetStateManagerGL(context);
const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
bool shouldUseClear = !nativegl::SupportsTexImage(getType());
GLenum nativeInternalFormat =
getLevelInfo(imageIndex.getTarget(), imageIndex.getLevelIndex()).nativeInternalFormat;
if (nativegl::SupportsNativeRendering(functions, mState.getType(), nativeInternalFormat))
if ((workarounds.allowClearForRobustResourceInit.enabled || shouldUseClear) &&
nativegl::SupportsNativeRendering(functions, mState.getType(), nativeInternalFormat))
{
BlitGL *blitter = GetBlitGL(context);
......@@ -1578,6 +1580,7 @@ angle::Result TextureGL::initializeContents(const gl::Context *context,
// Either the texture is not renderable or was incomplete when clearing, fall back to a data
// upload
ASSERT(nativegl::SupportsTexImage(getType()));
const gl::ImageDesc &desc = mState.getImageDesc(imageIndex);
const gl::InternalFormat &internalFormatInfo = *desc.format.info;
......@@ -1585,6 +1588,7 @@ angle::Result TextureGL::initializeContents(const gl::Context *context,
unpackState.alignment = 1;
stateManager->setPixelUnpackState(unpackState);
stateManager->bindTexture(getType(), mTextureID);
if (internalFormatInfo.compressed)
{
nativegl::CompressedTexSubImageFormat nativeSubImageFormat =
......
......@@ -275,6 +275,17 @@ struct WorkaroundsGL : angle::FeatureSetBase
"disable_worker_contexts", angle::FeatureCategory::OpenGLWorkarounds,
"Some tests have been seen to fail using worker contexts", &members,
"http://crbug.com/849576"};
// Prefer to do the robust resource init clear using a glClear. Calls to TexSubImage2D on large
// textures can take hundreds of milliseconds because of slow uploads on macOS. Do this only on
// macOS because clears are buggy on other drivers.
// https://crbug.com/848952 (slow uploads on macOS)
// https://crbug.com/883276 (buggy clears on Android)
angle::Feature allowClearForRobustResourceInit = {
"allow_clear_for_robust_resource_init", angle::FeatureCategory::OpenGLWorkarounds,
"Using glClear for robust resource initialization is buggy on some drivers and leads to "
"texture corruption. Default to data uploads except on MacOS where it is very slow.",
&members, "http://crbug.com/883276"};
};
inline WorkaroundsGL::WorkaroundsGL() = default;
......
......@@ -1475,6 +1475,8 @@ void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workaround
// crbug.com/922936
workarounds->disableWorkerContexts.enabled =
(IsWindows() && (IsIntel(vendor) || IsAMD(vendor))) || (IsLinux() && IsNvidia(vendor));
workarounds->allowClearForRobustResourceInit.enabled = IsApple();
}
void ApplyWorkarounds(const FunctionsGL *functions, gl::Workarounds *workarounds)
......@@ -1533,6 +1535,20 @@ bool SupportsNativeRendering(const FunctionsGL *functions,
}
}
bool SupportsTexImage(gl::TextureType type)
{
switch (type)
{
// Multi-sample texture types only support TexStorage data upload
case gl::TextureType::_2DMultisample:
case gl::TextureType::_2DMultisampleArray:
return false;
default:
return true;
}
}
bool UseTexImage2D(gl::TextureType textureType)
{
return textureType == gl::TextureType::_2D || textureType == gl::TextureType::CubeMap ||
......
......@@ -73,6 +73,7 @@ bool SupportsOcclusionQueries(const FunctionsGL *functions);
bool SupportsNativeRendering(const FunctionsGL *functions,
gl::TextureType type,
GLenum internalFormat);
bool SupportsTexImage(gl::TextureType type);
bool UseTexImage2D(gl::TextureType textureType);
bool UseTexImage3D(gl::TextureType textureType);
} // namespace nativegl
......
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