Metal: Implement sampler object & shadow compare mode

Note: GL_TEXTURE_COMPARE_MODE=GL_NONE is not supported on shadow sampler
for now.

Bug: angleproject:2634
Change-Id: I470bad6322e78ef1408e4334e1e778821df7cbf1
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2433332
Commit-Queue: Le Hoang Quyen <le.hoang.q@gmail.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>
This commit is contained in:
Le Hoang Quyen 2020-09-27 15:27:12 +08:00 коммит произвёл Commit Bot
Родитель f037cdc446
Коммит 9ff58e264a
20 изменённых файлов: 246 добавлений и 36 удалений

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

@ -154,7 +154,10 @@ std::vector<std::string> Extensions::getStrings() const
return extensionStrings;
}
Limitations::Limitations() = default;
Limitations::Limitations() = default;
Limitations::Limitations(const Limitations &other) = default;
Limitations &Limitations::operator=(const Limitations &other) = default;
static bool GetFormatSupportBase(const TextureCapsMap &textureCaps,
const GLenum *requiredFormats,

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

@ -681,6 +681,9 @@ const ExtensionInfoMap &GetExtensionInfoMap();
struct Limitations
{
Limitations();
Limitations(const Limitations &other);
Limitations &operator=(const Limitations &other);
// Renderer doesn't support gl_FrontFacing in fragment shaders
bool noFrontFacingSupport = false;
@ -709,6 +712,10 @@ struct Limitations
// D3D does not support vertex attribute aliasing
bool noVertexAttributeAliasing = false;
// Renderer doesn't support GL_TEXTURE_COMPARE_MODE=GL_NONE on a shadow sampler.
// TODO(http://anglebug.com/5231): add validation code to front-end.
bool noShadowSamplerCompareModeNone = false;
};
struct TypePrecision

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

@ -29,6 +29,8 @@ _metal_backend_sources = [
"RenderBufferMtl.mm",
"RenderTargetMtl.h",
"RenderTargetMtl.mm",
"SamplerMtl.h",
"SamplerMtl.mm",
"ShaderMtl.h",
"ShaderMtl.mm",
"SurfaceMtl.h",

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

@ -21,6 +21,7 @@
#include "libANGLE/renderer/metal/QueryMtl.h"
#include "libANGLE/renderer/metal/RenderBufferMtl.h"
#include "libANGLE/renderer/metal/RenderTargetMtl.h"
#include "libANGLE/renderer/metal/SamplerMtl.h"
#include "libANGLE/renderer/metal/ShaderMtl.h"
#include "libANGLE/renderer/metal/SyncMtl.h"
#include "libANGLE/renderer/metal/TextureMtl.h"
@ -1010,9 +1011,7 @@ TransformFeedbackImpl *ContextMtl::createTransformFeedback(const gl::TransformFe
// Sampler object creation
SamplerImpl *ContextMtl::createSampler(const gl::SamplerState &state)
{
// NOTE(hqle): ES 3.0
UNIMPLEMENTED();
return nullptr;
return new SamplerMtl(state);
}
// Program Pipeline object creation

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

@ -107,7 +107,7 @@ class DisplayMtl : public DisplayImpl
gl::Caps getNativeCaps() const;
const gl::TextureCapsMap &getNativeTextureCaps() const;
const gl::Extensions &getNativeExtensions() const;
const gl::Limitations &getNativeLimitations() const { return mNativeLimitations; }
const gl::Limitations &getNativeLimitations() const;
const angle::FeaturesMtl &getFeatures() const { return mFeatures; }
// Check whether either of the specified iOS or Mac GPU family is supported

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

@ -247,7 +247,12 @@ ShareGroupImpl *DisplayMtl::createShareGroup()
gl::Version DisplayMtl::getMaxSupportedESVersion() const
{
return mtl::kMaxSupportedGLVersion;
// NOTE(hqle): Supports GLES 3.0 on iOS GPU family 4+ for now.
if (supportsEitherGPUFamily(4, 1))
{
return mtl::kMaxSupportedGLVersion;
}
return gl::Version(2, 0);
}
gl::Version DisplayMtl::getMaxConformantESVersion() const
@ -456,6 +461,12 @@ const gl::Extensions &DisplayMtl::getNativeExtensions() const
return mNativeExtensions;
}
const gl::Limitations &DisplayMtl::getNativeLimitations() const
{
ensureCapsInitialized();
return mNativeLimitations;
}
void DisplayMtl::ensureCapsInitialized() const
{
if (mCapsInitialized)
@ -600,6 +611,9 @@ void DisplayMtl::ensureCapsInitialized() const
// GL_APPLE_clip_distance
mNativeCaps.maxClipDistances = 8;
// Metal doesn't support GL_TEXTURE_COMPARE_MODE=GL_NONE for shadow samplers
mNativeLimitations.noShadowSamplerCompareModeNone = true;
}
void DisplayMtl::initializeExtensions() const

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

@ -985,17 +985,34 @@ angle::Result ProgramMtl::updateTextures(const gl::Context *glContext,
{
GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
gl::Texture *texture = completeTextures[textureUnit];
gl::Sampler *sampler = contextMtl->getState().getSampler(textureUnit);
uint32_t textureSlot = mslBinding.textureBinding + arrayElement;
uint32_t samplerSlot = mslBinding.samplerBinding + arrayElement;
if (!texture)
{
ANGLE_TRY(contextMtl->getIncompleteTexture(glContext, textureType, &texture));
}
const gl::SamplerState *samplerState =
sampler ? &sampler->getSamplerState() : &texture->getSamplerState();
TextureMtl *textureMtl = mtl::GetImpl(texture);
if (samplerBinding.format == gl::SamplerFormat::Shadow)
{
// http://anglebug.com/5107
// Metal doesn't support a compare mode where sampling a shadow sampler could
// return a same value as if sampling from a normal sampler.
// Supporting this could require hacking spirv-cross to change sample_compare()
// to sample().
if (ANGLE_UNLIKELY(samplerState->getCompareMode() != GL_COMPARE_REF_TO_TEXTURE))
{
ERR() << "GL_TEXTURE_COMPARE_MODE != GL_COMPARE_REF_TO_TEXTURE is not "
"supported";
ANGLE_MTL_TRY(contextMtl,
samplerState->getCompareMode() == GL_COMPARE_REF_TO_TEXTURE);
}
}
ANGLE_TRY(textureMtl->bindToShader(glContext, cmdEncoder, shaderType, textureSlot,
samplerSlot));
ANGLE_TRY(textureMtl->bindToShader(glContext, cmdEncoder, shaderType, sampler,
textureSlot, samplerSlot));
} // for array elements
} // for sampler bindings
} // for shader types

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

@ -0,0 +1,44 @@
//
// Copyright 2020 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.
//
// SamplerMtl.h:
// Defines the class interface for SamplerMtl, implementing SamplerImpl.
//
#ifndef LIBANGLE_RENDERER_METAL_SAMPLERMTL_H_
#define LIBANGLE_RENDERER_METAL_SAMPLERMTL_H_
#include "libANGLE/renderer/SamplerImpl.h"
#include "libANGLE/renderer/metal/mtl_common.h"
namespace rx
{
class ContextMtl;
class SamplerMtl : public SamplerImpl
{
public:
SamplerMtl(const gl::SamplerState &state);
~SamplerMtl() override;
void onDestroy(const gl::Context *context) override;
angle::Result syncState(const gl::Context *context, const bool dirty) override;
const mtl::AutoObjCPtr<id<MTLSamplerState>> &getSampler(ContextMtl *contextMtl);
private:
mtl::AutoObjCPtr<id<MTLSamplerState>> mSamplerState;
// Cache compare mode & func to detect their changes and let ProgramMtl verify that
// GL_TEXTURE_COMPARE_MODE is not GL_NONE on a shadow sampler.
// TODO(http://anglebug.com/5231): Once the validation code is implemented on front-end, it
// is possible to remove these caching.
GLenum mCompareMode = 0;
GLenum mCompareFunc = 0;
};
} // namespace rx
#endif

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

@ -0,0 +1,67 @@
//
// Copyright 2020 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.
//
// SamplerMtl.mm:
// Defines the class interface for SamplerMtl, implementing SamplerImpl.
//
#include "libANGLE/renderer/metal/SamplerMtl.h"
#include "common/debug.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/metal/ContextMtl.h"
#include "libANGLE/renderer/metal/DisplayMtl.h"
#include "libANGLE/renderer/metal/mtl_state_cache.h"
namespace rx
{
SamplerMtl::SamplerMtl(const gl::SamplerState &state) : SamplerImpl(state) {}
SamplerMtl::~SamplerMtl() = default;
void SamplerMtl::onDestroy(const gl::Context *context)
{
mSamplerState = nil;
}
const mtl::AutoObjCPtr<id<MTLSamplerState>> &SamplerMtl::getSampler(ContextMtl *contextMtl)
{
if (!mSamplerState)
{
DisplayMtl *displayMtl = contextMtl->getDisplay();
mtl::SamplerDesc samplerDesc(mState);
mSamplerState =
displayMtl->getStateCache().getSamplerState(displayMtl->getMetalDevice(), samplerDesc);
}
return mSamplerState;
}
angle::Result SamplerMtl::syncState(const gl::Context *context, const bool dirty)
{
if (dirty)
{
// Recreate sampler
mSamplerState = nil;
if (mCompareMode != mState.getCompareMode() || mCompareFunc != mState.getCompareFunc())
{
ContextMtl *contextMtl = mtl::GetImpl(context);
mCompareMode = mState.getCompareMode();
mCompareFunc = mState.getCompareFunc();
// Tell context to rebind textures so that ProgramMtl has a chance to verify
// depth texture compare mode.
contextMtl->invalidateCurrentTextures();
}
}
return angle::Result::Continue;
}
} // namespace rx

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

@ -162,6 +162,7 @@ class TextureMtl : public TextureImpl
angle::Result bindToShader(const gl::Context *context,
mtl::RenderCommandEncoder *cmdEncoder,
gl::ShaderType shaderType,
gl::Sampler *sampler, /** nullable */
int textureSlotIndex,
int samplerSlotIndex);

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

@ -20,6 +20,7 @@
#include "libANGLE/renderer/metal/ContextMtl.h"
#include "libANGLE/renderer/metal/DisplayMtl.h"
#include "libANGLE/renderer/metal/FrameBufferMtl.h"
#include "libANGLE/renderer/metal/SamplerMtl.h"
#include "libANGLE/renderer/metal/SurfaceMtl.h"
#include "libANGLE/renderer/metal/mtl_common.h"
#include "libANGLE/renderer/metal/mtl_format_utils.h"
@ -536,9 +537,11 @@ angle::Result TextureMtl::createNativeTexture(const gl::Context *context,
}
encoder->copyTexture(imageToTransfer, 0, mtl::kZeroNativeMipLevel, mNativeTexture,
face, actualMip, imageToTransfer->arrayLength(), 1);
}
imageToTransfer = nullptr;
// Invalidate texture image definition at this index so that we can make it a
// view of the native texture at this index later.
imageToTransfer = nullptr;
}
}
}
@ -1001,14 +1004,14 @@ angle::Result TextureMtl::generateMipmap(const gl::Context *context)
}
const mtl::FormatCaps &caps = mFormat.getCaps();
//
bool sRGB = mFormat.actualInternalFormat().colorEncoding == GL_SRGB;
if (caps.writable && mState.getType() == gl::TextureType::_3D)
{
// http://anglebug.com/4921.
// Use compute for 3D mipmap generation.
ANGLE_TRY(ensureNativeLevelViewsCreated());
bool sRGB = mFormat.metalFormat == MTLPixelFormatRGBA8Unorm_sRGB ||
mFormat.metalFormat == MTLPixelFormatBGRA8Unorm_sRGB;
ANGLE_TRY(contextMtl->getDisplay()->getUtils().generateMipmapCS(contextMtl, mNativeTexture,
sRGB, &mNativeLevelViews));
}
@ -1195,16 +1198,34 @@ angle::Result TextureMtl::syncState(const gl::Context *context,
angle::Result TextureMtl::bindToShader(const gl::Context *context,
mtl::RenderCommandEncoder *cmdEncoder,
gl::ShaderType shaderType,
gl::Sampler *sampler,
int textureSlotIndex,
int samplerSlotIndex)
{
ASSERT(mNativeTexture);
float minLodClamp = std::max(0.f, mState.getSamplerState().getMinLod());
float maxLodClamp = mState.getSamplerState().getMaxLod();
float minLodClamp;
float maxLodClamp;
id<MTLSamplerState> samplerState;
if (!sampler)
{
samplerState = mMetalSamplerState;
minLodClamp = mState.getSamplerState().getMinLod();
maxLodClamp = mState.getSamplerState().getMaxLod();
}
else
{
SamplerMtl *samplerMtl = mtl::GetImpl(sampler);
samplerState = samplerMtl->getSampler(mtl::GetImpl(context));
minLodClamp = sampler->getSamplerState().getMinLod();
maxLodClamp = sampler->getSamplerState().getMaxLod();
}
minLodClamp = std::max(minLodClamp, 0.f);
cmdEncoder->setTexture(shaderType, mNativeTexture, textureSlotIndex);
cmdEncoder->setSamplerState(shaderType, mMetalSamplerState, minLodClamp, maxLodClamp,
cmdEncoder->setSamplerState(shaderType, samplerState, minLodClamp, maxLodClamp,
samplerSlotIndex);
return angle::Result::Continue;
@ -1453,9 +1474,14 @@ angle::Result TextureMtl::setPerSliceSubImage(const gl::Context *context,
if (unpackBuffer)
{
uintptr_t offset = reinterpret_cast<uintptr_t>(pixels);
if (offset % mFormat.actualAngleFormat().pixelBytes)
GLuint minRowPitch;
ANGLE_CHECK_GL_MATH(contextMtl, internalFormat.computeRowPitch(
type, static_cast<GLint>(mtlArea.size.width),
/** aligment */ 1, /** rowLength */ 0, &minRowPitch));
if (offset % mFormat.actualAngleFormat().pixelBytes || pixelsRowPitch < minRowPitch)
{
// offset is not divisible by pixelByte, use convertAndSetPerSliceSubImage() function.
// offset is not divisible by pixelByte or the source row pitch is smaller than minimum
// row pitch, use convertAndSetPerSliceSubImage() function.
return convertAndSetPerSliceSubImage(context, slice, mtlArea, internalFormat, type,
pixelsAngleFormat, pixelsRowPitch,
pixelsDepthPitch, unpackBuffer, pixels, image);

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

@ -69,6 +69,7 @@ class Image;
PROC(MemoryObject) \
PROC(Query) \
PROC(Program) \
PROC(Sampler) \
PROC(Semaphore) \
PROC(Texture) \
PROC(TransformFeedback) \
@ -93,6 +94,8 @@ class BufferMtl;
class VertexArrayMtl;
class TextureMtl;
class ProgramMtl;
class SamplerMtl;
class TransformFeedbackMtl;
ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_MTL_OBJECT)

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

@ -63,6 +63,7 @@ struct Format : public FormatBase
Format() = default;
const gl::InternalFormat &intendedInternalFormat() const;
const gl::InternalFormat &actualInternalFormat() const;
bool valid() const { return metalFormat != MTLPixelFormatInvalid; }
bool hasDepthAndStencilBits() const

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

@ -132,6 +132,11 @@ const gl::InternalFormat &Format::intendedInternalFormat() const
return gl::GetSizedInternalFormatInfo(intendedAngleFormat().glInternalFormat);
}
const gl::InternalFormat &Format::actualInternalFormat() const
{
return gl::GetSizedInternalFormatInfo(actualAngleFormat().glInternalFormat);
}
bool Format::needConversion(angle::FormatID srcFormatId) const
{
if ((srcFormatId == angle::FormatID::BC1_RGB_UNORM_BLOCK &&

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

@ -110,6 +110,9 @@ struct alignas(4) SamplerDesc
uint8_t mipFilter : 2;
uint8_t maxAnisotropy : 5;
// Use uint8_t instead of MTLCompareFunction to compact space
uint8_t compareFunction : 3;
};
struct VertexAttributeDesc

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

@ -74,6 +74,7 @@ MTLSamplerDescriptor *ToObjC(const SamplerDesc &desc)
ANGLE_OBJC_CP_PROPERTY(objCDesc, desc, magFilter);
ANGLE_OBJC_CP_PROPERTY(objCDesc, desc, mipFilter);
ANGLE_OBJC_CP_PROPERTY(objCDesc, desc, maxAnisotropy);
ANGLE_OBJC_CP_PROPERTY(objCDesc, desc, compareFunction);
return [objCDesc ANGLE_MTL_AUTORELEASE];
}
@ -459,6 +460,8 @@ SamplerDesc::SamplerDesc(const gl::SamplerState &glState) : SamplerDesc()
mipFilter = GetMipmapFilter(glState.getMinFilter());
maxAnisotropy = static_cast<uint32_t>(glState.getMaxAnisotropy());
compareFunction = GetCompareFunc(glState.getCompareFunc());
}
SamplerDesc &SamplerDesc::operator=(const SamplerDesc &src)
@ -478,6 +481,8 @@ void SamplerDesc::reset()
mipFilter = MTLSamplerMipFilterNearest;
maxAnisotropy = 1;
compareFunction = MTLCompareFunctionNever;
}
bool SamplerDesc::operator==(const SamplerDesc &rhs) const
@ -488,7 +493,9 @@ bool SamplerDesc::operator==(const SamplerDesc &rhs) const
ANGLE_PROP_EQ(*this, rhs, minFilter) && ANGLE_PROP_EQ(*this, rhs, magFilter) &&
ANGLE_PROP_EQ(*this, rhs, mipFilter) &&
ANGLE_PROP_EQ(*this, rhs, maxAnisotropy);
ANGLE_PROP_EQ(*this, rhs, maxAnisotropy) &&
ANGLE_PROP_EQ(*this, rhs, compareFunction);
}
size_t SamplerDesc::hash() const

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

@ -539,6 +539,9 @@ TEST_P(SRGBTextureTestES3, GenerateMipmaps)
{
ANGLE_SKIP_TEST_IF(IsOpenGL() && ((IsIntel() && IsOSX()) || IsAMD()));
// http://anglebug.com/5108
ANGLE_SKIP_TEST_IF(IsMetal());
auto createAndReadBackTexture = [this](GLenum internalFormat, const GLColor &color) {
constexpr GLsizei width = 128;
constexpr GLsizei height = 128;
@ -593,7 +596,7 @@ TEST_P(SRGBTextureTestES3, GenerateMipmaps)
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(SRGBTextureTest);
ANGLE_INSTANTIATE_TEST_ES3(SRGBTextureTestES3);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(SRGBTextureTest, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(SRGBTextureTestES3, ES3_METAL());
} // namespace angle

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

@ -88,5 +88,5 @@ TEST_P(SamplersTest, InvalidOverTextureSamplerMaxAnisotropyExt)
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
// Samplers are only supported on ES3.
ANGLE_INSTANTIATE_TEST_ES3(SamplersTest);
ANGLE_INSTANTIATE_TEST_ES3_AND(SamplersTest, ES3_METAL());
} // namespace angle

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

@ -5827,7 +5827,7 @@ ANGLE_INSTANTIATE_TEST_ES2(StateChangeRenderTest);
ANGLE_INSTANTIATE_TEST_ES3(StateChangeTestES3);
ANGLE_INSTANTIATE_TEST_ES3(StateChangeRenderTestES3);
ANGLE_INSTANTIATE_TEST_ES2(SimpleStateChangeTest);
ANGLE_INSTANTIATE_TEST_ES3(SimpleStateChangeTestES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(SimpleStateChangeTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3(ImageRespecificationTest);
ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestES31);
ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31);

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

@ -4461,6 +4461,9 @@ TEST_P(Texture2DTestES3, TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1)
// ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
ANGLE_SKIP_TEST_IF(IsOSX() && IsDesktopOpenGL());
// http://anglebug.com/5187
ANGLE_SKIP_TEST_IF(IsOSX() && IsMetal());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTexture2D);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 1, 1, 0, 8, nullptr);
@ -4478,6 +4481,9 @@ TEST_P(Texture2DTestES3, TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)
// ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
ANGLE_SKIP_TEST_IF(IsOSX() && IsDesktopOpenGL());
// http://anglebug.com/5187
ANGLE_SKIP_TEST_IF(IsOSX() && IsMetal());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTexture2D);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_ETC2, 1, 1, 0, 8, nullptr);
@ -6584,7 +6590,7 @@ TEST_P(Texture2DTestES3, UnpackOverlappingRowsFromUnpackBuffer)
ANGLE_SKIP_TEST_IF(IsD3D11());
// Incorrect rendering results seen on OSX AMD.
ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD());
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsOSX() && IsAMD());
const GLuint width = 8u;
const GLuint height = 8u;
@ -8086,17 +8092,19 @@ ANGLE_INSTANTIATE_TEST_ES2(Texture2DTestWithDrawScale);
ANGLE_INSTANTIATE_TEST_ES2(Sampler2DAsFunctionParameterTest);
ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayTest);
ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayAsFunctionParameterTest);
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3, WithAllocateNonZeroMemory(ES3_VULKAN()));
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3,
WithAllocateNonZeroMemory(ES3_VULKAN()),
ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES31(Texture2DTestES31PPO);
ANGLE_INSTANTIATE_TEST_ES3(Texture2DBaseMaxTestES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DBaseMaxTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES2(Texture3DTestES2);
ANGLE_INSTANTIATE_TEST_ES3(Texture3DTestES3);
ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerAlpha1TestES3);
ANGLE_INSTANTIATE_TEST_ES3(Texture2DUnsignedIntegerAlpha1TestES3);
ANGLE_INSTANTIATE_TEST_ES3(ShadowSamplerPlusSampler3DTestES3);
ANGLE_INSTANTIATE_TEST_ES3(SamplerTypeMixTestES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture3DTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DIntegerAlpha1TestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DUnsignedIntegerAlpha1TestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(ShadowSamplerPlusSampler3DTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(SamplerTypeMixTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DArrayTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3(TextureSizeTextureArrayTest);
ANGLE_INSTANTIATE_TEST_ES3_AND(TextureSizeTextureArrayTest, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructTest);
ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAsFunctionParameterTest);
ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructArrayAsFunctionParameterTest);
@ -8113,9 +8121,9 @@ ANGLE_INSTANTIATE_TEST(Texture2DRGTest,
ANGLE_ALL_TEST_PLATFORMS_ES3,
ES2_EMULATE_COPY_TEX_IMAGE(),
ES3_EMULATE_COPY_TEX_IMAGE());
ANGLE_INSTANTIATE_TEST_ES3(Texture2DFloatTestES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DFloatTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES2(Texture2DFloatTestES2);
ANGLE_INSTANTIATE_TEST_ES3(TextureCubeTestES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(TextureCubeTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DIntegerTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(TextureCubeIntegerTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(TextureCubeIntegerEdgeTestES3, ES3_METAL());
@ -8123,7 +8131,7 @@ ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DIntegerProjectiveOffsetTestES3, ES3_META
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DArrayIntegerTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture3DIntegerTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(Texture2DDepthTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(PBOCompressedTextureTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ETC1CompressedTextureTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(PBOCompressedTextureTest, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(ETC1CompressedTextureTest, ES3_METAL());
} // anonymous namespace