blob: 546dde6d2a90b66a59fb16e0a56855e27e4e4d17 [file] [log] [blame]
//
// Copyright 2018 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.
//
// ANGLE_draw_id.cpp:
// Test for ANGLE_draw_id extension
//
#include "GLSLANG/ShaderLang.h"
#include "angle_gl.h"
#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"
#include "gtest/gtest.h"
#include "tests/test_utils/compiler_test.h"
using namespace sh;
class EmulateGLDrawIDTest : public MatchOutputCodeTest
{
public:
EmulateGLDrawIDTest()
: MatchOutputCodeTest(GL_VERTEX_SHADER, SH_VARIABLES, SH_GLSL_COMPATIBILITY_OUTPUT)
{
getResources()->ANGLE_multi_draw = 1;
}
protected:
void CheckCompileFailure(const std::string &shaderString, const char *expectedError = nullptr)
{
std::string translatedCode;
std::string infoLog;
bool success = compileTestShader(GL_VERTEX_SHADER, SH_GLES2_SPEC,
SH_GLSL_COMPATIBILITY_OUTPUT, shaderString, getResources(),
SH_VARIABLES, &translatedCode, &infoLog);
EXPECT_FALSE(success);
if (expectedError)
{
EXPECT_TRUE(infoLog.find(expectedError) != std::string::npos);
}
}
};
// Check that compilation fails if the compile option to emulate gl_DrawID
// is not set
TEST_F(EmulateGLDrawIDTest, RequiresEmulation)
{
CheckCompileFailure(
"#extension GL_ANGLE_multi_draw : require\n"
"void main() {\n"
" gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
"}\n",
"extension is not supported");
}
// Check that compiling with emulation with gl_DrawID works with different shader versions
TEST_F(EmulateGLDrawIDTest, CheckCompile)
{
const std::string shaderString =
"#extension GL_ANGLE_multi_draw : require\n"
"void main() {\n"
" gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
"}\n";
compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
compile("#version 100\n" + shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
compile("#version 300 es\n" + shaderString,
SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
}
// Check that gl_DrawID is properly emulated
TEST_F(EmulateGLDrawIDTest, EmulatesUniform)
{
addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
addOutputType(SH_ESSL_OUTPUT);
#ifdef ANGLE_ENABLE_VULKAN
addOutputType(SH_GLSL_VULKAN_OUTPUT);
#endif
#ifdef ANGLE_ENABLE_HLSL
addOutputType(SH_HLSL_3_0_OUTPUT);
addOutputType(SH_HLSL_3_0_OUTPUT);
#endif
const std::string &shaderString =
"#extension GL_ANGLE_multi_draw : require\n"
"void main() {\n"
" gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
"}\n";
compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
EXPECT_TRUE(notFoundInCode("gl_DrawID"));
EXPECT_TRUE(foundInCode("angle_DrawID"));
EXPECT_TRUE(notFoundInCode("GL_ANGLE_multi_draw"));
EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_DrawID"));
EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_DrawID"));
#ifdef ANGLE_ENABLE_VULKAN
EXPECT_TRUE(
foundInCode(SH_GLSL_VULKAN_OUTPUT, "uniform defaultUniforms\n{\n int angle_DrawID;"));
#endif
#ifdef ANGLE_ENABLE_HLSL
EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_DrawID : register"));
EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_DrawID : register"));
#endif
}
// Check that a user-defined "gl_DrawID" is not permitted
TEST_F(EmulateGLDrawIDTest, DisallowsUserDefinedGLDrawID)
{
// Check that it is not permitted without the extension
CheckCompileFailure(
"uniform int gl_DrawID;\n"
"void main() {\n"
" gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
CheckCompileFailure(
"void main() {\n"
" int gl_DrawID = 0;\n"
" gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
// Check that it is not permitted with the extension
CheckCompileFailure(
"#extension GL_ANGLE_multi_draw : require\n"
"uniform int gl_DrawID;\n"
"void main() {\n"
" gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
CheckCompileFailure(
"#extension GL_ANGLE_multi_draw : require\n"
"void main() {\n"
" int gl_DrawID = 0;\n"
" gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
"}\n",
"reserved built-in name");
}
// gl_DrawID is translated to angle_DrawID internally. Check that a user-defined
// angle_DrawID is permitted
TEST_F(EmulateGLDrawIDTest, AllowsUserDefinedANGLEDrawID)
{
addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
addOutputType(SH_ESSL_OUTPUT);
#ifdef ANGLE_ENABLE_VULKAN
addOutputType(SH_GLSL_VULKAN_OUTPUT);
#endif
#ifdef ANGLE_ENABLE_HLSL
addOutputType(SH_HLSL_3_0_OUTPUT);
addOutputType(SH_HLSL_3_0_OUTPUT);
#endif
const std::string &shaderString =
"#extension GL_ANGLE_multi_draw : require\n"
"uniform int angle_DrawID;\n"
"void main() {\n"
" gl_Position = vec4(float(angle_DrawID + gl_DrawID), 0.0, 0.0, 1.0);\n"
"}\n";
compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
// " angle_DrawID" (note the space) should appear exactly twice:
// once in the declaration and once in the body.
// The user-defined angle_DrawID should be decorated
EXPECT_TRUE(foundInCode(" angle_DrawID", 2));
}