blob: 563480dc6bf75c22c2be51e791b5b3c3a00a6921 [file] [log] [blame]
//
// 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.
//
// APPLE_clip_distance_test.cpp:
// Test for APPLE_clip_distance
//
#include "tests/test_utils/ShaderExtensionTest.h"
namespace
{
const char EXTPragma[] = "#extension GL_APPLE_clip_distance : require\n";
// Shader using gl_ClipDistance
const char ESSL100_APPLEClipDistanceShader1[] =
R"(
uniform vec4 uPlane;
attribute vec4 aPosition;
void main()
{
gl_Position = aPosition;
gl_ClipDistance[1] = dot(aPosition, uPlane);
})";
// Shader redeclares gl_ClipDistance
const char ESSL100_APPLEClipDistanceShader2[] =
R"(
uniform vec4 uPlane;
attribute vec4 aPosition;
varying highp float gl_ClipDistance[4];
void main()
{
gl_Position = aPosition;
gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane);
gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane);
})";
class APPLEClipDistanceTest : public sh::ShaderExtensionTest
{
public:
void InitializeCompiler() { InitializeCompiler(SH_GLSL_130_OUTPUT); }
void InitializeCompiler(ShShaderOutput shaderOutputType)
{
DestroyCompiler();
mCompiler = sh::ConstructCompiler(GL_VERTEX_SHADER, testing::get<0>(GetParam()),
shaderOutputType, &mResources);
ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
}
testing::AssertionResult TestShaderCompile(const char *pragma)
{
const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma,
testing::get<2>(GetParam())};
ShCompileOptions compileOptions = {};
compileOptions.objectCode = true;
compileOptions.variables = true;
bool success = sh::Compile(mCompiler, shaderStrings, 3, compileOptions);
if (success)
{
return ::testing::AssertionSuccess() << "Compilation success";
}
return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler);
}
};
// Extension flag is required to compile properly. Expect failure when it is
// not present.
TEST_P(APPLEClipDistanceTest, CompileFailsWithoutExtension)
{
mResources.APPLE_clip_distance = 0;
InitializeCompiler();
EXPECT_FALSE(TestShaderCompile(EXTPragma));
}
// Extension directive is required to compile properly. Expect failure when
// it is not present.
TEST_P(APPLEClipDistanceTest, CompileFailsWithExtensionWithoutPragma)
{
mResources.APPLE_clip_distance = 1;
InitializeCompiler();
EXPECT_FALSE(TestShaderCompile(""));
}
// With extension flag and extension directive, compiling succeeds.
// Also test that the extension directive state is reset correctly.
TEST_P(APPLEClipDistanceTest, CompileSucceedsWithExtensionAndPragma)
{
mResources.APPLE_clip_distance = 1;
mResources.MaxClipDistances = 8;
InitializeCompiler();
EXPECT_TRUE(TestShaderCompile(EXTPragma));
// Test reset functionality.
EXPECT_FALSE(TestShaderCompile(""));
EXPECT_TRUE(TestShaderCompile(EXTPragma));
}
#if defined(ANGLE_ENABLE_VULKAN)
// With extension flag and extension directive, compiling using TranslatorVulkan succeeds.
TEST_P(APPLEClipDistanceTest, CompileSucceedsVulkan)
{
mResources.APPLE_clip_distance = 1;
mResources.MaxClipDistances = 8;
InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT);
EXPECT_TRUE(TestShaderCompile(EXTPragma));
}
// Test that the SPIR-V gen path can compile a shader when this extension is not supported.
TEST_P(APPLEClipDistanceTest, CompileSucceedsWithoutExtSupportVulkan)
{
mResources.APPLE_clip_distance = 0;
mResources.MaxClipDistances = 0;
mResources.MaxCullDistances = 0;
InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT);
constexpr char kNoClipCull[] = R"(
void main()
{
gl_Position = vec4(0);
})";
const char *shaderStrings[] = {kNoClipCull};
ShCompileOptions compileOptions = {};
compileOptions.objectCode = true;
bool success = sh::Compile(mCompiler, shaderStrings, 1, compileOptions);
if (success)
{
::testing::AssertionSuccess() << "Compilation success";
}
else
{
::testing::AssertionFailure() << sh::GetInfoLog(mCompiler);
}
EXPECT_TRUE(success);
}
#endif
#if defined(ANGLE_ENABLE_METAL)
// With extension flag and extension directive, compiling using TranslatorMetalDirect succeeds.
TEST_P(APPLEClipDistanceTest, CompileSucceedsMetal)
{
mResources.APPLE_clip_distance = 1;
mResources.MaxClipDistances = 8;
InitializeCompiler(SH_MSL_METAL_OUTPUT);
EXPECT_TRUE(TestShaderCompile(EXTPragma));
}
#endif
#if defined(ANGLE_ENABLE_METAL_SPIRV)
// With extension flag and extension directive, compiling using TranslatorMetal succeeds.
TEST_P(APPLEClipDistanceTest, CompileSucceedsMetalSPIRV)
{
mResources.APPLE_clip_distance = 1;
mResources.MaxClipDistances = 8;
InitializeCompiler(SH_SPIRV_METAL_OUTPUT);
EXPECT_TRUE(TestShaderCompile(EXTPragma));
}
#endif
// The SL #version 100 shaders that are correct work similarly
// in both GL2 and GL3, with and without the version string.
INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders,
APPLEClipDistanceTest,
Combine(Values(SH_GLES2_SPEC),
Values(sh::ESSLVersion100),
Values(ESSL100_APPLEClipDistanceShader1,
ESSL100_APPLEClipDistanceShader2)));
} // anonymous namespace