Metal: Upload IOSurface data with staging buffers on AMD

Crashes have been seen in the AMD driver when locking IOSurfaces. Avoid
this by always using a staging buffer and doing a GPU-GPU copy for
uploading client side data to IOSurfaces.

Bug: angleproject:7573
Change-Id: I4d981a24554a755a7248199699b486d98cbad83d
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3915180
Commit-Queue: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Gregg Tavares <gman@chromium.org>
This commit is contained in:
Geoff Lang 2022-09-23 13:15:44 -04:00 коммит произвёл Angle LUCI CQ
Родитель b59609c564
Коммит 2aa52da7e4
7 изменённых файлов: 40 добавлений и 26 удалений

Просмотреть файл

@ -232,6 +232,11 @@ struct FeaturesMtl : FeatureSetBase
"unpackLastRowSeparatelyForPaddingInclusion", FeatureCategory::MetalWorkarounds,
"When uploading textures, some drivers count an extra row padding", &members,
"http://anglebug.com/7573"};
FeatureInfo uploadDataToIosurfacesWithStagingBuffers = {
"uploadDataToIosurfacesWithStagingBuffers", FeatureCategory::MetalWorkarounds,
"When uploading data to IOSurface-backed textures, use a staging buffer.", &members,
"http://anglebug.com/7573"};
};
inline FeaturesMtl::FeaturesMtl() = default;

Просмотреть файл

@ -243,6 +243,14 @@
"When uploading textures, some drivers count an extra row padding"
],
"issue": "http://anglebug.com/7573"
},
{
"name": "upload_data_to_iosurfaces_with_staging_buffers",
"category": "Workarounds",
"description": [
"When uploading data to IOSurface-backed textures, use a staging buffer."
],
"issue": "http://anglebug.com/7573"
}
]
}

Просмотреть файл

@ -4,7 +4,7 @@
"include/platform/FeaturesGL_autogen.h":
"b559f25f72ed9e103c39ef7e130ca58c",
"include/platform/FeaturesMtl_autogen.h":
"32ae6d019cb755d10d962b23a62db0bd",
"ab79ea7540de9e00fe9ed4dd25e84f04",
"include/platform/FeaturesVk_autogen.h":
"5345629fc56cba42aa38f3e8d99f09cb",
"include/platform/FrontendFeatures_autogen.h":
@ -18,11 +18,11 @@
"include/platform/gl_features.json":
"3fb9baa3748a8dd383cf189f1bc12d30",
"include/platform/mtl_features.json":
"2b7671c6d2b0630d209986454bea5eea",
"0da02d9620fbb5b582a369174b5c1295",
"include/platform/vk_features.json":
"288eb5ed66ea3758e0da7cd7ec1a0003",
"util/angle_features_autogen.cpp":
"7fc1339e85fc399c9e0e5cd6f3121003",
"4913cb55fae7e72202fb43b5cff3a859",
"util/angle_features_autogen.h":
"85fecd502c8e20a8e07c197a385d1833"
"a63db55999dfad8e96b8542bc7ce57bc"
}

Просмотреть файл

@ -1155,6 +1155,8 @@ void DisplayMtl::initializeFeatures()
ANGLE_FEATURE_CONDITION((&mFeatures), unpackLastRowSeparatelyForPaddingInclusion, isAMD());
ANGLE_FEATURE_CONDITION((&mFeatures), uploadDataToIosurfacesWithStagingBuffers, isAMD());
ApplyFeatureOverrides(&mFeatures, getState());
#ifdef ANGLE_ENABLE_ASSERTS
static bool once = true;

Просмотреть файл

@ -175,7 +175,6 @@ void WriteDepthStencilToDepth24(const uint8_t *srcPtr, uint8_t *dstPtr)
*dst = gl::floatToNormalized<24, uint32_t>(static_cast<float>(src->depth));
}
#if TARGET_OS_SIMULATOR
void CopyTextureData(const MTLSize &regionSize,
size_t srcRowPitch,
size_t src2DImageSize,
@ -197,7 +196,6 @@ void CopyTextureData(const MTLSize &regionSize,
}
}
}
#endif // TARGET_OS_SIMULATOR
void ConvertDepthStencilData(const MTLSize &regionSize,
const angle::Format &srcAngleFormat,
@ -291,7 +289,6 @@ angle::Result CopyDepthStencilTextureContentsToStagingBuffer(
return angle::Result::Continue;
}
#if TARGET_OS_SIMULATOR
angle::Result CopyTextureContentsToStagingBuffer(ContextMtl *contextMtl,
const angle::Format &textureAngleFormat,
const MTLSize &regionSize,
@ -349,7 +346,6 @@ angle::Result CopyCompressedTextureContentsToStagingBuffer(ContextMtl *contextMt
return angle::Result::Continue;
}
#endif
angle::Result UploadDepthStencilTextureContentsWithStagingBuffer(
ContextMtl *contextMtl,
@ -463,7 +459,6 @@ angle::Result UploadPackedDepthStencilTextureContentsWithStagingBuffer(
return angle::Result::Continue;
}
#if TARGET_OS_SIMULATOR
angle::Result UploadTextureContentsWithStagingBuffer(ContextMtl *contextMtl,
const angle::Format &textureAngleFormat,
MTLRegion region,
@ -515,7 +510,6 @@ angle::Result UploadTextureContentsWithStagingBuffer(ContextMtl *contextMtl,
return angle::Result::Continue;
}
#endif // TARGET_OS_SIMULATOR
angle::Result UploadTextureContents(const gl::Context *context,
const angle::Format &textureAngleFormat,
@ -526,20 +520,16 @@ angle::Result UploadTextureContents(const gl::Context *context,
size_t bytesPerRow,
size_t bytesPer2DImage,
const mtl::TextureRef &texture)
{
ASSERT(texture && texture->valid());
ContextMtl *contextMtl = mtl::GetImpl(context);
ContextMtl *contextMtl = mtl::GetImpl(context);
const angle::FeaturesMtl &features = contextMtl->getDisplay()->getFeatures();
#if TARGET_OS_SIMULATOR
if (!textureAngleFormat.depthBits && !textureAngleFormat.stencilBits)
{
ANGLE_TRY(UploadTextureContentsWithStagingBuffer(contextMtl, textureAngleFormat, region,
mipmapLevel, slice, data, bytesPerRow,
bytesPer2DImage, texture));
return angle::Result::Continue;
}
#else
if (texture->isCPUAccessible())
#if !TARGET_OS_SIMULATOR
bool forceStagedUpload =
texture->hasIOSurface() && features.uploadDataToIosurfacesWithStagingBuffers.enabled;
if (texture->isCPUAccessible() && !forceStagedUpload)
{
// If texture is CPU accessible, just call replaceRegion() directly.
texture->replaceRegion(contextMtl, region, mipmapLevel, slice, data, bytesPerRow,
@ -547,19 +537,26 @@ angle::Result UploadTextureContents(const gl::Context *context,
return angle::Result::Continue;
}
#endif // TARGET_OS_SIMULATOR
#endif
ASSERT(textureAngleFormat.depthBits || textureAngleFormat.stencilBits);
// Texture is not CPU accessible, we need to use staging buffer
if (textureAngleFormat.depthBits && textureAngleFormat.stencilBits)
// Texture is not CPU accessible or staging is forced due to a workaround
if (!textureAngleFormat.depthBits && !textureAngleFormat.stencilBits)
{
// Upload color data
ANGLE_TRY(UploadTextureContentsWithStagingBuffer(contextMtl, textureAngleFormat, region,
mipmapLevel, slice, data, bytesPerRow,
bytesPer2DImage, texture));
}
else if (textureAngleFormat.depthBits && textureAngleFormat.stencilBits)
{
// Packed depth-stencil
ANGLE_TRY(UploadPackedDepthStencilTextureContentsWithStagingBuffer(
contextMtl, textureAngleFormat, region, mipmapLevel, slice, data, bytesPerRow,
bytesPer2DImage, texture));
}
else
{
// Depth or stencil
ANGLE_TRY(UploadDepthStencilTextureContentsWithStagingBuffer(
contextMtl, textureAngleFormat, region, mipmapLevel, slice, data, bytesPerRow,
bytesPer2DImage, texture));

Просмотреть файл

@ -303,6 +303,7 @@ constexpr PackedEnumMap<Feature, const char *> kFeatureNames = {{
{Feature::UnpackOverlappingRowsSeparatelyUnpackBuffer,
"unpackOverlappingRowsSeparatelyUnpackBuffer"},
{Feature::UnsizedSRGBReadPixelsDoesntTransform, "unsizedSRGBReadPixelsDoesntTransform"},
{Feature::UploadDataToIosurfacesWithStagingBuffers, "uploadDataToIosurfacesWithStagingBuffers"},
{Feature::UploadTextureDataInChunks, "uploadTextureDataInChunks"},
{Feature::UseInstancedPointSpriteEmulation, "useInstancedPointSpriteEmulation"},
{Feature::UseMultipleDescriptorsForExternalFormats, "useMultipleDescriptorsForExternalFormats"},

Просмотреть файл

@ -281,6 +281,7 @@ enum class Feature
UnpackLastRowSeparatelyForPaddingInclusion,
UnpackOverlappingRowsSeparatelyUnpackBuffer,
UnsizedSRGBReadPixelsDoesntTransform,
UploadDataToIosurfacesWithStagingBuffers,
UploadTextureDataInChunks,
UseInstancedPointSpriteEmulation,
UseMultipleDescriptorsForExternalFormats,