Commit c12f594a by Geoff Lang Committed by Angle LUCI CQ

GL: Chunk uploads of texture data >120kb on Mac.

Mac drivers are hanging and crashing after large glTexSubImage uploads. Chunk those uploads to avoid this problematic path in the driver. Bug: chromium:1181068 Change-Id: I7dca0b8e49420f015ff7830283c14283a0515826 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2928098Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent 1e832ad6
......@@ -554,6 +554,13 @@ struct FeaturesGL : FeatureSetBase
"disable_mutlisampled_render_to_texture", FeatureCategory::OpenGLWorkarounds,
"Many drivers have bugs when using GL_EXT_multisampled_render_to_texture", &members,
"http://anglebug.com/2894"};
// Mac OpenGL drivers often hang when calling glTexSubImage with >120kb of data. Instead, upload
// the data in <120kb chunks.
Feature uploadTextureDataInChunks = {
"chunked_texture_upload", FeatureCategory::OpenGLWorkarounds,
"Upload texture data in <120kb chunks to work around Mac driver hangs and crashes.",
&members, "http://crbug.com/1181068"};
};
inline FeaturesGL::FeaturesGL() = default;
......
......@@ -269,6 +269,8 @@ class ContextGL : public ContextImpl
void setNeedsFlushBeforeDeleteTextures();
void flushIfNecessaryBeforeDeleteTextures();
const gl::Debug &getDebug() const { return mState.getDebug(); }
private:
angle::Result setDrawArraysState(const gl::Context *context,
GLint first,
......
......@@ -187,7 +187,7 @@ angle::Result TextureGL::setImage(const gl::Context *context,
gl::Box area(0, 0, 0, size.width, size.height, size.depth);
return setSubImageRowByRowWorkaround(context, target, level, area, format, type, unpack,
unpackBuffer, pixels);
unpackBuffer, 0, pixels);
}
if (features.unpackLastRowSeparatelyForPaddingInclusion.enabled)
......@@ -335,7 +335,7 @@ angle::Result TextureGL::setSubImage(const gl::Context *context,
unpack.rowLength != 0 && unpack.rowLength < area.width)
{
return setSubImageRowByRowWorkaround(context, target, level, area, format, type, unpack,
unpackBuffer, pixels);
unpackBuffer, 0, pixels);
}
if (features.unpackLastRowSeparatelyForPaddingInclusion.enabled)
......@@ -356,6 +356,13 @@ angle::Result TextureGL::setSubImage(const gl::Context *context,
}
}
if (features.uploadTextureDataInChunks.enabled)
{
constexpr const size_t kMaxUploadChunkSize = (120 * 1024) - 1;
return setSubImageRowByRowWorkaround(context, target, level, area, format, type, unpack,
unpackBuffer, kMaxUploadChunkSize, pixels);
}
if (nativegl::UseTexImage2D(getType()))
{
ASSERT(area.z == 0 && area.depth == 1);
......@@ -385,14 +392,18 @@ angle::Result TextureGL::setSubImageRowByRowWorkaround(const gl::Context *contex
GLenum type,
const gl::PixelUnpackState &unpack,
const gl::Buffer *unpackBuffer,
size_t maxBytesUploadedPerChunk,
const uint8_t *pixels)
{
ContextGL *contextGL = GetImplAs<ContextGL>(context);
const FunctionsGL *functions = GetFunctionsGL(context);
StateManagerGL *stateManager = GetStateManagerGL(context);
ContextGL *contextGL = GetImplAs<ContextGL>(context);
const FunctionsGL *functions = GetFunctionsGL(context);
StateManagerGL *stateManager = GetStateManagerGL(context);
const angle::FeaturesGL &features = GetFeaturesGL(context);
gl::PixelUnpackState directUnpack;
directUnpack.alignment = 1;
gl::PixelUnpackState directUnpack = unpack;
directUnpack.skipRows = 0;
directUnpack.skipPixels = 0;
directUnpack.skipImages = 0;
ANGLE_TRY(stateManager->setPixelUnpackState(context, directUnpack));
ANGLE_TRY(stateManager->setPixelUnpackBuffer(context, unpackBuffer));
......@@ -409,33 +420,48 @@ angle::Result TextureGL::setSubImageRowByRowWorkaround(const gl::Context *contex
ANGLE_CHECK_GL_MATH(contextGL, glFormat.computeSkipBytes(type, rowBytes, imageBytes, unpack,
useTexImage3D, &skipBytes));
GLint rowsPerChunk =
std::min(std::max(static_cast<GLint>(maxBytesUploadedPerChunk / rowBytes), 1), area.height);
if (maxBytesUploadedPerChunk > 0 && rowsPerChunk < area.height)
{
ANGLE_PERF_WARNING(contextGL->getDebug(), GL_DEBUG_SEVERITY_LOW,
"Chunking upload of texture data to work around driver hangs.");
}
nativegl::TexSubImageFormat texSubImageFormat =
nativegl::GetTexSubImageFormat(functions, features, format, type);
const uint8_t *pixelsWithSkip = pixels + skipBytes;
if (useTexImage3D)
{
for (GLint image = 0; image < area.depth; ++image)
{
GLint imageByteOffset = image * imageBytes;
for (GLint row = 0; row < area.height; ++row)
for (GLint row = 0; row < area.height; row += rowsPerChunk)
{
GLint height = std::min(rowsPerChunk, area.height - row);
GLint byteOffset = imageByteOffset + row * rowBytes;
const GLubyte *rowPixels = pixelsWithSkip + byteOffset;
ANGLE_GL_TRY(context,
functions->texSubImage3D(ToGLenum(target), static_cast<GLint>(level),
area.x, row + area.y, image + area.z,
area.width, 1, 1, format, type, rowPixels));
functions->texSubImage3D(
ToGLenum(target), static_cast<GLint>(level), area.x, row + area.y,
image + area.z, area.width, height, 1, texSubImageFormat.format,
texSubImageFormat.type, rowPixels));
}
}
}
else
{
ASSERT(nativegl::UseTexImage2D(getType()));
for (GLint row = 0; row < area.height; ++row)
for (GLint row = 0; row < area.height; row += rowsPerChunk)
{
GLint height = std::min(rowsPerChunk, area.height - row);
GLint byteOffset = row * rowBytes;
const GLubyte *rowPixels = pixelsWithSkip + byteOffset;
ANGLE_GL_TRY(context, functions->texSubImage2D(
ToGLenum(target), static_cast<GLint>(level), area.x,
row + area.y, area.width, 1, format, type, rowPixels));
row + area.y, area.width, height, texSubImageFormat.format,
texSubImageFormat.type, rowPixels));
}
}
return angle::Result::Continue;
......
......@@ -241,6 +241,7 @@ class TextureGL : public TextureImpl
GLenum type,
const gl::PixelUnpackState &unpack,
const gl::Buffer *unpackBuffer,
size_t maxBytesUploadedPerChunk,
const uint8_t *pixels);
angle::Result setSubImagePaddingWorkaround(const gl::Context *context,
......
......@@ -2162,6 +2162,9 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature
isAdreno4xxOnAndroidLessThan51 || isAdreno4xxOnAndroid70 ||
isAdreno5xxOnAndroidLessThan70 || isAdreno5xxOnAndroid71 ||
isLinuxVivante);
// http://crbug.com/1181068
ANGLE_FEATURE_CONDITION(features, uploadTextureDataInChunks, IsApple());
}
void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features)
......
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