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::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::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 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(&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 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 +# import +# import + +namespace rx +{ +namespace mtl +{ +inline void setOwnerWithIdentity(id resource, task_id_token_t identityToken) +{ + if (identityToken != TASK_ID_TOKEN_NULL) + { + kern_return_t kr = [(id)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> +class Buffer final : public Resource, + public WrappedObject>, + public std::enable_shared_from_this { 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 -void InvokeCPUMemSync(ContextMtl *context, mtl::BlitCommandEncoder *blitEncoder, T *resource) +void InvokeCPUMemSync(ContextMtl *context, + mtl::BlitCommandEncoder *blitEncoder, + const std::shared_ptr &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 -void EnsureCPUMemWillBeSynced(ContextMtl *context, T *resource) +void EnsureCPUMemWillBeSynced(ContextMtl *context, const std::shared_ptr &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> RenderPipelineCache::createRenderPipelineState( ContextMtl *context, const RenderPipelineDesc &originalDesc, @@ -1005,23 +1061,10 @@ void ToObjC(const RenderPassStencilAttachmentDesc &desc, // Convert to Objective-C desc: AutoObjCObj 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> CreateShaderLibrary( bool enableFastMath, AutoObjCPtr *error); -AutoObjCPtr> CreateShaderLibraryFromBinary( - id metalDevice, +AutoObjCPtr> CreateShaderLibraryFromBinary(id metalDevice, const uint8_t *binarySource, size_t binarySourceLen, - NSDictionary *substitutionDictionary, AutoObjCPtr *error); bool SupportsAppleGPUFamily(id 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