mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-03 14:09:33 +03:00
Metal: Always prefer staged GPU uploads for textures.
Uploading Metal texture data via MTLTexture::replaceRegion is a source
of lots of CPU hangs and jank. There may be better heuristics to
determine if we should do a CPU vs GPU upload but for now preferring
GPU uploads has better overall performance.
This also improves the MotionMark images test:
- 40 -> 100 when using Metal.
- 217 -> 235 when using Metal +
https://chromium-review.googlesource.com/c/chromium/src/+/4091749
Bug: angleproject:8024, angleproject:8092, angleproject:8109
Change-Id: I36b5f585884391b4cc416365ae65f8542745beee
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4264963
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>
This commit is contained in:
committed by
Angle LUCI CQ
parent
ec307af4ad
commit
f1f80e1e3f
@@ -265,6 +265,17 @@ struct FeaturesMtl : FeatureSetBase
|
||||
FeatureInfo enableParallelMtlLibraryCompilation = {
|
||||
"enableParallelMtlLibraryCompilation", FeatureCategory::MetalFeatures,
|
||||
"Compile MTLLibrary in multiple threads.", &members, "http://crbug.com/1385510"};
|
||||
|
||||
FeatureInfo alwaysPreferStagedTextureUploads = {
|
||||
"alwaysPreferStagedTextureUploads", FeatureCategory::MetalFeatures,
|
||||
"Always prefer to upload texture data via a staging buffer and avoid "
|
||||
"MTLTexture::replaceRegion.",
|
||||
&members, "http://crbug.com/1380790"};
|
||||
|
||||
FeatureInfo disableStagedInitializationOfPackedTextureFormats = {
|
||||
"disableStagedInitializationOfPackedTextureFormats", FeatureCategory::MetalFeatures,
|
||||
"Staged GPU upload of some packed texture formats such as RGB9_E5 fail on Intel GPUs.",
|
||||
&members, "http://anglebug.com/8092"};
|
||||
};
|
||||
|
||||
inline FeaturesMtl::FeaturesMtl() = default;
|
||||
|
||||
@@ -289,6 +289,22 @@
|
||||
"Compile MTLLibrary in multiple threads."
|
||||
],
|
||||
"issue": "http://crbug.com/1385510"
|
||||
},
|
||||
{
|
||||
"name": "always_prefer_staged_texture_uploads",
|
||||
"category": "Features",
|
||||
"description": [
|
||||
"Always prefer to upload texture data via a staging buffer and avoid MTLTexture::replaceRegion."
|
||||
],
|
||||
"issue": "http://crbug.com/1380790"
|
||||
},
|
||||
{
|
||||
"name": "disable_staged_initialization_of_packed_texture_formats",
|
||||
"category": "Features",
|
||||
"description": [
|
||||
"Staged GPU upload of some packed texture formats such as RGB9_E5 fail on Intel GPUs."
|
||||
],
|
||||
"issue": "http://anglebug.com/8092"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"include/platform/FeaturesGL_autogen.h":
|
||||
"331b1660b3982f6540e362764df26021",
|
||||
"include/platform/FeaturesMtl_autogen.h":
|
||||
"d67e2035dabd6e495737da385d5dbe94",
|
||||
"fc2e0328446f01a76c4b301e3b3eae3c",
|
||||
"include/platform/FeaturesVk_autogen.h":
|
||||
"5ab2618c7c158a4af52342eed3114e5f",
|
||||
"include/platform/FrontendFeatures_autogen.h":
|
||||
@@ -18,11 +18,11 @@
|
||||
"include/platform/gl_features.json":
|
||||
"cef92e7ede4c824b8bae37123401d354",
|
||||
"include/platform/mtl_features.json":
|
||||
"cd4de616ed3d18620f8c5b16cb076e66",
|
||||
"17c058de70379f2f5695e1791d45d63c",
|
||||
"include/platform/vk_features.json":
|
||||
"0bc86b174a5f2ec7d1efcf396453693a",
|
||||
"util/angle_features_autogen.cpp":
|
||||
"8cb93987ff50d8fb12e117421b904001",
|
||||
"7ef32f9454ec37566a93741815f65a3f",
|
||||
"util/angle_features_autogen.h":
|
||||
"0f74a51d5cfe16fb2a2087467f1e9362"
|
||||
"1b7b43d4c28184cb6b74f8982688e6ce"
|
||||
}
|
||||
@@ -1274,6 +1274,13 @@ void DisplayMtl::initializeFeatures()
|
||||
ANGLE_FEATURE_CONDITION((&mFeatures), enableInMemoryMtlLibraryCache, true);
|
||||
ANGLE_FEATURE_CONDITION((&mFeatures), enableParallelMtlLibraryCompilation, true);
|
||||
|
||||
// Uploading texture data via staging buffers improves performance on all tested systems.
|
||||
// http://anglebug.com/8092: Disabled on intel due to some texture formats uploading incorrectly
|
||||
// with staging buffers
|
||||
ANGLE_FEATURE_CONDITION(&mFeatures, alwaysPreferStagedTextureUploads, true);
|
||||
ANGLE_FEATURE_CONDITION(&mFeatures, disableStagedInitializationOfPackedTextureFormats,
|
||||
isIntel());
|
||||
|
||||
ApplyFeatureOverrides(&mFeatures, getState());
|
||||
}
|
||||
|
||||
|
||||
@@ -525,13 +525,11 @@ angle::Result UploadTextureContents(const gl::Context *context,
|
||||
|
||||
{
|
||||
ASSERT(texture && texture->valid());
|
||||
ContextMtl *contextMtl = mtl::GetImpl(context);
|
||||
#if !TARGET_OS_SIMULATOR
|
||||
const angle::FeaturesMtl &features = contextMtl->getDisplay()->getFeatures();
|
||||
ContextMtl *contextMtl = mtl::GetImpl(context);
|
||||
const mtl::Format &mtlFormat = contextMtl->getPixelFormat(textureAngleFormat.id);
|
||||
|
||||
bool forceStagedUpload =
|
||||
texture->hasIOSurface() && features.uploadDataToIosurfacesWithStagingBuffers.enabled;
|
||||
if (texture->isCPUAccessible() && !forceStagedUpload)
|
||||
bool preferGPUInitialization = PreferStagedTextureUploads(context, texture, mtlFormat);
|
||||
if (texture->isCPUAccessible() && !preferGPUInitialization)
|
||||
{
|
||||
// If texture is CPU accessible, just call replaceRegion() directly.
|
||||
texture->replaceRegion(contextMtl, region, mipmapLevel, slice, data, bytesPerRow,
|
||||
@@ -539,7 +537,6 @@ angle::Result UploadTextureContents(const gl::Context *context,
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Texture is not CPU accessible or staging is forced due to a workaround
|
||||
if (!textureAngleFormat.depthBits && !textureAngleFormat.stencilBits)
|
||||
|
||||
@@ -33,12 +33,16 @@ void StopFrameCapture();
|
||||
namespace mtl
|
||||
{
|
||||
|
||||
bool PreferStagedTextureUploads(const gl::Context *context,
|
||||
const TextureRef &texture,
|
||||
const Format &textureObjFormat);
|
||||
|
||||
// Initialize texture content to black.
|
||||
angle::Result InitializeTextureContents(const gl::Context *context,
|
||||
const TextureRef &texture,
|
||||
const Format &textureObjFormat,
|
||||
const ImageNativeIndex &index);
|
||||
// Same as above but using GPU clear operation instead of CPU.
|
||||
// Same as above but using GPU clear operation instead of CPU.forma
|
||||
// - channelsToInit parameter controls which channels will get their content initialized.
|
||||
angle::Result InitializeTextureContentsGPU(const gl::Context *context,
|
||||
const TextureRef &texture,
|
||||
|
||||
@@ -346,6 +346,47 @@ static angle::Result InitializeCompressedTextureContents(const gl::Context *cont
|
||||
|
||||
} // namespace
|
||||
|
||||
bool PreferStagedTextureUploads(const gl::Context *context,
|
||||
const TextureRef &texture,
|
||||
const Format &textureObjFormat)
|
||||
{
|
||||
// The simulator MUST upload all textures as staged.
|
||||
if (TARGET_OS_SIMULATOR)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ContextMtl *contextMtl = mtl::GetImpl(context);
|
||||
const angle::FeaturesMtl &features = contextMtl->getDisplay()->getFeatures();
|
||||
|
||||
const gl::InternalFormat &intendedInternalFormat = textureObjFormat.intendedInternalFormat();
|
||||
if (intendedInternalFormat.compressed || textureObjFormat.actualAngleFormat().isBlock)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (intendedInternalFormat.isLUMA())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (features.disableStagedInitializationOfPackedTextureFormats.enabled)
|
||||
{
|
||||
switch (intendedInternalFormat.sizedInternalFormat)
|
||||
{
|
||||
case GL_RGB9_E5:
|
||||
case GL_R11F_G11F_B10F:
|
||||
return false;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (texture->hasIOSurface() && features.uploadDataToIosurfacesWithStagingBuffers.enabled) ||
|
||||
features.alwaysPreferStagedTextureUploads.enabled;
|
||||
}
|
||||
|
||||
angle::Result InitializeTextureContents(const gl::Context *context,
|
||||
const TextureRef &texture,
|
||||
const Format &textureObjFormat,
|
||||
@@ -358,10 +399,7 @@ angle::Result InitializeTextureContents(const gl::Context *context,
|
||||
|
||||
const gl::InternalFormat &intendedInternalFormat = textureObjFormat.intendedInternalFormat();
|
||||
|
||||
bool forceGPUInitialization = false;
|
||||
#if TARGET_OS_SIMULATOR
|
||||
forceGPUInitialization = true;
|
||||
#endif // TARGET_OS_SIMULATOR
|
||||
bool preferGPUInitialization = PreferStagedTextureUploads(context, texture, textureObjFormat);
|
||||
|
||||
// This function is called in many places to initialize the content of a texture.
|
||||
// So it's better we do the initial check here instead of let the callers do it themselves:
|
||||
@@ -385,7 +423,7 @@ angle::Result InitializeTextureContents(const gl::Context *context,
|
||||
startDepth);
|
||||
}
|
||||
else if (texture->isCPUAccessible() && index.getType() != gl::TextureType::_2DMultisample &&
|
||||
index.getType() != gl::TextureType::_2DMultisampleArray && !forceGPUInitialization)
|
||||
index.getType() != gl::TextureType::_2DMultisampleArray && !preferGPUInitialization)
|
||||
{
|
||||
const angle::Format &dstFormat = angle::Format::Get(textureObjFormat.actualFormatId);
|
||||
const size_t dstRowPitch = dstFormat.pixelBytes * size.width;
|
||||
|
||||
@@ -987,6 +987,9 @@
|
||||
6824 METAL INTEL : CubeMapTextureTest.SampleCoordinateTransformGrad/* = SKIP
|
||||
6824 METAL INTEL : CubeMapTextureTest.SampleCoordinateTransformGrad_ES3/* = SKIP
|
||||
|
||||
// Staged texture uploads causes some incorrect texture data on Intel
|
||||
8109 MAC METAL INTEL : Texture2DTest.ManySupersedingTextureUpdates/ES2_Metal = SKIP
|
||||
|
||||
2799 NVIDIA OPENGL WIN : RobustBufferAccessBehaviorTest.DrawElementsIndexOutOfRangeWithStaticDraw/* = SKIP
|
||||
2799 NVIDIA OPENGL WIN : RobustBufferAccessBehaviorTest.DrawElementsIndexOutOfRangeWithDynamicDraw/* = SKIP
|
||||
2861 ANDROID GLES : RobustBufferAccessBehaviorTest.NoBufferData/* = SKIP
|
||||
|
||||
@@ -38,6 +38,7 @@ constexpr PackedEnumMap<Feature, const char *> kFeatureNames = {{
|
||||
{Feature::AllowTranslateUniformBlockToStructuredBuffer,
|
||||
"allowTranslateUniformBlockToStructuredBuffer"},
|
||||
{Feature::AlwaysCallUseProgramAfterLink, "alwaysCallUseProgramAfterLink"},
|
||||
{Feature::AlwaysPreferStagedTextureUploads, "alwaysPreferStagedTextureUploads"},
|
||||
{Feature::AlwaysUnbindFramebufferTexture2D, "alwaysUnbindFramebufferTexture2D"},
|
||||
{Feature::AppendAliasedMemoryDecorationsToSsbo, "appendAliasedMemoryDecorationsToSsbo"},
|
||||
{Feature::AsyncCommandBufferReset, "asyncCommandBufferReset"},
|
||||
@@ -82,6 +83,8 @@ constexpr PackedEnumMap<Feature, const char *> kFeatureNames = {{
|
||||
{Feature::DisableRasterOrderGroups, "disableRasterOrderGroups"},
|
||||
{Feature::DisableRWTextureTier2Support, "disableRWTextureTier2Support"},
|
||||
{Feature::DisableSemaphoreFd, "disableSemaphoreFd"},
|
||||
{Feature::DisableStagedInitializationOfPackedTextureFormats,
|
||||
"disableStagedInitializationOfPackedTextureFormats"},
|
||||
{Feature::DisableSyncControlSupport, "disableSyncControlSupport"},
|
||||
{Feature::DisableTextureClampToBorder, "disableTextureClampToBorder"},
|
||||
{Feature::DisableTimestampQueries, "disableTimestampQueries"},
|
||||
|
||||
@@ -37,6 +37,7 @@ enum class Feature
|
||||
AllowSeparateDepthStencilBuffers,
|
||||
AllowTranslateUniformBlockToStructuredBuffer,
|
||||
AlwaysCallUseProgramAfterLink,
|
||||
AlwaysPreferStagedTextureUploads,
|
||||
AlwaysUnbindFramebufferTexture2D,
|
||||
AppendAliasedMemoryDecorationsToSsbo,
|
||||
AsyncCommandBufferReset,
|
||||
@@ -78,6 +79,7 @@ enum class Feature
|
||||
DisableRasterOrderGroups,
|
||||
DisableRWTextureTier2Support,
|
||||
DisableSemaphoreFd,
|
||||
DisableStagedInitializationOfPackedTextureFormats,
|
||||
DisableSyncControlSupport,
|
||||
DisableTextureClampToBorder,
|
||||
DisableTimestampQueries,
|
||||
|
||||
Reference in New Issue
Block a user