// // Copyright 2019 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_base_vertex_base_instance.cpp: // Test for ANGLE_base_vertex_base_instance 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 EmulateGLBaseVertexBaseInstanceTest : public MatchOutputCodeTest { public: EmulateGLBaseVertexBaseInstanceTest() : MatchOutputCodeTest(GL_VERTEX_SHADER, SH_GLSL_COMPATIBILITY_OUTPUT) { ShCompileOptions defaultCompileOptions = {}; setDefaultCompileOptions(defaultCompileOptions); getResources()->ANGLE_base_vertex_base_instance_shader_builtin = 1; } protected: void CheckCompileFailure(const std::string &shaderString, const char *expectedError = nullptr, ShCompileOptions *compileOptions = nullptr) { ShCompileOptions options = {}; if (compileOptions != nullptr) { options = *compileOptions; } std::string translatedCode; std::string infoLog; bool success = compileTestShader(GL_VERTEX_SHADER, SH_GLES3_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT, shaderString, getResources(), options, &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_BaseVertex and gl_BaseInstance // is not set TEST_F(EmulateGLBaseVertexBaseInstanceTest, RequiresEmulation) { CheckCompileFailure( "#version 300 es\n" "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" "void main() {\n" " gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n" "}\n", "extension is not supported"); } // Check that compiling with emulation with gl_BaseVertex and gl_BaseInstance works TEST_F(EmulateGLBaseVertexBaseInstanceTest, CheckCompile) { const std::string shaderString = "#version 300 es\n" "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" "void main() {\n" " gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n" "}\n"; ShCompileOptions compileOptions = {}; compileOptions.objectCode = true; compileOptions.emulateGLBaseVertexBaseInstance = true; compile(shaderString, compileOptions); } // Check that compiling with the old extension doesn't work TEST_F(EmulateGLBaseVertexBaseInstanceTest, CheckCompileOldExtension) { const std::string shaderString = "#version 300 es\n" "#extension GL_ANGLE_base_vertex_base_instance : require\n" "void main() {\n" " gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n" "}\n"; ShCompileOptions compileOptions = {}; compileOptions.objectCode = true; compileOptions.emulateGLBaseVertexBaseInstance = true; CheckCompileFailure(shaderString, "extension is not supported", &compileOptions); } // Check that gl_BaseVertex and gl_BaseInstance is properly emulated TEST_F(EmulateGLBaseVertexBaseInstanceTest, EmulatesUniform) { addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT); addOutputType(SH_ESSL_OUTPUT); #ifdef ANGLE_ENABLE_VULKAN addOutputType(SH_SPIRV_VULKAN_OUTPUT); #endif #ifdef ANGLE_ENABLE_HLSL addOutputType(SH_HLSL_3_0_OUTPUT); addOutputType(SH_HLSL_3_0_OUTPUT); #endif const std::string &shaderString = "#version 300 es\n" "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" "void main() {\n" " gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n" "}\n"; ShCompileOptions compileOptions = {}; compileOptions.objectCode = true; compileOptions.emulateGLBaseVertexBaseInstance = true; compile(shaderString, compileOptions); EXPECT_TRUE(notFoundInCode("gl_BaseVertex")); EXPECT_TRUE(foundInCode("angle_BaseVertex")); EXPECT_TRUE(notFoundInCode("gl_BaseInstance")); EXPECT_TRUE(foundInCode("angle_BaseInstance")); EXPECT_TRUE(notFoundInCode("GL_ANGLE_base_vertex_base_instance_shader_builtin")); EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_BaseVertex")); EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_BaseInstance")); EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_BaseVertex")); EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_BaseInstance")); #ifdef ANGLE_ENABLE_HLSL EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_BaseVertex : register")); EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_BaseInstance : register")); #endif } // Check that a user-defined "gl_BaseVertex" or "gl_BaseInstance" is not permitted TEST_F(EmulateGLBaseVertexBaseInstanceTest, DisallowsUserDefinedGLDrawID) { // Check that it is not permitted without the extension CheckCompileFailure( "#version 300 es\n" "uniform int gl_BaseVertex;\n" "void main() {\n" " gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); CheckCompileFailure( "#version 300 es\n" "uniform int gl_BaseInstance;\n" "void main() {\n" " gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); CheckCompileFailure( "#version 300 es\n" "void main() {\n" " int gl_BaseVertex = 0;\n" " gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); CheckCompileFailure( "#version 300 es\n" "void main() {\n" " int gl_BaseInstance = 0;\n" " gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); // Check that it is not permitted with the extension CheckCompileFailure( "#version 300 es\n" "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" "uniform int gl_BaseVertex;\n" "void main() {\n" " gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); CheckCompileFailure( "#version 300 es\n" "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" "uniform int gl_BaseInstance;\n" "void main() {\n" " gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); CheckCompileFailure( "#version 300 es\n" "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" "void main() {\n" " int gl_BaseVertex = 0;\n" " gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); CheckCompileFailure( "#version 300 es\n" "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" "void main() {\n" " int gl_BaseInstance = 0;\n" " gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); } // gl_BaseVertex and gl_BaseInstance are translated to angle_BaseVertex and angle_BaseInstance // internally. Check that a user-defined angle_BaseVertex or angle_BaseInstance is permitted TEST_F(EmulateGLBaseVertexBaseInstanceTest, AllowsUserDefinedANGLEDrawID) { addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT); addOutputType(SH_ESSL_OUTPUT); #ifdef ANGLE_ENABLE_VULKAN addOutputType(SH_SPIRV_VULKAN_OUTPUT); #endif #ifdef ANGLE_ENABLE_HLSL addOutputType(SH_HLSL_3_0_OUTPUT); addOutputType(SH_HLSL_3_0_OUTPUT); #endif const std::string &shaderString = "#version 300 es\n" "#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n" "uniform int angle_BaseVertex;\n" "uniform int angle_BaseInstance;\n" "void main() {\n" " gl_Position = vec4(\n" " float(angle_BaseVertex + gl_BaseVertex),\n" " float(angle_BaseInstance + gl_BaseInstance),\n" " 0.0, 1.0);\n" "}\n"; ShCompileOptions compileOptions = {}; compileOptions.objectCode = true; compileOptions.emulateGLBaseVertexBaseInstance = true; compile(shaderString, compileOptions); // " angle_BaseVertex" (note the space) should appear exactly twice: // once in the declaration and once in the body. // The user-defined angle_BaseVertex should be decorated EXPECT_TRUE(foundInCode(" angle_BaseVertex", 2)); EXPECT_TRUE(foundInCode(" angle_BaseInstance", 2)); }