Metal: fix max varyings, copyImage between mips, depth fmt

- GLSLTest_ES3.MaxVaryingWithFeedbackAndGLline failed before because
  gl_Position takes up one slot from max varyings on Metal back-end.
  FIXED

- Previously, copyImage() between mips of the same texture would fail.
  Due to the read RenderTargetMtl is released before the copy happens.
  FIXED

- GL_DEPTH_COMPONENT24 texture data upload didn't work due to the source
  32 bit depth data wasn't handled properly.  FIXED

- D24S8 format will be disabled on AMD for now, it will be converted to
  D32S8 instead.

Bug: angleproject:2634
Bug: angleproject:5235
Bug: angleproject:5242
Change-Id: Ie7082f0545c0885ce5ec72df8a7ec4ee5d5de4b1
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2494525
Commit-Queue: Le Hoang Quyen <le.hoang.q@gmail.com>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Le Hoang Quyen 2020-10-25 03:08:25 +08:00 коммит произвёл Commit Bot
Родитель 4707feaa8f
Коммит 9ff063e9c0
14 изменённых файлов: 129 добавлений и 66 удалений

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

@ -80,6 +80,9 @@ struct FeaturesMtl : FeatureSetBase
"On systems that support both buffer's memory allocation on GPU and shared memory (such as "
"macOS), force using GPU memory allocation for buffers.",
&members};
Feature forceD24S8AsUnsupported = {"force_d24s8_as_unsupported", FeatureCategory::MetalFeatures,
"Force Depth24Stencil8 format as unsupported.", &members};
};
} // namespace angle

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

@ -4,9 +4,9 @@
"src/libANGLE/renderer/angle_format_map.json":
"aa4a0d3463b76858a75787b9cdec8e98",
"src/libANGLE/renderer/metal/gen_mtl_format_table.py":
"91579339b484425ef81b0e900a5c04ed",
"60bf684695cd552e85fc11eba2a1d5bc",
"src/libANGLE/renderer/metal/mtl_format_map.json":
"bd60f72f1dc35054ce439c3edad1caab",
"src/libANGLE/renderer/metal/mtl_format_table_autogen.mm":
"bebdaf4b73c3319075a775e715e35e42"
"1d962a58e82ce1288470e9e0ba3d688b"
}

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

@ -487,26 +487,27 @@ void DisplayMtl::ensureCapsInitialized() const
mNativeCaps.maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
mNativeCaps.max3DTextureSize = 2048;
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
mNativeCaps.max2DTextureSize = 16384;
mNativeCaps.maxVaryingVectors = 31;
mNativeCaps.maxVertexOutputComponents = 124;
mNativeCaps.max2DTextureSize = 16384;
// On macOS exclude [[position]] from maxVaryingVectors.
mNativeCaps.maxVaryingVectors = 31 - 1;
mNativeCaps.maxVertexOutputComponents = mNativeCaps.maxFragmentInputComponents = 124 - 4;
#else
if (supportsIOSGPUFamily(3))
{
mNativeCaps.max2DTextureSize = 16384;
mNativeCaps.maxVertexOutputComponents = 124;
mNativeCaps.maxVaryingVectors = mNativeCaps.maxVertexOutputComponents / 4;
mNativeCaps.maxVertexOutputComponents = mNativeCaps.maxFragmentInputComponents = 124;
mNativeCaps.maxVaryingVectors = mNativeCaps.maxVertexOutputComponents / 4;
}
else
{
mNativeCaps.max2DTextureSize = 8192;
mNativeCaps.maxVertexOutputComponents = 60;
mNativeCaps.maxVaryingVectors = mNativeCaps.maxVertexOutputComponents / 4;
mNativeCaps.maxVertexOutputComponents = mNativeCaps.maxFragmentInputComponents = 60;
mNativeCaps.maxVaryingVectors = mNativeCaps.maxVertexOutputComponents / 4;
}
#endif
mNativeCaps.maxArrayTextureLayers = 2048;
mNativeCaps.maxLODBias = 0;
mNativeCaps.maxLODBias = 2.0; // default GLES3 limit
mNativeCaps.maxCubeMapTextureSize = mNativeCaps.max2DTextureSize;
mNativeCaps.maxRenderbufferSize = mNativeCaps.max2DTextureSize;
mNativeCaps.minAliasedPointSize = 1;
@ -538,8 +539,9 @@ void DisplayMtl::ensureCapsInitialized() const
mNativeCaps.maxVertexAttribRelativeOffset = std::numeric_limits<GLint>::max();
mNativeCaps.maxVertexAttribStride = std::numeric_limits<GLint>::max();
mNativeCaps.maxElementsIndices = std::numeric_limits<GLuint>::max();
mNativeCaps.maxElementsVertices = std::numeric_limits<GLuint>::max();
// glGet() use signed integer as parameter so we have to use GLint's max here, not GLuint.
mNativeCaps.maxElementsIndices = std::numeric_limits<GLint>::max();
mNativeCaps.maxElementsVertices = std::numeric_limits<GLint>::max();
// Looks like all floats are IEEE according to the docs here:
mNativeCaps.vertexHighpFloat.setIEEEFloat();
@ -577,6 +579,10 @@ void DisplayMtl::ensureCapsInitialized() const
mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment] = mtl::kMaxShaderSamplers;
mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex] = mtl::kMaxShaderSamplers;
// No info from Metal given, use default GLES3 spec values:
mNativeCaps.minProgramTexelOffset = -8;
mNativeCaps.maxProgramTexelOffset = 7;
// NOTE(hqle): support storage buffer.
const uint32_t maxPerStageStorageBuffers = 0;
mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Vertex] = maxPerStageStorageBuffers;
@ -592,7 +598,7 @@ void DisplayMtl::ensureCapsInitialized() const
mNativeCaps.maxShaderStorageBlockSize = 0;
mNativeCaps.shaderStorageBufferOffsetAlignment = 0;
// NOTE(hqle): support UBO
// UBO plus default uniform limits
const uint32_t maxCombinedUniformComponents =
maxDefaultUniformComponents + mtl::kMaxUBOSize * mtl::kMaxShaderUBOs / 4;
for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
@ -759,6 +765,10 @@ void DisplayMtl::initializeFeatures()
ANGLE_FEATURE_CONDITION((&mFeatures), hasCheapRenderPass, (isOSX || isCatalyst) && !isARM);
// http://anglebug.com/5235
// D24S8 is unreliable on AMD.
ANGLE_FEATURE_CONDITION((&mFeatures), forceD24S8AsUnsupported, isAMD());
// Base Vertex drawing is only supported since GPU family 3.
ANGLE_FEATURE_CONDITION((&mFeatures), hasBaseVertexInstancedDraw,
isOSX || isCatalyst || supportsIOSGPUFamily(3));

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

@ -115,8 +115,8 @@ class FramebufferMtl : public FramebufferImpl
angle::Result readPixelsImpl(const gl::Context *context,
const gl::Rectangle &area,
const PackPixelsParams &packPixelsParams,
RenderTargetMtl *renderTarget,
uint8_t *pixels);
const RenderTargetMtl *renderTarget,
uint8_t *pixels) const;
private:
void reset();
@ -172,7 +172,7 @@ class FramebufferMtl : public FramebufferImpl
angle::Result readPixelsToPBO(const gl::Context *context,
const gl::Rectangle &area,
const PackPixelsParams &packPixelsParams,
RenderTargetMtl *renderTarget);
const RenderTargetMtl *renderTarget) const;
// NOTE: we cannot use RenderTargetCache here because it doesn't support separate
// depth & stencil attachments as of now. Separate depth & stencil could be useful to

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

@ -1202,8 +1202,8 @@ gl::Rectangle FramebufferMtl::getCorrectFlippedReadArea(const gl::Context *conte
angle::Result FramebufferMtl::readPixelsImpl(const gl::Context *context,
const gl::Rectangle &area,
const PackPixelsParams &packPixelsParams,
RenderTargetMtl *renderTarget,
uint8_t *pixels)
const RenderTargetMtl *renderTarget,
uint8_t *pixels) const
{
ContextMtl *contextMtl = mtl::GetImpl(context);
if (!renderTarget)
@ -1269,7 +1269,7 @@ angle::Result FramebufferMtl::readPixelsImpl(const gl::Context *context,
angle::Result FramebufferMtl::readPixelsToPBO(const gl::Context *context,
const gl::Rectangle &area,
const PackPixelsParams &packPixelsParams,
RenderTargetMtl *renderTarget)
const RenderTargetMtl *renderTarget) const
{
ASSERT(packPixelsParams.packBuffer);
ASSERT(renderTarget);

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

@ -43,6 +43,7 @@ class RenderTargetMtl final : public FramebufferAttachmentRenderTarget
const mtl::Format &format);
void setTexture(const mtl::TextureRef &texture);
void setImplicitMSTexture(const mtl::TextureRef &implicitMSTexture);
void duplicateFrom(const RenderTargetMtl &src);
void reset();
mtl::TextureRef getTexture() const { return mTexture.lock(); }

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

@ -56,6 +56,12 @@ void RenderTargetMtl::setImplicitMSTexture(const mtl::TextureRef &implicitMSText
mImplicitMSTexture = implicitMSTexture;
}
void RenderTargetMtl::duplicateFrom(const RenderTargetMtl &src)
{
setWithImplicitMSTexture(src.getTexture(), src.getImplicitMSTexture(), src.getLevelIndex(),
src.getLayerIndex(), *src.getFormat());
}
void RenderTargetMtl::reset()
{
mTexture.reset();

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

@ -229,19 +229,22 @@ class TextureMtl : public TextureImpl
const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
const gl::InternalFormat &internalFormat,
gl::Framebuffer *source);
const FramebufferMtl *source,
const RenderTargetMtl *sourceRtt);
angle::Result copySubImageWithDraw(const gl::Context *context,
const gl::ImageIndex &index,
const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
const gl::InternalFormat &internalFormat,
gl::Framebuffer *source);
const FramebufferMtl *source,
const RenderTargetMtl *sourceRtt);
angle::Result copySubImageCPU(const gl::Context *context,
const gl::ImageIndex &index,
const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
const gl::InternalFormat &internalFormat,
gl::Framebuffer *source);
const FramebufferMtl *source,
const RenderTargetMtl *sourceRtt);
angle::Result copySubTextureImpl(const gl::Context *context,
const gl::ImageIndex &index,

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

@ -943,6 +943,18 @@ angle::Result TextureMtl::copyImage(const gl::Context *context,
angle::Format::InternalFormatToID(internalFormatInfo.sizedInternalFormat);
const mtl::Format &mtlFormat = contextMtl->getPixelFormat(angleFormatId);
FramebufferMtl *srcFramebufferMtl = mtl::GetImpl(source);
RenderTargetMtl *srcReadRT = srcFramebufferMtl->getColorReadRenderTarget(context);
RenderTargetMtl colorReadRT;
if (srcReadRT)
{
// Need to duplicate RenderTargetMtl since the srcReadRT would be invalidated in
// redefineImage(). This can happen if the source and this texture are the same texture.
// Duplication ensures the copyImage() will be able to proceed even if the source texture
// will be redefined.
colorReadRT.duplicateFrom(*srcReadRT);
}
ANGLE_TRY(redefineImage(context, index, mtlFormat, newImageSize));
gl::Extents fbSize = source->getReadColorAttachment()->getSize();
@ -953,7 +965,7 @@ angle::Result TextureMtl::copyImage(const gl::Context *context,
}
return copySubImageImpl(context, index, gl::Offset(0, 0, 0), sourceArea, internalFormatInfo,
source);
srcFramebufferMtl, &colorReadRT);
}
angle::Result TextureMtl::copySubImage(const gl::Context *context,
@ -963,7 +975,10 @@ angle::Result TextureMtl::copySubImage(const gl::Context *context,
gl::Framebuffer *source)
{
const gl::InternalFormat &currentFormat = *mState.getImageDesc(index).format.info;
return copySubImageImpl(context, index, destOffset, sourceArea, currentFormat, source);
FramebufferMtl *srcFramebufferMtl = mtl::GetImpl(source);
RenderTargetMtl *colorReadRT = srcFramebufferMtl->getColorReadRenderTarget(context);
return copySubImageImpl(context, index, destOffset, sourceArea, currentFormat,
srcFramebufferMtl, colorReadRT);
}
angle::Result TextureMtl::copyTexture(const gl::Context *context,
@ -1531,8 +1546,18 @@ angle::Result TextureMtl::setSubImageImpl(const gl::Context *context,
}
}
const angle::Format &srcAngleFormat =
angle::Format::Get(angle::Format::InternalFormatToID(formatInfo.sizedInternalFormat));
// Get corresponding source data's ANGLE format
angle::FormatID srcAngleFormatId;
if (formatInfo.sizedInternalFormat == GL_DEPTH_COMPONENT24)
{
// GL_DEPTH_COMPONENT24 is special case, its supplied data is 32 bit depth.
srcAngleFormatId = angle::FormatID::D32_UNORM;
}
else
{
srcAngleFormatId = angle::Format::InternalFormatToID(formatInfo.sizedInternalFormat);
}
const angle::Format &srcAngleFormat = angle::Format::Get(srcAngleFormatId);
const uint8_t *usablePixels = oriPixels + sourceSkipBytes;
@ -1859,9 +1884,16 @@ angle::Result TextureMtl::copySubImageImpl(const gl::Context *context,
const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
const gl::InternalFormat &internalFormat,
gl::Framebuffer *source)
const FramebufferMtl *source,
const RenderTargetMtl *colorReadRT)
{
gl::Extents fbSize = source->getReadColorAttachment()->getSize();
if (!colorReadRT || !colorReadRT->getTexture())
{
// Is this an error?
return angle::Result::Continue;
}
gl::Extents fbSize = colorReadRT->getTexture()->size(colorReadRT->getLevelIndex());
gl::Rectangle clippedSourceArea;
if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
&clippedSourceArea))
@ -1880,12 +1912,12 @@ angle::Result TextureMtl::copySubImageImpl(const gl::Context *context,
if (!mFormat.getCaps().isRenderable())
{
return copySubImageCPU(context, index, modifiedDestOffset, clippedSourceArea,
internalFormat, source);
internalFormat, source, colorReadRT);
}
// NOTE(hqle): Use compute shader.
return copySubImageWithDraw(context, index, modifiedDestOffset, clippedSourceArea,
internalFormat, source);
internalFormat, source, colorReadRT);
}
angle::Result TextureMtl::copySubImageWithDraw(const gl::Context *context,
@ -1893,19 +1925,11 @@ angle::Result TextureMtl::copySubImageWithDraw(const gl::Context *context,
const gl::Offset &modifiedDestOffset,
const gl::Rectangle &clippedSourceArea,
const gl::InternalFormat &internalFormat,
gl::Framebuffer *source)
const FramebufferMtl *source,
const RenderTargetMtl *colorReadRT)
{
ContextMtl *contextMtl = mtl::GetImpl(context);
DisplayMtl *displayMtl = contextMtl->getDisplay();
FramebufferMtl *framebufferMtl = mtl::GetImpl(source);
RenderTargetMtl *colorReadRT = framebufferMtl->getColorReadRenderTarget(context);
if (!colorReadRT || !colorReadRT->getTexture())
{
// Is this an error?
return angle::Result::Continue;
}
ContextMtl *contextMtl = mtl::GetImpl(context);
DisplayMtl *displayMtl = contextMtl->getDisplay();
const RenderTargetMtl &imageRtt = getRenderTarget(index);
@ -1923,7 +1947,7 @@ angle::Result TextureMtl::copySubImageWithDraw(const gl::Context *context,
blitParams.srcLevel = colorReadRT->getLevelIndex();
blitParams.srcLayer = colorReadRT->getLayerIndex();
blitParams.srcRect = clippedSourceArea;
blitParams.srcYFlipped = framebufferMtl->flipY();
blitParams.srcYFlipped = source->flipY();
blitParams.dstLuminance = internalFormat.isLUMA();
return displayMtl->getUtils().blitColorWithDraw(
@ -1935,20 +1959,13 @@ angle::Result TextureMtl::copySubImageCPU(const gl::Context *context,
const gl::Offset &modifiedDestOffset,
const gl::Rectangle &clippedSourceArea,
const gl::InternalFormat &internalFormat,
gl::Framebuffer *source)
const FramebufferMtl *source,
const RenderTargetMtl *colorReadRT)
{
mtl::TextureRef &image = getImage(index);
ASSERT(image && image->valid());
ContextMtl *contextMtl = mtl::GetImpl(context);
FramebufferMtl *framebufferMtl = mtl::GetImpl(source);
RenderTargetMtl *colorReadRT = framebufferMtl->getColorReadRenderTarget(context);
if (!colorReadRT || !colorReadRT->getTexture())
{
// Is this an error?
return angle::Result::Continue;
}
ContextMtl *contextMtl = mtl::GetImpl(context);
const angle::Format &dstFormat = angle::Format::Get(mFormat.actualFormatId);
const int dstRowPitch = dstFormat.pixelBytes * clippedSourceArea.width;
@ -1986,11 +2003,9 @@ angle::Result TextureMtl::copySubImageCPU(const gl::Context *context,
PackPixelsParams packParams(srcRowArea, dstFormat, dstRowPitch, false, nullptr, 0);
// Read pixels from framebuffer to memory:
gl::Rectangle flippedSrcRowArea =
framebufferMtl->getCorrectFlippedReadArea(context, srcRowArea);
ANGLE_TRY(framebufferMtl->readPixelsImpl(context, flippedSrcRowArea, packParams,
framebufferMtl->getColorReadRenderTarget(context),
conversionRow.data()));
gl::Rectangle flippedSrcRowArea = source->getCorrectFlippedReadArea(context, srcRowArea);
ANGLE_TRY(source->readPixelsImpl(context, flippedSrcRowArea, packParams, colorReadRT,
conversionRow.data()));
// Upload to texture
ANGLE_TRY(UploadTextureContents(context, dstFormat, mtlDstRowArea, mtl::kZeroNativeMipLevel,

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

@ -95,7 +95,8 @@ image_format_assign_template1 = """
"""
image_format_assign_template2 = """
if (metalDevice.depth24Stencil8PixelFormatSupported)
if (metalDevice.depth24Stencil8PixelFormatSupported &&
!display->getFeatures().forceD24S8AsUnsupported.enabled)
{{
this->metalFormat = {mtl_format};
this->actualFormatId = angle::FormatID::{actual_angle_format};

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

@ -826,7 +826,8 @@ void Format::init(const DisplayMtl *display, angle::FormatID intendedFormatId_)
case angle::FormatID::D24_UNORM_S8_UINT:
if (metalDevice.depth24Stencil8PixelFormatSupported)
if (metalDevice.depth24Stencil8PixelFormatSupported &&
!display->getFeatures().forceD24S8AsUnsupported.enabled)
{
this->metalFormat = MTLPixelFormatDepth24Unorm_Stencil8;
this->actualFormatId = angle::FormatID::D24_UNORM_S8_UINT;

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

@ -824,6 +824,8 @@ TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawArrays)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF(isSwiftshader());
// http://anglebug.com/5232
ANGLE_SKIP_TEST_IF(IsMetal());
// TODO(crbug.com/1132295): Failing on ARM-based Apple DTKs.
ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
// Have to set a large point size because the window size is much larger than the texture
@ -2399,7 +2401,7 @@ TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
{
std::stringstream vertexShaderStream;
// Note: SPIR-V doesn't allow more than 255 parameters to a function.
const unsigned int paramCount = IsVulkan() ? 255u : 1024u;
const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u;
vertexShaderStream << "#version 300 es\n"
"precision highp float;\n"
@ -2680,6 +2682,9 @@ TEST_P(GLSLTest_ES3, AtanVec2)
// Convers a bug with the unary minus operator on signed integer workaround.
TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
{
// http://anglebug.com/5242
ANGLE_SKIP_TEST_IF(IsMetal() && IsIntel());
constexpr char kVS[] =
"#version 300 es\n"
"in highp vec4 position;\n"
@ -2727,6 +2732,9 @@ TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
// Convers a bug with the unary minus operator on unsigned integer workaround.
TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
{
// http://anglebug.com/5242
ANGLE_SKIP_TEST_IF(IsMetal() && IsIntel());
constexpr char kVS[] =
"#version 300 es\n"
"in highp vec4 position;\n"
@ -8756,10 +8764,10 @@ ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTestNoValidation);
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST_ES3(GLSLTest_ES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(GLSLTest_ES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES2(WebGLGLSLTest);
ANGLE_INSTANTIATE_TEST_ES3(WebGL2GLSLTest);
ANGLE_INSTANTIATE_TEST_ES3_AND(WebGL2GLSLTest, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES31(GLSLTest_ES31);

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

@ -232,9 +232,24 @@ TEST_P(TextureUploadFormatTest, All)
case GL_RG:
expected = {refVals[0], refVals[1], 0, 255};
break;
case GL_RED:
case GL_DEPTH_COMPONENT:
case GL_DEPTH_STENCIL:
// Metal back-end requires swizzle feature to return (depth, 0, 0, 1) from sampling
// a depth texture.
// http://anglebug.com/5243
if (IsMetal() && !IsMetalTextureSwizzleAvailable())
{
// If texture swizzle is not supported, we should only compare the first
// component.
expected = {refVals[0], actual[1], actual[2], actual[3]};
}
else
{
expected = {refVals[0], 0, 0, 255};
}
break;
case GL_RED:
expected = {refVals[0], 0, 0, 255};
break;
@ -607,4 +622,4 @@ TEST_P(TextureUploadFormatTest, All)
EXPECT_GL_NO_ERROR();
}
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(TextureUploadFormatTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(TextureUploadFormatTest, ES3_METAL());

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

@ -5138,5 +5138,5 @@ TEST_P(WebGL2CompatibilityTest, RenderToLevelsOfSampledTexture)
// tests should be run against.
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(WebGLCompatibilityTest);
ANGLE_INSTANTIATE_TEST_ES3(WebGL2CompatibilityTest);
ANGLE_INSTANTIATE_TEST_ES3_AND(WebGL2CompatibilityTest, ES3_METAL());
} // namespace angle