blob: 92da5c92e2a6848d308620b39cafcae6431a6b0e [file] [log] [blame]
diff --git a/src/common/utilities.cpp b/src/common/utilities.cpp
index 274d8029521aa8e6d6fdae039a21931f00125fe6..5314733998768cdbda34126ed61d4247ef952541 100644
--- a/src/common/utilities.cpp
+++ b/src/common/utilities.cpp
@@ -6,6 +6,12 @@
// utilities.cpp: Conversion functions and other utility routines.
+// Older clang versions have a false positive on this warning here.
+// TODO(dino): Is this still necessary?
+#if defined(__clang__)
+# pragma clang diagnostic ignored "-Wglobal-constructors"
+#endif
+
#include "common/utilities.h"
#include "GLES3/gl3.h"
#include "common/mathutil.h"
diff --git a/src/compiler/preprocessor/preprocessor_tab_autogen.cpp b/src/compiler/preprocessor/preprocessor_tab_autogen.cpp
index 50822f2007292801b41be16ad956ae0bf06e7e88..3ece2105bcdaea98917001b33d1c6834de022d5e 100644
--- a/src/compiler/preprocessor/preprocessor_tab_autogen.cpp
+++ b/src/compiler/preprocessor/preprocessor_tab_autogen.cpp
@@ -1,5 +1,8 @@
/* A Bison parser, made by GNU Bison 3.3.2. */
+/* Apple Note: For the avoidance of doubt, Apple elects to distribute this file under the terms of
+ * the BSD license. */
+
/* Bison implementation for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
diff --git a/src/compiler/translator/CodeGen.cpp b/src/compiler/translator/CodeGen.cpp
index 497ef881e2d9cf0efb669ca8c7c4f2669633baba..47213c90497c8c9d8f76baf0653fdbc3c7a2e19d 100644
--- a/src/compiler/translator/CodeGen.cpp
+++ b/src/compiler/translator/CodeGen.cpp
@@ -23,6 +23,9 @@
#ifdef ANGLE_ENABLE_METAL
# include "compiler/translator/TranslatorMetalDirect.h"
#endif // ANGLE_ENABLE_METAL
+#ifdef ANGLE_ENABLE_METAL_SPIRV
+# include "compiler/translator/TranslatorMetal.h"
+#endif // ANGLE_ENABLE_METAL_SPIRV
#ifdef ANGLE_ENABLE_METAL_SPIRV
# include "compiler/translator/TranslatorMetal.h"
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 11cb0f04409902a33f2c3677ac280d3d9b3f373c..791dd6dc4e3ea5bbb6289245ded8acffe27568c7 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -279,7 +279,7 @@ bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replaceme
}
TIntermBranch::TIntermBranch(const TIntermBranch &node)
- : TIntermBranch(node.mFlowOp, node.mExpression->deepCopy())
+ : TIntermBranch(node.mFlowOp, node.mExpression ? node.mExpression->deepCopy() : nullptr)
{}
size_t TIntermBranch::getChildCount() const
@@ -1602,10 +1602,10 @@ TIntermLoop::TIntermLoop(TLoopType type,
TIntermLoop::TIntermLoop(const TIntermLoop &node)
: TIntermLoop(node.mType,
- node.mInit->deepCopy(),
- node.mCond->deepCopy(),
- node.mExpr->deepCopy(),
- node.mBody->deepCopy())
+ node.mInit ? node.mInit->deepCopy() : nullptr,
+ node.mCond ? node.mCond->deepCopy() : nullptr,
+ node.mExpr ? node.mExpr->deepCopy() : nullptr,
+ node.mBody ? node.mBody->deepCopy() : nullptr)
{}
TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB)
diff --git a/src/compiler/translator/TranslatorMetalDirect/IdGen.cpp b/src/compiler/translator/TranslatorMetalDirect/IdGen.cpp
index 81ff2722f4983df6bc508602ea4fe06d6da74dd2..9d2b43bc0f987e8b9cb37b2119778e8b5ceb886c 100644
--- a/src/compiler/translator/TranslatorMetalDirect/IdGen.cpp
+++ b/src/compiler/translator/TranslatorMetalDirect/IdGen.cpp
@@ -25,7 +25,7 @@ Name IdGen::createNewName(size_t count,
{
const unsigned id = mNext++;
char idBuffer[std::numeric_limits<unsigned>::digits10 + 1];
- sprintf(idBuffer, "%u", id);
+ snprintf(idBuffer, sizeof(idBuffer), "%u", id);
mNewNameBuffer.clear();
mNewNameBuffer += '_';
diff --git a/src/compiler/translator/TranslatorMetalDirect/ModifyStruct.cpp b/src/compiler/translator/TranslatorMetalDirect/ModifyStruct.cpp
index bcc5d65897a4ab90b2b64c5a5108b7e0d25a3e04..60758fbe8f45b609799af915943e166d2e697e8c 100644
--- a/src/compiler/translator/TranslatorMetalDirect/ModifyStruct.cpp
+++ b/src/compiler/translator/TranslatorMetalDirect/ModifyStruct.cpp
@@ -601,7 +601,7 @@ class ConvertStructState : angle::NonCopyable
void pushNamePath(unsigned extra)
{
char buffer[std::numeric_limits<unsigned>::digits10 + 1];
- sprintf(buffer, "%u", extra);
+ snprintf(buffer, sizeof(buffer), "%u", extra);
pushNamePath(buffer);
}
diff --git a/src/compiler/translator/glslang_tab_autogen.cpp b/src/compiler/translator/glslang_tab_autogen.cpp
index daa1c614f71f0788bc8b1ea1d0e4d8709f6c7b0a..e3a3ddba082f4629478be45068cc7c560276e7e6 100644
--- a/src/compiler/translator/glslang_tab_autogen.cpp
+++ b/src/compiler/translator/glslang_tab_autogen.cpp
@@ -1,5 +1,8 @@
/* A Bison parser, made by GNU Bison 3.3.2. */
+/* Apple Note: For the avoidance of doubt, Apple elects to distribute this file under the terms of
+ * the BSD license. */
+
/* Bison implementation for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
diff --git a/src/compiler/translator/glslang_tab_autogen.h b/src/compiler/translator/glslang_tab_autogen.h
index d2eab0b7bc55675eb9ad5e210fb4d0cb869f35d1..2ec2d2c4495c1ed97a55173e49ea329d82d3f155 100644
--- a/src/compiler/translator/glslang_tab_autogen.h
+++ b/src/compiler/translator/glslang_tab_autogen.h
@@ -1,5 +1,8 @@
/* A Bison parser, made by GNU Bison 3.3.2. */
+/* Apple Note: For the avoidance of doubt, Apple elects to distribute this file under the terms of
+ * the BSD license. */
+
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
diff --git a/src/compiler/translator/glslang_wrapper.cpp b/src/compiler/translator/glslang_wrapper.cpp
index 187f350014fd283b3f406f5c3144a753f02436cb..3de7597d17b8813b60a62ffb14dd29e71491f8af 100644
--- a/src/compiler/translator/glslang_wrapper.cpp
+++ b/src/compiler/translator/glslang_wrapper.cpp
@@ -10,6 +10,7 @@
// This file is separated as glslang's header contains conflicting macro definitions with ANGLE's.
//
+#include "common/spirv/spirv_types.h"
#include "compiler/translator/glslang_wrapper.h"
// glslang has issues with some specific warnings.
diff --git a/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp b/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp
index 55e2f8b9717ec73d2d52607d400352f5f4c0c191..4237558526274ea3e643d45ccf574b6b10eac785 100644
--- a/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp
+++ b/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp
@@ -10,6 +10,7 @@
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
+#if defined(ANGLE_ENABLE_GLSL) && defined(ANGLE_ENABLE_APPLE_WORKAROUNDS)
namespace sh
{
@@ -70,5 +71,5 @@ bool UnfoldShortCircuitAST(TCompiler *compiler, TIntermBlock *root)
root->traverse(&traverser);
return traverser.updateTree(compiler, root);
}
-
+#endif
} // namespace sh
diff --git a/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h b/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h
index ad3cc080de119748939e5aa893fe095b9dd4a2f3..75069c57284bb3b0cb796717191c7d55934c11af 100644
--- a/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h
+++ b/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h
@@ -11,7 +11,7 @@
#define COMPILER_TRANSLATOR_TREEOPS_APPLE_UNFOLDSHORTCIRCUITAST_H_
#include "common/angleutils.h"
-
+#include "common/debug.h"
namespace sh
{
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index 1a5b0d8874f173fed2ee1f27d69b8ea4db6fd919..4459f29401d15fd2b3c553c10c71f1625dc2e2e1 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -6,6 +6,9 @@
// State.cpp: Implements the State class, encapsulating raw GL state.
+// Older clang versions have a false positive on this warning here.
+#pragma clang diagnostic ignored "-Wglobal-constructors"
+
#include "libANGLE/State.h"
#include <string.h>
diff --git a/src/libANGLE/renderer/ShaderInterfaceVariableInfoMap.cpp b/src/libANGLE/renderer/ShaderInterfaceVariableInfoMap.cpp
index ae040dfc19960b7cc686d0c2136454eb246ca80d..9e69e2fa308675249c48aee6b44b09cd4a5d2dfa 100644
--- a/src/libANGLE/renderer/ShaderInterfaceVariableInfoMap.cpp
+++ b/src/libANGLE/renderer/ShaderInterfaceVariableInfoMap.cpp
@@ -114,12 +114,14 @@ const ShaderInterfaceVariableInfo &ShaderInterfaceVariableInfoMap::getVariableBy
return mData[shaderType][typeAndIndex.variableType][typeAndIndex.index];
}
+#if ANGLE_ENABLE_METAL_SPIRV
bool ShaderInterfaceVariableInfoMap::hasTransformFeedbackInfo(gl::ShaderType shaderType,
uint32_t bufferIndex) const
{
std::string bufferName = rx::GetXfbBufferName(bufferIndex);
return hasVariable(shaderType, bufferName);
}
+#endif
void ShaderInterfaceVariableInfoMap::mapIndexedResourceByName(gl::ShaderType shaderType,
ShaderVariableType variableType,
diff --git a/src/libANGLE/renderer/ShaderInterfaceVariableInfoMap.h b/src/libANGLE/renderer/ShaderInterfaceVariableInfoMap.h
index ce9c26e401ffd4fa59eb8308a5210998970bec8c..dcaa142fc2a5e0d45ddf7e8fcaac14bb7f30ff2d 100644
--- a/src/libANGLE/renderer/ShaderInterfaceVariableInfoMap.h
+++ b/src/libANGLE/renderer/ShaderInterfaceVariableInfoMap.h
@@ -89,7 +89,9 @@ class ShaderInterfaceVariableInfoMap final : angle::NonCopyable
bool hasAtomicCounterInfo(gl::ShaderType shaderType) const;
const ShaderInterfaceVariableInfo &getAtomicCounterInfo(gl::ShaderType shaderType) const;
const ShaderInterfaceVariableInfo &getFramebufferFetchInfo(gl::ShaderType shaderType) const;
+#if ANGLE_ENABLE_METAL_SPIRV
bool hasTransformFeedbackInfo(gl::ShaderType shaderType, uint32_t bufferIndex) const;
+#endif
const ShaderInterfaceVariableInfo &getTransformFeedbackInfo(gl::ShaderType shaderType,
uint32_t bufferIndex) const;
diff --git a/src/libANGLE/renderer/driver_utils.cpp b/src/libANGLE/renderer/driver_utils.cpp
index e1555cff0ce083f309e845eab2678be57839122e..ad08da0ed2befa72cf2a5291a6d91c62538939b4 100644
--- a/src/libANGLE/renderer/driver_utils.cpp
+++ b/src/libANGLE/renderer/driver_utils.cpp
@@ -268,6 +268,10 @@ const char *GetVendorString(uint32_t vendorId)
return "Qualcomm";
case VENDOR_ID_SAMSUNG:
return "Samsung Electronics Co., Ltd.";
+ case VENDOR_ID_VMWARE:
+ return "VMware";
+ case VENDOR_ID_VIVANTE:
+ return "Vivante";
case 0xba5eba11: // Mock vendor ID used for tests.
return "Test";
case 0:
diff --git a/src/libANGLE/renderer/glslang_wrapper_utils.h b/src/libANGLE/renderer/glslang_wrapper_utils.h
index 6eb21d9e204cd958448603938053f9c72bb91846..e21456e19ce5112a5535080193979d0858b7d58b 100644
--- a/src/libANGLE/renderer/glslang_wrapper_utils.h
+++ b/src/libANGLE/renderer/glslang_wrapper_utils.h
@@ -157,7 +157,7 @@ void GlslangAssignTransformFeedbackLocations(gl::ShaderType shaderType,
bool isTransformFeedbackStage,
GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut);
-
+#if ANGLE_ENABLE_METAL_SPIRV
// Retrieves the compiled SPIR-V code for each shader stage, and calls |GlslangAssignLocations|.
void GlslangGetShaderSpirvCode(const GlslangSourceOptions &options,
const gl::ProgramState &programState,
@@ -170,6 +170,7 @@ angle::Result GlslangTransformSpirvCode(const GlslangSpirvOptions &options,
const ShaderInterfaceVariableInfoMap &variableInfoMap,
const angle::spirv::Blob &initialSpirvBlob,
angle::spirv::Blob *spirvBlobOut);
+#endif
} // namespace rx
diff --git a/src/libANGLE/renderer/metal/BufferMtl.mm b/src/libANGLE/renderer/metal/BufferMtl.mm
index c8769efa38736be06a1c7fc12a4f21ef578c5f01..1766256930914b030119724f01d2adb2f54269a2 100644
--- a/src/libANGLE/renderer/metal/BufferMtl.mm
+++ b/src/libANGLE/renderer/metal/BufferMtl.mm
@@ -365,7 +365,7 @@
{
if (buffer.offset == offset)
{
- return &buffer;
+ return static_cast<ConversionBufferMtl *>(&buffer);
}
}
@@ -520,7 +520,7 @@
default:
// dynamic buffer, allow up to 10 update per frame/encoding without
// waiting for GPU.
- if (adjustedSize <= mtl::kSharedMemBufferMaxBufSizeHint)
+ if (adjustedSize <= kConvertedElementArrayBufferInitialSize)
{
maxBuffers = 10;
mBufferPool.setAlwaysUseSharedMem();
diff --git a/src/libANGLE/renderer/metal/ContextMtl.h b/src/libANGLE/renderer/metal/ContextMtl.h
index 038515414371ccde7b55e50d41465438dc163b00..67e137dc22a12cf56394162754090f7d102bf48b 100644
--- a/src/libANGLE/renderer/metal/ContextMtl.h
+++ b/src/libANGLE/renderer/metal/ContextMtl.h
@@ -577,6 +577,8 @@ class ContextMtl : public ContextImpl, public mtl::Context
gl::AttributesMask mDirtyDefaultAttribsMask;
DirtyBits mDirtyBits;
+ uint32_t mRenderPassesSinceFlush = 0;
+
// State
mtl::RenderPipelineDesc mRenderPipelineDesc;
mtl::DepthStencilDesc mDepthStencilDesc;
diff --git a/src/libANGLE/renderer/metal/ContextMtl.mm b/src/libANGLE/renderer/metal/ContextMtl.mm
index 89bb8b23a4f712adfa3f9b72967d36d6cfe14527..dc2f5fe8fbd3c8bc2c11f9982f76f7a290be0517 100644
--- a/src/libANGLE/renderer/metal/ContextMtl.mm
+++ b/src/libANGLE/renderer/metal/ContextMtl.mm
@@ -1693,10 +1693,19 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs)
endEncoding(true);
mCmdBuffer.commit(operation);
+ mRenderPassesSinceFlush = 0;
}
void ContextMtl::flushCommandBufferIfNeeded()
{
+ if (mRenderPassesSinceFlush >= mtl::kMaxRenderPassesPerCommandBuffer)
+ {
+ // WaitUntilScheduled here is intended to help the CPU-GPU pipeline and
+ // helps to keep the number of inflight render passes in the system to a
+ // minimum.
+ flushCommandBuffer(mtl::WaitUntilScheduled);
+ }
+
if (mCmdBuffer.needsFlushForDrawCallLimits())
{
flushCommandBuffer(mtl::NoWait);
@@ -1717,6 +1726,7 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs)
endEncoding(false);
mCmdBuffer.present(presentationDrawable);
mCmdBuffer.commit(mtl::NoWait);
+ mRenderPassesSinceFlush = 0;
}
angle::Result ContextMtl::finishCommandBuffer()
@@ -1752,6 +1762,7 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs)
endEncoding(false);
ensureCommandBufferReady();
+ mRenderPassesSinceFlush++;
// Need to re-apply everything on next draw call.
mDirtyBits.set();
diff --git a/src/libANGLE/renderer/metal/DisplayMtl.mm b/src/libANGLE/renderer/metal/DisplayMtl.mm
index 13aec00fac3e4ea8932a86883dcc6eff7f30f59c..295a3788aa012838660233608df48f10bd269831 100644
--- a/src/libANGLE/renderer/metal/DisplayMtl.mm
+++ b/src/libANGLE/renderer/metal/DisplayMtl.mm
@@ -1210,8 +1210,7 @@ bool IsMetalDisplayAvailable()
bool DisplayMtl::supports32BitFloatFiltering() const
{
#if (defined(__MAC_11_0) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_11_0) || \
- (defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_14_0) || \
- (defined(__TVOS_14_0) && __TV_OS_VERSION_MIN_REQUIRED >= __TVOS_14_0)
+ (defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_14_0)
if (@available(ios 14.0, macOS 11.0, *))
{
return [mMetalDevice supports32BitFloatFiltering];
diff --git a/src/libANGLE/renderer/metal/mtl_buffer_pool.h b/src/libANGLE/renderer/metal/mtl_buffer_pool.h
index c3be11f78156c7fab4ee8a90733de2f3b049de7e..204ebb949873112c010242b2b16b0860cd40c00a 100644
--- a/src/libANGLE/renderer/metal/mtl_buffer_pool.h
+++ b/src/libANGLE/renderer/metal/mtl_buffer_pool.h
@@ -126,7 +126,7 @@ class BufferPool
size_t mBuffersAllocated;
size_t mMaxBuffers;
- BufferPoolMemPolicy mMemPolicy;
+ BufferPoolMemPolicy mMemPolicy = BufferPoolMemPolicy::Auto;
bool mAlwaysAllocateNewBuffer;
};
diff --git a/src/libANGLE/renderer/metal/mtl_common.h b/src/libANGLE/renderer/metal/mtl_common.h
index 3f3086c36d3ae3886af05a044bbdc834e63d2239..c6618ecc2259f22756b61738d041e679420ce8bf 100644
--- a/src/libANGLE/renderer/metal/mtl_common.h
+++ b/src/libANGLE/renderer/metal/mtl_common.h
@@ -147,6 +147,11 @@ constexpr uint32_t kMaxViewports = 1;
// will be flushed next time
constexpr const size_t kMaximumResidentMemorySizeInBytes = 400 * 1024 * 1024;
+// Restrict in-flight render passes per command buffer to 16.
+// The goal is to reduce the number of active render passes on the system at
+// anyone time and this value was determined through experimentation.
+constexpr uint32_t kMaxRenderPassesPerCommandBuffer = 16;
+
constexpr uint32_t kVertexAttribBufferStrideAlignment = 4;
// Alignment requirement for offset passed to setVertex|FragmentBuffer
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
diff --git a/src/libANGLE/renderer/metal/mtl_render_utils.mm b/src/libANGLE/renderer/metal/mtl_render_utils.mm
index 4b854d589c5c7042ba8ab2e32960425c4070eb2a..1e2b6888ef205c355b2220fb36d3b889a614fa25 100644
--- a/src/libANGLE/renderer/metal/mtl_render_utils.mm
+++ b/src/libANGLE/renderer/metal/mtl_render_utils.mm
@@ -2540,45 +2540,13 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder,
bool sRGBMipmap,
NativeTexLevelArray *mipmapOutputViews)
{
- // Only support 3D texture for now.
- ASSERT(srcTexture->textureType() == MTLTextureType3D);
-
MTLSize threadGroupSize;
uint32_t slices = 1;
id<MTLComputePipelineState> computePipeline = nil;
-
- ensure3DMipGeneratorPipelineInitialized(contextMtl);
- computePipeline = m3DMipGeneratorPipeline;
- threadGroupSize =
- MTLSizeMake(kGenerateMipThreadGroupSizePerDim, kGenerateMipThreadGroupSizePerDim,
- kGenerateMipThreadGroupSizePerDim);
-
// The compute shader supports up to 4 mipmaps generated per pass.
// See shaders/gen_mipmap.metal
uint32_t maxMipsPerBatch = 4;
- if (threadGroupSize.width * threadGroupSize.height * threadGroupSize.depth >
- computePipeline.maxTotalThreadsPerThreadgroup ||
- ANGLE_UNLIKELY(
- !contextMtl->getDisplay()->getFeatures().allowGenMultipleMipsPerPass.enabled))
- {
- // Multiple mipmaps generation is not supported due to hardware's thread group size limits.
- // Fallback to generate one mip per pass and reduce thread group size.
- if (ANGLE_UNLIKELY(threadGroupSize.width * threadGroupSize.height >
- computePipeline.maxTotalThreadsPerThreadgroup))
- {
- // Even with reduced thread group size, we cannot proceed.
- // HACK: use blit command encoder to generate mipmaps if it is not possible
- // to use compute shader due to hardware limits.
- BlitCommandEncoder *blitEncoder = contextMtl->getBlitCommandEncoder();
- blitEncoder->generateMipmapsForTexture(srcTexture);
- return angle::Result::Continue;
- }
-
- threadGroupSize.depth = 1;
- maxMipsPerBatch = 1;
- }
-
ComputeCommandEncoder *cmdEncoder = contextMtl->getComputeCommandEncoder();
ASSERT(cmdEncoder);
@@ -2615,8 +2583,29 @@ ANGLE_INLINE void SetPipelineState(ComputeCommandEncoder *encoder,
UNREACHABLE();
}
- Generate3DMipmapUniform options;
+ if (threadGroupSize.width * threadGroupSize.height * threadGroupSize.depth >
+ computePipeline.maxTotalThreadsPerThreadgroup ||
+ ANGLE_UNLIKELY(
+ !contextMtl->getDisplay()->getFeatures().allowGenMultipleMipsPerPass.enabled))
+ {
+ // Multiple mipmaps generation is not supported due to hardware's thread group size limits.
+ // Fallback to generate one mip per pass and reduce thread group size.
+ if (ANGLE_UNLIKELY(threadGroupSize.width * threadGroupSize.height >
+ computePipeline.maxTotalThreadsPerThreadgroup))
+ {
+ // Even with reduced thread group size, we cannot proceed.
+ // HACK: use blit command encoder to generate mipmaps if it is not possible
+ // to use compute shader due to hardware limits.
+ BlitCommandEncoder *blitEncoder = contextMtl->getBlitCommandEncoder();
+ blitEncoder->generateMipmapsForTexture(srcTexture);
+ return angle::Result::Continue;
+ }
+
+ threadGroupSize.depth = 1;
+ maxMipsPerBatch = 1;
+ }
+ Generate3DMipmapUniform options;
uint32_t remainMips = srcTexture->mipmapLevels() - 1;
MipmapNativeLevel batchSrcLevel = kZeroNativeMipLevel;
options.srcLevel = batchSrcLevel.get();
diff --git a/src/libANGLE/renderer/metal/mtl_resource_spi.h b/src/libANGLE/renderer/metal/mtl_resource_spi.h
index 3eaa9a64e79af26faa786102ece3f0bdea84d090..2ecf7b40bd5a2edc3fd9d69841e266b6c3cee685 100644
--- a/src/libANGLE/renderer/metal/mtl_resource_spi.h
+++ b/src/libANGLE/renderer/metal/mtl_resource_spi.h
@@ -1,9 +1,63 @@
-//
-// Copyright 2021 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
//
// mtl_resource_spi.h:
-// Used to set Metal resource ownership identity with SPI.
-// Purposefully empty header file. Actual implementation will be hosted in WebKit.
+// Used to set Metal resource ownership identity with SPI
//
+
+#ifndef LIBANGLE_RENDERER_METAL_RESOURCE_SPI_H_
+#define LIBANGLE_RENDERER_METAL_RESOURCE_SPI_H_
+
+#import "common/apple/apple_platform.h"
+
+#if ANGLE_USE_METAL_OWNERSHIP_IDENTITY
+
+# import <Metal/MTLResource_Private.h>
+# import <Metal/Metal.h>
+# import <mach/mach_types.h>
+
+namespace rx
+{
+namespace mtl
+{
+inline void setOwnerWithIdentity(id<MTLResource> resource, task_id_token_t identityToken)
+{
+ if (identityToken != TASK_ID_TOKEN_NULL)
+ {
+ kern_return_t kr = [(id<MTLResourceSPI>)resource setOwnerWithIdentity:identityToken];
+ if (ANGLE_UNLIKELY(kr != KERN_SUCCESS))
+ {
+ ERR() << "setOwnerWithIdentity failed with: %s (%x)" << mach_error_string(kr) << kr;
+ ASSERT(false);
+ }
+ }
+ return;
+}
+}
+}
+#endif
+
+#endif /* LIBANGLE_RENDERER_METAL_RESOURCE_SPI_H_ */
diff --git a/src/libANGLE/renderer/metal/mtl_resources.h b/src/libANGLE/renderer/metal/mtl_resources.h
index afbc985eb92dfbd5af964bd8ac207ac1db6ac97e..9805aa705a259a97e92418387f12385171b2fa59 100644
--- a/src/libANGLE/renderer/metal/mtl_resources.h
+++ b/src/libANGLE/renderer/metal/mtl_resources.h
@@ -339,7 +339,9 @@ class Texture final : public Resource,
size_t mEstimatedByteSize = 0;
};
-class Buffer final : public Resource, public WrappedObject<id<MTLBuffer>>
+class Buffer final : public Resource,
+ public WrappedObject<id<MTLBuffer>>,
+ public std::enable_shared_from_this<Buffer>
{
public:
static angle::Result MakeBuffer(ContextMtl *context,
diff --git a/src/libANGLE/renderer/metal/mtl_resources.mm b/src/libANGLE/renderer/metal/mtl_resources.mm
index 6bcb9cd8d3e2087dd269b4c5fb8b8214c33e2f0e..414a3d9dbb7ab125172ee99aa9df636383c3d4f5 100644
--- a/src/libANGLE/renderer/metal/mtl_resources.mm
+++ b/src/libANGLE/renderer/metal/mtl_resources.mm
@@ -35,12 +35,14 @@ inline NSUInteger GetMipSize(NSUInteger baseSize, const MipmapNativeLevel level)
// Asynchronously synchronize the content of a resource between GPU memory and its CPU cache.
// NOTE: This operation doesn't finish immediately upon function's return.
template <class T>
-void InvokeCPUMemSync(ContextMtl *context, mtl::BlitCommandEncoder *blitEncoder, T *resource)
+void InvokeCPUMemSync(ContextMtl *context,
+ mtl::BlitCommandEncoder *blitEncoder,
+ const std::shared_ptr<T> &resource)
{
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
if (blitEncoder)
{
- blitEncoder->synchronizeResource(resource);
+ blitEncoder->synchronizeResource(resource.get());
resource->resetCPUReadMemNeedSync();
resource->setCPUReadMemSyncPending(true);
@@ -49,7 +51,7 @@ void InvokeCPUMemSync(ContextMtl *context, mtl::BlitCommandEncoder *blitEncoder,
}
template <class T>
-void EnsureCPUMemWillBeSynced(ContextMtl *context, T *resource)
+void EnsureCPUMemWillBeSynced(ContextMtl *context, const std::shared_ptr<T> &resource)
{
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
// Make sure GPU & CPU contents are synchronized.
@@ -271,11 +273,10 @@ void EnsureCPUMemWillBeSynced(ContextMtl *context, T *resource)
{
return angle::Result::Stop;
}
- refOut->reset(new Texture(context, desc, mips, renderTargetOnly, allowFormatView, memoryLess));
- if (!refOut || !refOut->get())
- {
- ANGLE_MTL_CHECK(context, false, GL_OUT_OF_MEMORY);
- }
+ ASSERT(refOut);
+ Texture *newTexture = new Texture(context, desc, mips, renderTargetOnly, allowFormatView, memoryLess);
+ ANGLE_MTL_CHECK(context, newTexture->valid(), GL_OUT_OF_MEMORY);
+ refOut->reset(newTexture);
if (!mtlFormat.hasDepthAndStencilBits())
{
refOut->get()->setColorWritableMask(GetEmulatedColorWriteMask(mtlFormat));
@@ -299,13 +300,10 @@ void EnsureCPUMemWillBeSynced(ContextMtl *context, T *resource)
bool renderTargetOnly,
TextureRef *refOut)
{
-
- refOut->reset(new Texture(context, desc, surfaceRef, slice, renderTargetOnly));
-
- if (!(*refOut) || !(*refOut)->get())
- {
- ANGLE_MTL_CHECK(context, false, GL_OUT_OF_MEMORY);
- }
+ ASSERT(refOut);
+ Texture *newTexture = new Texture(context, desc, surfaceRef, slice, renderTargetOnly);
+ ANGLE_MTL_CHECK(context, newTexture->valid(), GL_OUT_OF_MEMORY);
+ refOut->reset(newTexture);
if (!mtlFormat.hasDepthAndStencilBits())
{
refOut->get()->setColorWritableMask(GetEmulatedColorWriteMask(mtlFormat));
@@ -504,12 +502,12 @@ bool needMultisampleColorFormatShaderReadWorkaround(ContextMtl *context, MTLText
void Texture::syncContent(ContextMtl *context, mtl::BlitCommandEncoder *blitEncoder)
{
- InvokeCPUMemSync(context, blitEncoder, this);
+ InvokeCPUMemSync(context, blitEncoder, shared_from_this());
}
void Texture::syncContentIfNeeded(ContextMtl *context)
{
- EnsureCPUMemWillBeSynced(context, this);
+ EnsureCPUMemWillBeSynced(context, shared_from_this());
}
bool Texture::isCPUAccessible() const
@@ -988,7 +986,7 @@ bool needMultisampleColorFormatShaderReadWorkaround(ContextMtl *context, MTLText
void Buffer::syncContent(ContextMtl *context, mtl::BlitCommandEncoder *blitEncoder)
{
- InvokeCPUMemSync(context, blitEncoder, this);
+ InvokeCPUMemSync(context, blitEncoder, shared_from_this());
}
const uint8_t *Buffer::mapReadOnly(ContextMtl *context)
@@ -1009,7 +1007,7 @@ bool needMultisampleColorFormatShaderReadWorkaround(ContextMtl *context, MTLText
{
CommandQueue &cmdQueue = context->cmdQueue();
- EnsureCPUMemWillBeSynced(context, this);
+ EnsureCPUMemWillBeSynced(context, shared_from_this());
if (this->isBeingUsedByGPU(context))
{
diff --git a/src/libANGLE/renderer/metal/mtl_state_cache.mm b/src/libANGLE/renderer/metal/mtl_state_cache.mm
index 7ef96c443d7b780ad045dfeac423ef0a86889750..625416a3ba8f1f819ecbe63e81371a5b13949b32 100644
--- a/src/libANGLE/renderer/metal/mtl_state_cache.mm
+++ b/src/libANGLE/renderer/metal/mtl_state_cache.mm
@@ -943,6 +943,62 @@ void ToObjC(const RenderPassStencilAttachmentDesc &desc,
return re.first->second;
}
+static bool ValidateRenderPipelineState(const MTLRenderPipelineDescriptor *descriptor,
+ ContextMtl *context,
+ const mtl::ContextDevice &device)
+{
+ // Ensure there is at least one valid render target.
+ bool hasValidRenderTarget = false;
+
+ const NSUInteger maxColorRenderTargets = GetMaxNumberOfRenderTargetsForDevice(device);
+ for (NSUInteger i = 0; i < maxColorRenderTargets; ++i)
+ {
+ auto colorAttachment = descriptor.colorAttachments[i];
+ if (colorAttachment && colorAttachment.pixelFormat != MTLPixelFormatInvalid)
+ {
+ hasValidRenderTarget = true;
+ break;
+ }
+ }
+
+ if (!hasValidRenderTarget && descriptor.depthAttachmentPixelFormat != MTLPixelFormatInvalid)
+ {
+ hasValidRenderTarget = true;
+ }
+
+ if (!hasValidRenderTarget && descriptor.stencilAttachmentPixelFormat != MTLPixelFormatInvalid)
+ {
+ hasValidRenderTarget = true;
+ }
+
+ if (!hasValidRenderTarget)
+ {
+ UNREACHABLE();
+ ANGLE_MTL_HANDLE_ERROR(context, "Render pipeline requires at least one render target.",
+ GL_INVALID_OPERATION);
+ return false;
+ }
+
+ // Ensure the device can support the storage requirement for render targets.
+ if (DeviceHasMaximumRenderTargetSize(device))
+ {
+ // TODO: Is the use of NSUInteger in 32 bit systems ok without any overflow checking?
+ NSUInteger maxSize = GetMaxRenderTargetSizeForDeviceInBytes(device);
+ NSUInteger renderTargetSize =
+ ComputeTotalSizeUsedForMTLRenderPipelineDescriptor(descriptor, context, device);
+ if (renderTargetSize > maxSize)
+ {
+ std::stringstream errorStream;
+ errorStream << "This set of render targets requires " << renderTargetSize
+ << " bytes of pixel storage. This device supports " << maxSize << " bytes.";
+ ANGLE_MTL_HANDLE_ERROR(context, errorStream.str().c_str(), GL_INVALID_OPERATION);
+ return false;
+ }
+ }
+
+ return true;
+}
+
AutoObjCPtr<id<MTLRenderPipelineState>> RenderPipelineCache::createRenderPipelineState(
ContextMtl *context,
const RenderPipelineDesc &originalDesc,
@@ -1005,23 +1061,10 @@ void ToObjC(const RenderPassStencilAttachmentDesc &desc,
// Convert to Objective-C desc:
AutoObjCObj<MTLRenderPipelineDescriptor> objCDesc = ToObjC(vertShader, fragShader, desc);
- // Validate Render Pipeline State:
- if (DeviceHasMaximumRenderTargetSize(metalDevice))
- {
- // TODO: Is the use of NSUInteger in 32 bit systems ok without any overflow checking?
- NSUInteger maxSize = GetMaxRenderTargetSizeForDeviceInBytes(metalDevice);
- NSUInteger renderTargetSize =
- ComputeTotalSizeUsedForMTLRenderPipelineDescriptor(objCDesc, context, metalDevice);
- if (renderTargetSize > maxSize)
+ if (!ValidateRenderPipelineState(objCDesc, context, metalDevice))
{
- std::stringstream errorStream;
- errorStream << "This set of render targets requires " << renderTargetSize
- << " bytes of pixel storage. This device supports " << maxSize
- << " bytes.";
- ANGLE_MTL_HANDLE_ERROR(context, errorStream.str().c_str(), GL_INVALID_OPERATION);
return nil;
}
- }
// Special attribute slot for default attribute
if (insertDefaultAttribLayout)
diff --git a/src/libANGLE/renderer/metal/mtl_utils.h b/src/libANGLE/renderer/metal/mtl_utils.h
index d218c13ed14be57f514cbf3c9dbeedefcdd49621..b236d92655d0307bb0b61ce51bf6406e9e934e96 100644
--- a/src/libANGLE/renderer/metal/mtl_utils.h
+++ b/src/libANGLE/renderer/metal/mtl_utils.h
@@ -105,11 +105,9 @@ AutoObjCPtr<id<MTLLibrary>> CreateShaderLibrary(
bool enableFastMath,
AutoObjCPtr<NSError *> *error);
-AutoObjCPtr<id<MTLLibrary>> CreateShaderLibraryFromBinary(
- id<MTLDevice> metalDevice,
+AutoObjCPtr<id<MTLLibrary>> CreateShaderLibraryFromBinary(id<MTLDevice> metalDevice,
const uint8_t *binarySource,
size_t binarySourceLen,
- NSDictionary<NSString *, NSObject *> *substitutionDictionary,
AutoObjCPtr<NSError *> *error);
bool SupportsAppleGPUFamily(id<MTLDevice> device, uint8_t appleFamily);
diff --git a/src/tests/deqp_support/deqp_egl_test_expectations.txt b/src/tests/deqp_support/deqp_egl_TestExpectations
similarity index 100%
rename from src/tests/deqp_support/deqp_egl_test_expectations.txt
rename to src/tests/deqp_support/deqp_egl_TestExpectations
diff --git a/src/tests/deqp_support/deqp_gles2_test_expectations.txt b/src/tests/deqp_support/deqp_gles2_TestExpectations
similarity index 100%
rename from src/tests/deqp_support/deqp_gles2_test_expectations.txt
rename to src/tests/deqp_support/deqp_gles2_TestExpectations
diff --git a/src/tests/deqp_support/deqp_gles31_test_expectations.txt b/src/tests/deqp_support/deqp_gles31_TestExpectations
similarity index 100%
rename from src/tests/deqp_support/deqp_gles31_test_expectations.txt
rename to src/tests/deqp_support/deqp_gles31_TestExpectations
diff --git a/src/tests/deqp_support/deqp_gles31_rotate_test_expectations.txt b/src/tests/deqp_support/deqp_gles31_rotate_TestExpectations
similarity index 100%
rename from src/tests/deqp_support/deqp_gles31_rotate_test_expectations.txt
rename to src/tests/deqp_support/deqp_gles31_rotate_TestExpectations
diff --git a/src/tests/deqp_support/deqp_gles3_test_expectations.txt b/src/tests/deqp_support/deqp_gles3_TestExpectations
similarity index 100%
rename from src/tests/deqp_support/deqp_gles3_test_expectations.txt
rename to src/tests/deqp_support/deqp_gles3_TestExpectations
diff --git a/src/tests/deqp_support/deqp_gles3_rotate_test_expectations.txt b/src/tests/deqp_support/deqp_gles3_rotate_TestExpectations
similarity index 100%
rename from src/tests/deqp_support/deqp_gles3_rotate_test_expectations.txt
rename to src/tests/deqp_support/deqp_gles3_rotate_TestExpectations
diff --git a/src/tests/deqp_support/deqp_khr_gles2_test_expectations.txt b/src/tests/deqp_support/deqp_khr_gles2_TestExpectations
similarity index 100%
rename from src/tests/deqp_support/deqp_khr_gles2_test_expectations.txt
rename to src/tests/deqp_support/deqp_khr_gles2_TestExpectations
diff --git a/src/tests/deqp_support/deqp_khr_gles31_test_expectations.txt b/src/tests/deqp_support/deqp_khr_gles31_TestExpectations
similarity index 100%
rename from src/tests/deqp_support/deqp_khr_gles31_test_expectations.txt
rename to src/tests/deqp_support/deqp_khr_gles31_TestExpectations
diff --git a/src/tests/deqp_support/deqp_khr_gles32_test_expectations.txt b/src/tests/deqp_support/deqp_khr_gles32_TestExpectations
similarity index 100%
rename from src/tests/deqp_support/deqp_khr_gles32_test_expectations.txt
rename to src/tests/deqp_support/deqp_khr_gles32_TestExpectations
diff --git a/src/tests/deqp_support/deqp_khr_gles3_test_expectations.txt b/src/tests/deqp_support/deqp_khr_gles3_TestExpectations
similarity index 100%
rename from src/tests/deqp_support/deqp_khr_gles3_test_expectations.txt
rename to src/tests/deqp_support/deqp_khr_gles3_TestExpectations