First Commit

This commit is contained in:
2025-02-06 22:24:29 +08:00
parent ed7df4c81e
commit 7539e6a53c
18116 changed files with 6181499 additions and 0 deletions

View File

@@ -0,0 +1,316 @@
//
// Copyright (C) 2016 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include <gtest/gtest.h>
#include "TestFixture.h"
namespace glslangtest {
namespace {
using CompileToAstTest = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileToAstTestNV = GlslangTest<::testing::TestWithParam<std::string>>;
TEST_P(CompileToAstTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::OpenGL, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::AST);
}
// Compiling GLSL to SPIR-V under OpenGL semantics (NV extensions enabled).
TEST_P(CompileToAstTestNV, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::OpenGL, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::AST);
}
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileToAstTest,
::testing::ValuesIn(std::vector<std::string>({
"sample.frag",
"sample.vert",
"decls.frag",
"specExamples.frag",
"specExamples.vert",
"versionsClean.frag",
"versionsClean.vert",
"versionsErrors.frag",
"versionsErrors.vert",
"100.frag",
"100samplerExternal.frag",
"120.vert",
"120.frag",
"130.vert",
"130.frag",
"140.vert",
"140.frag",
"150.vert",
"150.geom",
"150.frag",
"precision.frag",
"precision.vert",
"nonSquare.vert",
"matrixError.vert",
"cppSimple.vert",
"cppIndent.vert",
"cppIntMinOverNegativeOne.frag",
"cppMerge.frag",
"cppNest.vert",
"cppBad.vert",
"cppBad2.vert",
"cppBad3.vert",
"cppBad4.vert",
"cppBad5.vert",
"cppComplexExpr.vert",
"cppDeepNest.frag",
"cppPassMacroName.frag",
"cppRelaxSkipTokensErrors.vert",
"badChars.frag",
"pointCoord.frag",
"array.frag",
"array100.frag",
"comment.frag",
"300.vert",
"300.frag",
"300BuiltIns.frag",
"300layout.vert",
"300layout.frag",
"300operations.frag",
"300block.frag",
"300samplerExternal.frag",
"300samplerExternalYUV.frag",
"310.comp",
"310.vert",
"310.geom",
"310.frag",
"310.tesc",
"310.tese",
"310implicitSizeArrayError.vert",
"310.inheritMemory.frag",
"310AofA.vert",
"310runtimeArray.vert",
"320.comp",
"320.vert",
"320.geom",
"320.frag",
"320.tesc",
"320.tese",
"330.frag",
"330comp.frag",
"constErrors.frag",
"constFold.frag",
"constFoldIntMin.frag",
"errors.frag",
"forwardRef.frag",
"uint.frag",
"switch.frag",
"tokenLength.vert",
"100Limits.vert",
"100scope.vert",
"110scope.vert",
"300scope.vert",
"400.frag",
"400.vert",
"410.vert",
"420.comp",
"420.frag",
"420.vert",
"420.geom",
"420_size_gl_in.geom",
"430scope.vert",
"lineContinuation100.vert",
"lineContinuation.vert",
"numeral.frag",
"400.geom",
"400.tesc",
"400.tese",
"410.tesc",
"420.tesc",
"420.tese",
"410.geom",
"430.vert",
"430.comp",
"430AofA.frag",
"435.vert",
"440.vert",
"440.frag",
"450.vert",
"450.geom",
"450.tesc",
"450.tese",
"450.frag",
"450.comp",
"460.frag",
"460.vert",
"dce.frag",
"atomic_uint.frag",
"implicitInnerAtomicUint.frag",
"aggOps.frag",
"always-discard.frag",
"always-discard2.frag",
"conditionalDiscard.frag",
"conversion.frag",
"dataOut.frag",
"dataOutIndirect.frag",
"deepRvalue.frag",
"depthOut.frag",
"discard-dce.frag",
"doWhileLoop.frag",
"earlyReturnDiscard.frag",
"flowControl.frag",
"forLoop.frag",
"functionCall.frag",
"functionSemantics.frag",
"length.frag",
"localAggregates.frag",
"loops.frag",
"loopsArtificial.frag",
"matrix.frag",
"matrix2.frag",
"mixedArrayDecls.frag",
"nonuniform.frag",
"newTexture.frag",
"Operations.frag",
"overlongLiteral.frag",
"prepost.frag",
"runtimeArray.vert",
"simpleFunctionCall.frag",
"stringToDouble.vert",
"struct.error.frag",
"structAssignment.frag",
"structDeref.frag",
"structure.frag",
"swizzle.frag",
"invalidSwizzle.vert",
"syntaxError.frag",
"test.frag",
"texture.frag",
"tokenPaste.vert",
"types.frag",
"uniformArray.frag",
"variableArrayIndex.frag",
"varyingArray.frag",
"varyingArrayIndirect.frag",
"voidFunction.frag",
"whileLoop.frag",
"nonVulkan.frag",
"negativeArraySize.comp",
"precise.tesc",
"precise_struct_block.vert",
"maxClipDistances.vert",
"findFunction.frag",
"noMatchingFunction.frag",
"constantUnaryConversion.comp",
"xfbUnsizedArray.error.vert",
"xfbUnsizedArray.error.tese",
"glsl.140.layoutOffset.error.vert",
"glsl.430.layoutOffset.error.vert",
"glsl.450.subgroup.frag",
"glsl.450.subgroup.geom",
"glsl.450.subgroup.tesc",
"glsl.450.subgroup.tese",
"glsl.450.subgroup.vert",
"glsl.450.subgroupArithmetic.comp",
"glsl.450.subgroupBasic.comp",
"glsl.450.subgroupBallot.comp",
"glsl.450.subgroupBallotNeg.comp",
"glsl.450.subgroupClustered.comp",
"glsl.450.subgroupClusteredNeg.comp",
"glsl.450.subgroupPartitioned.comp",
"glsl.450.subgroupShuffle.comp",
"glsl.450.subgroupShuffleRelative.comp",
"glsl.450.subgroupQuad.comp",
"glsl.450.subgroupVote.comp",
"glsl.460.subgroup.mesh",
"glsl.460.subgroup.task",
"glsl.460.subgroup.rahit",
"glsl.460.subgroup.rcall",
"glsl.460.subgroup.rchit",
"glsl.460.subgroup.rgen",
"glsl.460.subgroup.rint",
"glsl.460.subgroup.rmiss",
"glsl.es300.layoutOffset.error.vert",
"glsl.es320.subgroup.frag",
"glsl.es320.subgroup.geom",
"glsl.es320.subgroup.tesc",
"glsl.es320.subgroup.tese",
"glsl.es320.subgroup.vert",
"glsl.es320.subgroupArithmetic.comp",
"glsl.es320.subgroupBasic.comp",
"glsl.es320.subgroupBallot.comp",
"glsl.es320.subgroupBallotNeg.comp",
"glsl.es320.subgroupClustered.comp",
"glsl.es320.subgroupClusteredNeg.comp",
"glsl.es320.subgroupPartitioned.comp",
"glsl.es320.subgroupShuffle.comp",
"glsl.es320.subgroupShuffleRelative.comp",
"glsl.es320.subgroupQuad.comp",
"glsl.es320.subgroupVote.comp",
"terminate.frag",
"terminate.vert",
"negativeWorkGroupSize.comp",
"textureoffset_sampler2darrayshadow.vert",
"atomicAdd.comp",
"GL_ARB_gpu_shader5.u2i.vert",
"textureQueryLOD.frag",
"atomicCounterARBOps.vert",
"GL_EXT_shader_integer_mix.vert",
"GL_ARB_draw_instanced.vert",
"GL_ARB_fragment_coord_conventions.vert",
"GL_ARB_bindless_texture.frag",
"BestMatchFunction.vert",
"EndStreamPrimitive.geom",
"floatBitsToInt.vert",
"coord_conventions.frag",
"gl_FragCoord.frag"
})),
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileToAstTestNV,
::testing::ValuesIn(std::vector<std::string>({
"nvShaderNoperspectiveInterpolation.frag",
})),
FileNameAsCustomTestSuffix
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest

View File

@@ -0,0 +1,67 @@
//
// Copyright (C) 2016 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include <algorithm>
#include <gtest/gtest.h>
#include "glslang/Public/ResourceLimits.h"
#include "TestFixture.h"
namespace glslangtest {
namespace {
using DefaultResourceTest = GlslangTest<::testing::Test>;
TEST_F(DefaultResourceTest, FromFile)
{
const std::string path = GlobalTestSettings.testRoot + "/baseResults/test.conf";
std::string expectedConfig;
tryLoadFile(path, "expected resource limit", &expectedConfig);
const std::string realConfig = GetDefaultTBuiltInResourceString();
ASSERT_EQ(expectedConfig, realConfig);
}
TEST_F(DefaultResourceTest, UnrecognizedLimit)
{
const std::string defaultConfig = GetDefaultTBuiltInResourceString();
testing::internal::CaptureStdout();
TBuiltInResource resources;
DecodeResourceLimits(&resources, const_cast<char*>(defaultConfig.c_str()));
std::string output = testing::internal::GetCapturedStdout();
ASSERT_EQ(output.find("unrecognized limit"), std::string::npos);
}
} // anonymous namespace
} // namespace glslangtest

121
externals/glslang/gtests/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,121 @@
# Copyright (C) 2020 The Khronos Group 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:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 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.
#
# Neither the name of The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
# COPYRIGHT HOLDERS OR 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.
if(BUILD_TESTING)
if(TARGET gmock)
message(STATUS "Google Mock found - building tests")
set(TEST_SOURCES
# Framework related source files
${CMAKE_CURRENT_SOURCE_DIR}/Initializer.h
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings.h
${CMAKE_CURRENT_SOURCE_DIR}/TestFixture.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestFixture.h
# Test related source files
${CMAKE_CURRENT_SOURCE_DIR}/AST.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BuiltInResource.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Common.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Config.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/HexFloat.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Hlsl.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Link.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Link.FromFile.Vk.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Pp.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Spv.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/VkRelaxed.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/GlslMapIO.FromFile.cpp)
if(ENABLE_SPVREMAPPER)
set(TEST_SOURCES ${TEST_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/Remap.FromFile.cpp)
endif()
add_executable(glslangtests ${TEST_SOURCES})
glslang_pch(glslangtests ${CMAKE_CURRENT_SOURCE_DIR}/pch.h)
set_property(TARGET glslangtests PROPERTY FOLDER tests)
glslang_set_link_args(glslangtests)
if(ENABLE_GLSLANG_INSTALL)
install(TARGETS glslangtests EXPORT glslang-targets)
# Backward compatibility
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/glslangtestsTargets.cmake" "
message(WARNING \"Using `glslangtestsTargets.cmake` is deprecated: use `find_package(glslang)` to find glslang CMake targets.\")
if (NOT TARGET glslang::glslangtests)
include(\"${CMAKE_INSTALL_FULL_LIBDIR}/cmake/${PROJECT_NAME}/glslang-targets.cmake\")
endif()
add_library(glslangtests ALIAS glslang::glslangtests)
")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/glslangtestsTargets.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
endif()
set(GLSLANG_TEST_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../Test")
# Supply a default test root directory, so that manual testing
# doesn't have to specify the --test-root option in the normal
# case that you want to use the tests from the same source tree.
target_compile_definitions(glslangtests
PRIVATE GLSLANG_TEST_DIRECTORY="${GLSLANG_TEST_DIRECTORY}")
target_include_directories(glslangtests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}
${gmock_SOURCE_DIR}/include
${gtest_SOURCE_DIR}/include)
if(ENABLE_OPT)
target_include_directories(glslangtests
PRIVATE ${spirv-tools_SOURCE_DIR}/include
)
endif()
set(LIBRARIES
glslang OSDependent OGLCompiler glslang
SPIRV glslang-default-resource-limits)
if(ENABLE_SPVREMAPPER)
set(LIBRARIES ${LIBRARIES} SPVRemapper)
endif()
if(ENABLE_HLSL)
set(LIBRARIES ${LIBRARIES} HLSL)
endif()
target_link_libraries(glslangtests PRIVATE ${LIBRARIES} gmock)
add_test(NAME glslang-gtests
COMMAND glslangtests --test-root "${GLSLANG_TEST_DIRECTORY}")
endif()
endif()

165
externals/glslang/gtests/Common.cpp vendored Normal file
View File

@@ -0,0 +1,165 @@
// Copyright (c) 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cstdint>
#include <gmock/gmock.h>
#include "glslang/Include/Common.h"
namespace {
TEST(IsPow2, Int_Negative) {
EXPECT_EQ(false, glslang::IsPow2(-5));
EXPECT_EQ(false, glslang::IsPow2(-1));
EXPECT_EQ(false, glslang::IsPow2(INT_MIN));
EXPECT_EQ(false, glslang::IsPow2(int64_t(-10)));
}
TEST(IsPow2, Zero) {
EXPECT_EQ(false, glslang::IsPow2(0));
EXPECT_EQ(false, glslang::IsPow2(0u));
EXPECT_EQ(false, glslang::IsPow2(0));
EXPECT_EQ(false, glslang::IsPow2(uint64_t(0)));
EXPECT_EQ(false, glslang::IsPow2(int64_t(0)));
}
TEST(IsPow2, Int_Positive_PowersOf2) {
EXPECT_EQ(true, glslang::IsPow2(1));
EXPECT_EQ(true, glslang::IsPow2(2));
EXPECT_EQ(true, glslang::IsPow2(4));
EXPECT_EQ(true, glslang::IsPow2(8));
EXPECT_EQ(true, glslang::IsPow2(16));
EXPECT_EQ(true, glslang::IsPow2(32768));
EXPECT_EQ(true, glslang::IsPow2(65536));
EXPECT_EQ(true, glslang::IsPow2(2147483648));
}
TEST(IsPow2, Int_Positive_NonPowersOf2) {
EXPECT_EQ(false, glslang::IsPow2(3));
EXPECT_EQ(false, glslang::IsPow2(5));
EXPECT_EQ(false, glslang::IsPow2(2147483647));
}
TEST(IsPow2, Uint_Positive_PowersOf2) {
EXPECT_EQ(true, glslang::IsPow2(1u));
EXPECT_EQ(true, glslang::IsPow2(2u));
EXPECT_EQ(true, glslang::IsPow2(4u));
EXPECT_EQ(true, glslang::IsPow2(8u));
EXPECT_EQ(true, glslang::IsPow2(16u));
EXPECT_EQ(true, glslang::IsPow2(32768u));
EXPECT_EQ(true, glslang::IsPow2(65536u));
EXPECT_EQ(true, glslang::IsPow2(2147483648u));
}
TEST(IsPow2, Uint_Positive_NonPowersOf2) {
EXPECT_EQ(false, glslang::IsPow2(3u));
EXPECT_EQ(false, glslang::IsPow2(5u));
EXPECT_EQ(false, glslang::IsPow2(2147483647u));
}
TEST(IntLog2, Int) {
EXPECT_EQ(0, glslang::IntLog2(1));
EXPECT_EQ(1, glslang::IntLog2(2));
EXPECT_EQ(2, glslang::IntLog2(4));
EXPECT_EQ(3, glslang::IntLog2(8));
EXPECT_EQ(4, glslang::IntLog2(16));
EXPECT_EQ(5, glslang::IntLog2(32));
EXPECT_EQ(6, glslang::IntLog2(64));
EXPECT_EQ(7, glslang::IntLog2(128));
EXPECT_EQ(8, glslang::IntLog2(256));
EXPECT_EQ(9, glslang::IntLog2(512));
EXPECT_EQ(10, glslang::IntLog2(1024));
EXPECT_EQ(11, glslang::IntLog2(2048));
EXPECT_EQ(12, glslang::IntLog2(0x1000));
EXPECT_EQ(13, glslang::IntLog2(0x2000));
EXPECT_EQ(14, glslang::IntLog2(0x4000));
EXPECT_EQ(15, glslang::IntLog2(0x8000));
EXPECT_EQ(16, glslang::IntLog2(0x10000));
EXPECT_EQ(17, glslang::IntLog2(0x20000));
EXPECT_EQ(18, glslang::IntLog2(0x40000));
EXPECT_EQ(19, glslang::IntLog2(0x80000));
EXPECT_EQ(20, glslang::IntLog2(0x100000));
EXPECT_EQ(21, glslang::IntLog2(0x200000));
EXPECT_EQ(22, glslang::IntLog2(0x400000));
EXPECT_EQ(23, glslang::IntLog2(0x800000));
EXPECT_EQ(24, glslang::IntLog2(0x1000000));
EXPECT_EQ(25, glslang::IntLog2(0x2000000));
EXPECT_EQ(26, glslang::IntLog2(0x4000000));
EXPECT_EQ(27, glslang::IntLog2(0x8000000));
EXPECT_EQ(28, glslang::IntLog2(0x10000000));
EXPECT_EQ(29, glslang::IntLog2(0x20000000));
EXPECT_EQ(30, glslang::IntLog2(0x40000000));
}
TEST(IntLog2, Uint) {
EXPECT_EQ(0, glslang::IntLog2(1u));
EXPECT_EQ(1, glslang::IntLog2(2u));
EXPECT_EQ(2, glslang::IntLog2(4u));
EXPECT_EQ(3, glslang::IntLog2(8u));
EXPECT_EQ(4, glslang::IntLog2(16u));
EXPECT_EQ(5, glslang::IntLog2(32u));
EXPECT_EQ(6, glslang::IntLog2(64u));
EXPECT_EQ(7, glslang::IntLog2(128u));
EXPECT_EQ(8, glslang::IntLog2(256u));
EXPECT_EQ(9, glslang::IntLog2(512u));
EXPECT_EQ(10, glslang::IntLog2(1024u));
EXPECT_EQ(11, glslang::IntLog2(2048u));
EXPECT_EQ(12, glslang::IntLog2(0x1000u));
EXPECT_EQ(13, glslang::IntLog2(0x2000u));
EXPECT_EQ(14, glslang::IntLog2(0x4000u));
EXPECT_EQ(15, glslang::IntLog2(0x8000u));
EXPECT_EQ(16, glslang::IntLog2(0x10000u));
EXPECT_EQ(17, glslang::IntLog2(0x20000u));
EXPECT_EQ(18, glslang::IntLog2(0x40000u));
EXPECT_EQ(19, glslang::IntLog2(0x80000u));
EXPECT_EQ(20, glslang::IntLog2(0x100000u));
EXPECT_EQ(21, glslang::IntLog2(0x200000u));
EXPECT_EQ(22, glslang::IntLog2(0x400000u));
EXPECT_EQ(23, glslang::IntLog2(0x800000u));
EXPECT_EQ(24, glslang::IntLog2(0x1000000u));
EXPECT_EQ(25, glslang::IntLog2(0x2000000u));
EXPECT_EQ(26, glslang::IntLog2(0x4000000u));
EXPECT_EQ(27, glslang::IntLog2(0x8000000u));
EXPECT_EQ(28, glslang::IntLog2(0x10000000u));
EXPECT_EQ(29, glslang::IntLog2(0x20000000u));
EXPECT_EQ(30, glslang::IntLog2(0x40000000u));
EXPECT_EQ(31, glslang::IntLog2(0x80000000u));
}
TEST(IntLog2, Int64) {
EXPECT_EQ(0, glslang::IntLog2(int64_t(1)));
EXPECT_EQ(1, glslang::IntLog2(int64_t(2)));
EXPECT_EQ(2, glslang::IntLog2(int64_t(4)));
EXPECT_EQ(3, glslang::IntLog2(int64_t(8)));
EXPECT_EQ(30, glslang::IntLog2(int64_t(0x40000000u)));
EXPECT_EQ(31, glslang::IntLog2(int64_t(0x80000000u)));
EXPECT_EQ(32, glslang::IntLog2(int64_t(0x10000) * int64_t(0x10000)));
EXPECT_EQ(48, glslang::IntLog2(int64_t(0x10000) * int64_t(0x10000) * int64_t(0x10000)));
EXPECT_EQ(62, glslang::IntLog2(int64_t(0x10000) * int64_t(0x10000) * int64_t(0x10000) * int64_t(0x4000)));
}
TEST(IntLog2, Uint64) {
EXPECT_EQ(0, glslang::IntLog2(uint64_t(1)));
EXPECT_EQ(1, glslang::IntLog2(uint64_t(2)));
EXPECT_EQ(2, glslang::IntLog2(uint64_t(4)));
EXPECT_EQ(3, glslang::IntLog2(uint64_t(8)));
EXPECT_EQ(30, glslang::IntLog2(uint64_t(0x40000000u)));
EXPECT_EQ(31, glslang::IntLog2(uint64_t(0x80000000u)));
EXPECT_EQ(32, glslang::IntLog2(uint64_t(0x10000) * uint64_t(0x10000)));
EXPECT_EQ(48, glslang::IntLog2(uint64_t(0x10000) * uint64_t(0x10000) * uint64_t(0x10000)));
EXPECT_EQ(62, glslang::IntLog2(uint64_t(0x10000) * uint64_t(0x10000) * uint64_t(0x10000) * uint64_t(0x4000)));
EXPECT_EQ(63, glslang::IntLog2(uint64_t(0x10000) * uint64_t(0x10000) * uint64_t(0x10000) * uint64_t(0x8000)));
}
} // anonymous namespace

View File

@@ -0,0 +1,108 @@
//
// Copyright (C) 2016 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include "glslang/Public/ResourceLimits.h"
#include "TestFixture.h"
namespace glslangtest {
namespace {
struct TestCaseSpec {
std::string input;
std::string config;
std::string output;
EShMessages controls;
};
using ConfigTest = GlslangTest<::testing::TestWithParam<TestCaseSpec>>;
TEST_P(ConfigTest, FromFile)
{
TestCaseSpec testCase = GetParam();
GlslangResult result;
result.validationResult = true;
// Get the contents for input shader and limit configurations.
std::string shaderContents, configContents;
tryLoadFile(GlobalTestSettings.testRoot + "/" + testCase.input, "input", &shaderContents);
tryLoadFile(GlobalTestSettings.testRoot + "/" + testCase.config, "limits config", &configContents);
// Decode limit configurations.
TBuiltInResource resources = {};
{
const size_t len = configContents.size();
char* configChars = new char[len + 1];
memcpy(configChars, configContents.data(), len);
configChars[len] = 0;
DecodeResourceLimits(&resources, configChars);
delete[] configChars;
}
// Compile the shader.
glslang::TShader shader(GetShaderStage(GetSuffix(testCase.input)));
compile(&shader, shaderContents, "", testCase.controls, &resources);
result.shaderResults.push_back(
{testCase.input, shader.getInfoLog(), shader.getInfoDebugLog()});
// Link the shader.
glslang::TProgram program;
program.addShader(&shader);
program.link(testCase.controls);
result.linkingOutput = program.getInfoLog();
result.linkingError = program.getInfoDebugLog();
std::ostringstream stream;
outputResultToStream(&stream, result, testCase.controls);
// Check with expected results.
const std::string expectedOutputFname =
GlobalTestSettings.testRoot + "/baseResults/" + testCase.output;
std::string expectedOutput;
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname);
}
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, ConfigTest,
::testing::ValuesIn(std::vector<TestCaseSpec>({
{"specExamples.vert", "baseResults/test.conf", "specExamplesConf.vert.out", (EShMessages)(EShMsgAST | EShMsgCascadingErrors)},
{"100Limits.vert", "100.conf", "100LimitsConf.vert.out", EShMsgCascadingErrors},
}))
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest

View File

@@ -0,0 +1,355 @@
//
// Copyright (C) 2016-2017 Google, Inc.
// Copyright (C) 2020 The Khronos Group 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
//
#include <algorithm>
#include <gtest/gtest.h>
#include "TestFixture.h"
#include "glslang/MachineIndependent/iomapper.h"
#include "glslang/MachineIndependent/reflection.h"
#ifndef GLSLANG_WEB
namespace glslangtest {
namespace {
struct IoMapData {
std::vector<std::string> fileNames;
Semantics semantics;
};
using GlslMapIOTest = GlslangTest <::testing::TestWithParam<IoMapData>>;
template<class T>
std::string interfaceName(T symbol) {
return symbol.getType()->getBasicType() == glslang::EbtBlock ? std::string(symbol.getType()->getTypeName().c_str()) : symbol.name;
}
bool verifyIOMapping(std::string& linkingError, glslang::TProgram& program) {
bool success = true;
// Verify IO Mapping by generating reflection for each stage individually
// and comparing layout qualifiers on the results
int reflectionOptions = EShReflectionDefault;
//reflectionOptions |= EShReflectionStrictArraySuffix;
//reflectionOptions |= EShReflectionBasicArraySuffix;
reflectionOptions |= EShReflectionIntermediateIO;
reflectionOptions |= EShReflectionSeparateBuffers;
reflectionOptions |= EShReflectionAllBlockVariables;
//reflectionOptions |= EShReflectionUnwrapIOBlocks;
success &= program.buildReflection(reflectionOptions);
// check that the reflection output from the individual stages all makes sense..
std::vector<glslang::TReflection> stageReflections;
for (int s = 0; s < EShLangCount; ++s) {
if (program.getIntermediate((EShLanguage)s)) {
stageReflections.emplace_back((EShReflectionOptions)reflectionOptions, (EShLanguage)s, (EShLanguage)s);
success &= stageReflections.back().addStage((EShLanguage)s, *program.getIntermediate((EShLanguage)s));
}
}
// check that input/output locations match between stages
auto it = stageReflections.begin();
auto nextIt = it + 1;
for (; nextIt != stageReflections.end(); it++, nextIt++) {
int numOut = it->getNumPipeOutputs();
std::map<std::string, const glslang::TObjectReflection*> pipeOut;
for (int i = 0; i < numOut; i++) {
const glslang::TObjectReflection& out = it->getPipeOutput(i);
std::string name = interfaceName(out);
pipeOut[name] = &out;
}
int numIn = nextIt->getNumPipeInputs();
for (int i = 0; i < numIn; i++) {
auto in = nextIt->getPipeInput(i);
std::string name = interfaceName(in);
auto out = pipeOut.find(name);
if (out != pipeOut.end()) {
auto inQualifier = in.getType()->getQualifier();
auto outQualifier = out->second->getType()->getQualifier();
success &= outQualifier.layoutLocation == inQualifier.layoutLocation;
}
else {
if (!in.getType()->isStruct()) {
bool found = false;
for (auto outIt : pipeOut) {
if (outIt.second->getType()->isStruct()) {
unsigned int baseLoc = outIt.second->getType()->getQualifier().hasLocation() ?
outIt.second->getType()->getQualifier().layoutLocation :
std::numeric_limits<unsigned int>::max();
for (size_t j = 0; j < outIt.second->getType()->getStruct()->size(); j++) {
baseLoc = (*outIt.second->getType()->getStruct())[j].type->getQualifier().hasLocation() ?
(*outIt.second->getType()->getStruct())[j].type->getQualifier().layoutLocation : baseLoc;
if (baseLoc != std::numeric_limits<unsigned int>::max()) {
if (baseLoc == in.getType()->getQualifier().layoutLocation) {
found = true;
break;
}
baseLoc += glslang::TIntermediate::computeTypeLocationSize(*(*outIt.second->getType()->getStruct())[j].type, EShLangVertex);
}
}
if (found) {
break;
}
}
}
success &= found;
}
else {
unsigned int baseLoc = in.getType()->getQualifier().hasLocation() ? in.getType()->getQualifier().layoutLocation : -1;
for (size_t j = 0; j < in.getType()->getStruct()->size(); j++) {
baseLoc = (*in.getType()->getStruct())[j].type->getQualifier().hasLocation() ?
(*in.getType()->getStruct())[j].type->getQualifier().layoutLocation : baseLoc;
if (baseLoc != std::numeric_limits<unsigned int>::max()) {
bool isMemberFound = false;
for (auto outIt : pipeOut) {
if (baseLoc == outIt.second->getType()->getQualifier().layoutLocation) {
isMemberFound = true;
break;
}
}
if (!isMemberFound) {
success &= false;
break;
}
baseLoc += glslang::TIntermediate::computeTypeLocationSize(*(*in.getType()->getStruct())[j].type, EShLangVertex);
}
}
}
}
}
}
// compare uniforms in each stage to the program
{
int totalUniforms = program.getNumUniformVariables();
std::map<std::string, const glslang::TObjectReflection*> programUniforms;
for (int i = 0; i < totalUniforms; i++) {
const glslang::TObjectReflection& uniform = program.getUniform(i);
std::string name = interfaceName(uniform);
programUniforms[name] = &uniform;
}
it = stageReflections.begin();
for (; it != stageReflections.end(); it++) {
int numUniform = it->getNumUniforms();
std::map<std::string, glslang::TObjectReflection> uniforms;
for (int i = 0; i < numUniform; i++) {
glslang::TObjectReflection uniform = it->getUniform(i);
std::string name = interfaceName(uniform);
auto programUniform = programUniforms.find(name);
if (programUniform != programUniforms.end()) {
auto stageQualifier = uniform.getType()->getQualifier();
auto programQualifier = programUniform->second->getType()->getQualifier();
success &= stageQualifier.layoutLocation == programQualifier.layoutLocation;
success &= stageQualifier.layoutBinding == programQualifier.layoutBinding;
success &= stageQualifier.layoutSet == programQualifier.layoutSet;
}
else {
success &= false;
}
}
}
}
// compare uniform blocks in each stage to the program table
{
int totalUniforms = program.getNumUniformBlocks();
std::map<std::string, const glslang::TObjectReflection*> programUniforms;
for (int i = 0; i < totalUniforms; i++) {
const glslang::TObjectReflection& uniform = program.getUniformBlock(i);
std::string name = interfaceName(uniform);
programUniforms[name] = &uniform;
}
it = stageReflections.begin();
for (; it != stageReflections.end(); it++) {
int numUniform = it->getNumUniformBlocks();
std::map<std::string, glslang::TObjectReflection> uniforms;
for (int i = 0; i < numUniform; i++) {
glslang::TObjectReflection uniform = it->getUniformBlock(i);
std::string name = interfaceName(uniform);
auto programUniform = programUniforms.find(name);
if (programUniform != programUniforms.end()) {
auto stageQualifier = uniform.getType()->getQualifier();
auto programQualifier = programUniform->second->getType()->getQualifier();
success &= stageQualifier.layoutLocation == programQualifier.layoutLocation;
success &= stageQualifier.layoutBinding == programQualifier.layoutBinding;
success &= stageQualifier.layoutSet == programQualifier.layoutSet;
}
else {
success &= false;
}
}
}
}
if (!success) {
linkingError += "Mismatched cross-stage IO\n";
}
return success;
}
TEST_P(GlslMapIOTest, FromFile)
{
const auto& fileNames = GetParam().fileNames;
Semantics semantics = GetParam().semantics;
const size_t fileCount = fileNames.size();
const EShMessages controls = DeriveOptions(Source::GLSL, semantics, Target::BothASTAndSpv);
GlslangResult result;
// Compile each input shader file.
bool success = true;
std::vector<std::unique_ptr<glslang::TShader>> shaders;
for (size_t i = 0; i < fileCount; ++i) {
std::string contents;
tryLoadFile(GlobalTestSettings.testRoot + "/" + fileNames[i],
"input", &contents);
shaders.emplace_back(
new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i]))));
auto* shader = shaders.back().get();
shader->setAutoMapLocations(true);
shader->setAutoMapBindings(true);
if (controls & EShMsgSpvRules) {
if (controls & EShMsgVulkanRules) {
shader->setEnvInput((controls & EShMsgReadHlsl) ? glslang::EShSourceHlsl
: glslang::EShSourceGlsl,
shader->getStage(), glslang::EShClientVulkan, 100);
shader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
shader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0);
} else {
shader->setEnvInput((controls & EShMsgReadHlsl) ? glslang::EShSourceHlsl
: glslang::EShSourceGlsl,
shader->getStage(), glslang::EShClientOpenGL, 100);
shader->setEnvClient(glslang::EShClientOpenGL, glslang::EShTargetOpenGL_450);
shader->setEnvTarget(glslang::EshTargetSpv, glslang::EShTargetSpv_1_0);
}
}
success &= compile(shader, contents, "", controls);
result.shaderResults.push_back(
{ fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog() });
}
// Link all of them.
glslang::TProgram program;
for (const auto& shader : shaders) program.addShader(shader.get());
success &= program.link(controls);
result.linkingOutput = program.getInfoLog();
result.linkingError = program.getInfoDebugLog();
unsigned int stage = 0;
glslang::TIntermediate* firstIntermediate = nullptr;
while (!program.getIntermediate((EShLanguage)stage) && stage < EShLangCount) { stage++; }
firstIntermediate = program.getIntermediate((EShLanguage)stage);
glslang::TDefaultGlslIoResolver resolver(*firstIntermediate);
glslang::TGlslIoMapper ioMapper;
if (success) {
success &= program.mapIO(&resolver, &ioMapper);
result.linkingOutput = program.getInfoLog();
result.linkingError = program.getInfoDebugLog();
}
success &= verifyIOMapping(result.linkingError, program);
result.validationResult = success;
if (success && (controls & EShMsgSpvRules)) {
for (int stage = 0; stage < EShLangCount; ++stage) {
if (program.getIntermediate((EShLanguage)stage)) {
spv::SpvBuildLogger logger;
std::vector<uint32_t> spirv_binary;
options().disableOptimizer = false;
glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage),
spirv_binary, &logger, &options());
std::ostringstream disassembly_stream;
spv::Parameterize();
spv::Disassemble(disassembly_stream, spirv_binary);
result.spirvWarningsErrors += logger.getAllMessages();
result.spirv += disassembly_stream.str();
result.validationResult &= !options().validate || logger.getAllMessages().empty();
}
}
}
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
// Check with expected results.
const std::string expectedOutputFname =
GlobalTestSettings.testRoot + "/baseResults/" + fileNames.front() + ".out";
std::string expectedOutput;
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname,
result.spirvWarningsErrors);
}
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, GlslMapIOTest,
::testing::ValuesIn(std::vector<IoMapData>({
{{"iomap.crossStage.vert", "iomap.crossStage.frag" }, Semantics::OpenGL},
{{"iomap.crossStage.2.vert", "iomap.crossStage.2.geom", "iomap.crossStage.2.frag" }, Semantics::OpenGL},
{{"iomap.blockOutVariableIn.vert", "iomap.blockOutVariableIn.frag"}, Semantics::OpenGL},
{{"iomap.variableOutBlockIn.vert", "iomap.variableOutBlockIn.frag"}, Semantics::OpenGL},
{{"iomap.blockOutVariableIn.2.vert", "iomap.blockOutVariableIn.geom"}, Semantics::OpenGL},
{{"iomap.variableOutBlockIn.2.vert", "iomap.variableOutBlockIn.geom"}, Semantics::OpenGL},
// vulkan semantics
{{"iomap.crossStage.vk.vert", "iomap.crossStage.vk.geom", "iomap.crossStage.vk.frag" }, Semantics::Vulkan},
}))
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest
#endif

1231
externals/glslang/gtests/HexFloat.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,560 @@
//
// Copyright (C) 2016 Google, Inc.
// Copyright (C) 2016 LunarG, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include <gtest/gtest.h>
#include "TestFixture.h"
namespace glslangtest {
namespace {
struct FileNameEntryPointPair {
const char* fileName;
const char* entryPoint;
};
// We are using FileNameEntryPointPair objects as parameters for instantiating
// the template, so the global FileNameAsCustomTestSuffix() won't work since
// it assumes std::string as parameters. Thus, an overriding one here.
std::string FileNameAsCustomTestSuffix(
const ::testing::TestParamInfo<FileNameEntryPointPair>& info) {
std::string name = info.param.fileName;
// A valid test case suffix cannot have '.' and '-' inside.
std::replace(name.begin(), name.end(), '.', '_');
std::replace(name.begin(), name.end(), '-', '_');
return name;
}
using HlslCompileTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslVulkan1_1CompileTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslSpv1_6CompileTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslCompileAndFlattenTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslLegalizeTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslDebugTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslDX9CompatibleTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslLegalDebugTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslNonSemanticShaderDebugInfoTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
// Compiling HLSL to pre-legalized SPIR-V under Vulkan semantics. Expected
// to successfully generate both AST and SPIR-V.
TEST_P(HlslCompileTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::BothASTAndSpv, true, GetParam().entryPoint);
}
TEST_P(HlslVulkan1_1CompileTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_1, glslang::EShTargetSpv_1_3,
Target::BothASTAndSpv, true, GetParam().entryPoint);
}
TEST_P(HlslSpv1_6CompileTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_3, glslang::EShTargetSpv_1_6,
Target::BothASTAndSpv, true, GetParam().entryPoint);
}
TEST_P(HlslCompileAndFlattenTest, FromFile)
{
loadFileCompileFlattenUniformsAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::HLSL, Semantics::Vulkan,
Target::BothASTAndSpv, GetParam().entryPoint);
}
// Compiling HLSL to legal SPIR-V under Vulkan semantics. Expected to
// successfully generate SPIR-V.
TEST_P(HlslLegalizeTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv, true, GetParam().entryPoint,
"/baseLegalResults/", true);
}
// Compiling HLSL to pre-legalized SPIR-V. Expected to successfully generate
// SPIR-V with debug instructions, particularly line info.
TEST_P(HlslDebugTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv, true, GetParam().entryPoint,
"/baseResults/", false, true);
}
TEST_P(HlslDX9CompatibleTest, FromFile)
{
loadFileCompileAndCheckWithOptions(GlobalTestSettings.testRoot, GetParam().fileName, Source::HLSL,
Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::BothASTAndSpv, true,
GetParam().entryPoint, "/baseResults/",
EShMessages::EShMsgHlslDX9Compatible);
}
// Compiling HLSL to legalized SPIR-V with debug instructions. Expected to
// successfully generate SPIR-V with debug instructions preserved through
// legalization, particularly line info.
TEST_P(HlslLegalDebugTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv, true, GetParam().entryPoint,
"/baseResults/", true, true);
}
TEST_P(HlslNonSemanticShaderDebugInfoTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv, true, GetParam().entryPoint, "/baseResults/", false, false, true);
}
// clang-format off
INSTANTIATE_TEST_SUITE_P(
ToSpirv, HlslCompileTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.amend.frag", "f1"},
{"hlsl.aliasOpaque.frag", "main"},
{"hlsl.array.frag", "PixelShaderFunction"},
{"hlsl.array.implicit-size.frag", "PixelShaderFunction"},
{"hlsl.array.multidim.frag", "main"},
{"hlsl.assoc.frag", "PixelShaderFunction"},
{"hlsl.attribute.frag", "PixelShaderFunction"},
{"hlsl.attribute.expression.comp", "main"},
{"hlsl.attributeC11.frag", "main"},
{"hlsl.attributeGlobalBuffer.frag", "main"},
{"hlsl.basic.comp", "main"},
{"hlsl.basic.geom", "main"},
{"hlsl.boolConv.vert", "main"},
{"hlsl.buffer.frag", "PixelShaderFunction"},
{"hlsl.calculatelod.dx10.frag", "main"},
{"hlsl.calculatelodunclamped.dx10.frag", "main"},
{"hlsl.cast.frag", "PixelShaderFunction"},
{"hlsl.cbuffer-identifier.vert", "main"},
{"hlsl.charLit.vert", "main"},
{"hlsl.clip.frag", "main"},
{"hlsl.clipdistance-1.frag", "main"},
{"hlsl.clipdistance-1.geom", "main"},
{"hlsl.clipdistance-1.vert", "main"},
{"hlsl.clipdistance-2.frag", "main"},
{"hlsl.clipdistance-2.geom", "main"},
{"hlsl.clipdistance-2.vert", "main"},
{"hlsl.clipdistance-3.frag", "main"},
{"hlsl.clipdistance-3.geom", "main"},
{"hlsl.clipdistance-3.vert", "main"},
{"hlsl.clipdistance-4.frag", "main"},
{"hlsl.clipdistance-4.geom", "main"},
{"hlsl.clipdistance-4.vert", "main"},
{"hlsl.clipdistance-5.frag", "main"},
{"hlsl.clipdistance-5.vert", "main"},
{"hlsl.clipdistance-6.frag", "main"},
{"hlsl.clipdistance-6.vert", "main"},
{"hlsl.clipdistance-7.frag", "main"},
{"hlsl.clipdistance-7.vert", "main"},
{"hlsl.clipdistance-8.frag", "main"},
{"hlsl.clipdistance-8.vert", "main"},
{"hlsl.clipdistance-9.frag", "main"},
{"hlsl.clipdistance-9.vert", "main"},
{"hlsl.color.hull.tesc", "main"},
{"hlsl.comparison.vec.frag", "main"},
{"hlsl.conditional.frag", "PixelShaderFunction"},
{"hlsl.constantbuffer.frag", "main"},
{"hlsl.constructArray.vert", "main"},
{"hlsl.constructexpr.frag", "main"},
{"hlsl.constructimat.frag", "main"},
{"hlsl.coverage.frag", "main"},
{"hlsl.depthGreater.frag", "PixelShaderFunction"},
{"hlsl.depthLess.frag", "PixelShaderFunction"},
{"hlsl.discard.frag", "PixelShaderFunction"},
{"hlsl.doLoop.frag", "PixelShaderFunction"},
{"hlsl.earlydepthstencil.frag", "main"},
{"hlsl.emptystructreturn.frag", "main"},
{"hlsl.emptystructreturn.vert", "main"},
{"hlsl.emptystructreturn.tesc", "main"},
{"hlsl.emptystruct.init.vert", "main"},
{"hlsl.entry-in.frag", "PixelShaderFunction"},
{"hlsl.entry-out.frag", "PixelShaderFunction"},
{"hlsl.fraggeom.frag", "main"},
{"hlsl.float1.frag", "PixelShaderFunction"},
{"hlsl.float4.frag", "PixelShaderFunction"},
{"hlsl.flatten.return.frag", "main"},
{"hlsl.flattenOpaque.frag", "main"},
{"hlsl.flattenOpaqueInit.vert", "main"},
{"hlsl.flattenOpaqueInitMix.vert", "main"},
{"hlsl.flattenSubset.frag", "main"},
{"hlsl.flattenSubset2.frag", "main"},
{"hlsl.forLoop.frag", "PixelShaderFunction"},
{"hlsl.gather.array.dx10.frag", "main"},
{"hlsl.gather.basic.dx10.frag", "main"},
{"hlsl.gather.basic.dx10.vert", "main"},
{"hlsl.gather.offset.dx10.frag", "main"},
{"hlsl.gather.offsetarray.dx10.frag", "main"},
{"hlsl.gathercmpRGBA.offset.dx10.frag", "main"},
{"hlsl.gatherRGBA.array.dx10.frag", "main"},
{"hlsl.gatherRGBA.basic.dx10.frag", "main"},
{"hlsl.gatherRGBA.offset.dx10.frag", "main"},
{"hlsl.gatherRGBA.offsetarray.dx10.frag", "main"},
{"hlsl.getdimensions.dx10.frag", "main"},
{"hlsl.getdimensions.rw.dx10.frag", "main"},
{"hlsl.getdimensions.dx10.vert", "main"},
{"hlsl.getsampleposition.dx10.frag", "main"},
{"hlsl.global-const-init.frag", "main"},
{"hlsl.gs-hs-mix.tesc", "HSMain"},
{"hlsl.domain.1.tese", "main"},
{"hlsl.domain.2.tese", "main"},
{"hlsl.domain.3.tese", "main"},
{"hlsl.function.frag", "main"},
{"hlsl.hull.1.tesc", "main"},
{"hlsl.hull.2.tesc", "main"},
{"hlsl.hull.3.tesc", "main"},
{"hlsl.hull.4.tesc", "main"},
{"hlsl.hull.5.tesc", "main"},
{"hlsl.hull.6.tesc", "main"},
{"hlsl.hull.void.tesc", "main"},
{"hlsl.hull.ctrlpt-1.tesc", "main"},
{"hlsl.hull.ctrlpt-2.tesc", "main"},
{"hlsl.format.rwtexture.frag", "main"},
{"hlsl.groupid.comp", "main"},
{"hlsl.identifier.sample.frag", "main"},
{"hlsl.if.frag", "PixelShaderFunction"},
{"hlsl.imageload-subvec4.comp", "main"},
{"hlsl.imagefetch-subvec4.comp", "main"},
{"hlsl.implicitBool.frag", "main"},
{"hlsl.inf.vert", "main"},
{"hlsl.inoutquals.frag", "main"},
{"hlsl.inoutquals.negative.frag", "main"},
{"hlsl.init.frag", "ShaderFunction"},
{"hlsl.init2.frag", "main"},
{"hlsl.isfinite.frag", "main"},
{"hlsl.intrinsics.barriers.comp", "ComputeShaderFunction"},
{"hlsl.intrinsics.comp", "ComputeShaderFunction"},
{"hlsl.intrinsics.d3dcolortoubyte4.frag", "main"},
{"hlsl.intrinsics.double.frag", "PixelShaderFunction"},
{"hlsl.intrinsics.f1632.frag", "main"},
{"hlsl.intrinsics.f3216.frag", "main"},
{"hlsl.intrinsics.frag", "main"},
{"hlsl.intrinsic.frexp.frag", "main"},
{"hlsl.intrinsics.lit.frag", "PixelShaderFunction"},
{"hlsl.intrinsics.negative.comp", "ComputeShaderFunction"},
{"hlsl.intrinsics.negative.frag", "PixelShaderFunction"},
{"hlsl.intrinsics.negative.vert", "VertexShaderFunction"},
{"hlsl.intrinsics.promote.frag", "main"},
{"hlsl.intrinsics.promote.down.frag", "main"},
{"hlsl.intrinsics.promote.outputs.frag", "main"},
{"hlsl.layout.frag", "main"},
{"hlsl.layoutOverride.vert", "main"},
{"hlsl.load.2dms.dx10.frag", "main"},
{"hlsl.load.array.dx10.frag", "main"},
{"hlsl.load.basic.dx10.frag", "main"},
{"hlsl.load.basic.dx10.vert", "main"},
{"hlsl.load.buffer.dx10.frag", "main"},
{"hlsl.load.buffer.float.dx10.frag", "main"},
{"hlsl.load.rwbuffer.dx10.frag", "main"},
{"hlsl.load.rwtexture.dx10.frag", "main"},
{"hlsl.load.rwtexture.array.dx10.frag", "main"},
{"hlsl.load.offset.dx10.frag", "main"},
{"hlsl.load.offsetarray.dx10.frag", "main"},
{"hlsl.localStructuredBuffer.comp", "main"},
{"hlsl.logical.binary.frag", "main"},
{"hlsl.logical.binary.vec.frag", "main"},
{"hlsl.logicalConvert.frag", "main"},
{"hlsl.logical.unary.frag", "main"},
{"hlsl.loopattr.frag", "main"},
{"hlsl.matpack-pragma.frag", "main"},
{"hlsl.matpack-pragma-global.frag", "main"},
{"hlsl.mip.operator.frag", "main"},
{"hlsl.mip.negative.frag", "main"},
{"hlsl.mip.negative2.frag", "main"},
{"hlsl.namespace.frag", "main"},
{"hlsl.nonint-index.frag", "main"},
{"hlsl.matNx1.frag", "main"},
{"hlsl.matpack-1.frag", "main"},
{"hlsl.matrixSwizzle.vert", "ShaderFunction"},
{"hlsl.memberFunCall.frag", "main"},
{"hlsl.mintypes.frag", "main"},
{"hlsl.mul-truncate.frag", "main"},
{"hlsl.multiEntry.vert", "RealEntrypoint"},
{"hlsl.multiReturn.frag", "main"},
{"hlsl.matrixindex.frag", "main"},
{"hlsl.nonstaticMemberFunction.frag", "main"},
{"hlsl.numericsuffixes.frag", "main"},
{"hlsl.numthreads.comp", "main_aux2"},
{"hlsl.overload.frag", "PixelShaderFunction"},
{"hlsl.opaque-type-bug.frag", "main"},
{"hlsl.params.default.frag", "main"},
{"hlsl.params.default.negative.frag", "main"},
{"hlsl.partialInit.frag", "PixelShaderFunction"},
{"hlsl.partialFlattenLocal.vert", "main"},
{"hlsl.PointSize.geom", "main"},
{"hlsl.PointSize.vert", "main"},
{"hlsl.pp.vert", "main"},
{"hlsl.pp.line.frag", "main"},
{"hlsl.precise.frag", "main"},
{"hlsl.printf.comp", "main"},
{"hlsl.promote.atomic.frag", "main"},
{"hlsl.promote.binary.frag", "main"},
{"hlsl.promote.vec1.frag", "main"},
{"hlsl.promotions.frag", "main"},
{"hlsl.round.dx10.frag", "main"},
{"hlsl.rw.atomics.frag", "main"},
{"hlsl.rw.bracket.frag", "main"},
{"hlsl.rw.register.frag", "main"},
{"hlsl.rw.scalar.bracket.frag", "main"},
{"hlsl.rw.swizzle.frag", "main"},
{"hlsl.rw.vec2.bracket.frag", "main"},
{"hlsl.sample.array.dx10.frag", "main"},
{"hlsl.sample.basic.dx10.frag", "main"},
{"hlsl.sample.offset.dx10.frag", "main"},
{"hlsl.sample.offsetarray.dx10.frag", "main"},
{"hlsl.samplebias.array.dx10.frag", "main"},
{"hlsl.samplebias.basic.dx10.frag", "main"},
{"hlsl.samplebias.offset.dx10.frag", "main"},
{"hlsl.samplebias.offsetarray.dx10.frag", "main"},
{"hlsl.samplecmp.array.dx10.frag", "main"},
{"hlsl.samplecmp.basic.dx10.frag", "main"},
{"hlsl.samplecmp.dualmode.frag", "main"},
{"hlsl.samplecmp.offset.dx10.frag", "main"},
{"hlsl.samplecmp.offsetarray.dx10.frag", "main"},
{"hlsl.samplecmp.negative.frag", "main"},
{"hlsl.samplecmp.negative2.frag", "main"},
{"hlsl.samplecmplevelzero.array.dx10.frag", "main"},
{"hlsl.samplecmplevelzero.basic.dx10.frag", "main"},
{"hlsl.samplecmplevelzero.offset.dx10.frag", "main"},
{"hlsl.samplecmplevelzero.offsetarray.dx10.frag", "main"},
{"hlsl.samplegrad.array.dx10.frag", "main"},
{"hlsl.samplegrad.basic.dx10.frag", "main"},
{"hlsl.samplegrad.basic.dx10.vert", "main"},
{"hlsl.samplegrad.offset.dx10.frag", "main"},
{"hlsl.samplegrad.offsetarray.dx10.frag", "main"},
{"hlsl.samplelevel.array.dx10.frag", "main"},
{"hlsl.samplelevel.basic.dx10.frag", "main"},
{"hlsl.samplelevel.basic.dx10.vert", "main"},
{"hlsl.samplelevel.offset.dx10.frag", "main"},
{"hlsl.samplelevel.offsetarray.dx10.frag", "main"},
{"hlsl.sample.sub-vec4.dx10.frag", "main"},
{"hlsl.scalar-length.frag", "main"},
{"hlsl.scalarCast.vert", "main"},
{"hlsl.semicolons.frag", "main"},
{"hlsl.shapeConv.frag", "main"},
{"hlsl.shapeConvRet.frag", "main"},
{"hlsl.singleArgIntPromo.vert", "main"},
{"hlsl.self_cast.frag", "main"},
{"hlsl.snorm.uav.comp", "main"},
{"hlsl.specConstant.frag", "main"},
{"hlsl.staticMemberFunction.frag", "main"},
{"hlsl.staticFuncInit.frag", "main"},
{"hlsl.store.rwbyteaddressbuffer.type.comp", "main"},
{"hlsl.stringtoken.frag", "main"},
{"hlsl.string.frag", "main"},
{"hlsl.struct.split-1.vert", "main"},
{"hlsl.struct.split.array.geom", "main"},
{"hlsl.struct.split.assign.frag", "main"},
{"hlsl.struct.split.call.vert", "main"},
{"hlsl.struct.split.nested.geom", "main"},
{"hlsl.struct.split.trivial.geom", "main"},
{"hlsl.struct.split.trivial.vert", "main"},
{"hlsl.structarray.flatten.frag", "main"},
{"hlsl.structarray.flatten.geom", "main"},
{"hlsl.structbuffer.frag", "main"},
{"hlsl.structbuffer.append.frag", "main"},
{"hlsl.structbuffer.append.fn.frag", "main"},
{"hlsl.structbuffer.atomics.frag", "main"},
{"hlsl.structbuffer.byte.frag", "main"},
{"hlsl.structbuffer.coherent.frag", "main"},
{"hlsl.structbuffer.floatidx.comp", "main"},
{"hlsl.structbuffer.incdec.frag", "main"},
{"hlsl.structbuffer.fn.frag", "main"},
{"hlsl.structbuffer.fn2.comp", "main"},
{"hlsl.structbuffer.rw.frag", "main"},
{"hlsl.structbuffer.rwbyte.frag", "main"},
{"hlsl.structbuffer.rwbyte2.comp", "main"},
{"hlsl.structcopy.comp", "main"},
{"hlsl.structin.vert", "main"},
{"hlsl.structIoFourWay.frag", "main"},
{"hlsl.structStructName.frag", "main"},
{"hlsl.subpass.frag", "main"},
{"hlsl.synthesizeInput.frag", "main"},
{"hlsl.texturebuffer.frag", "main"},
{"hlsl.texture.struct.frag", "main"},
{"hlsl.texture.subvec4.frag", "main"},
{"hlsl.this.frag", "main"},
{"hlsl.intrinsics.vert", "VertexShaderFunction"},
{"hlsl.intrinsic.frexp.vert", "VertexShaderFunction"},
{"hlsl.matType.frag", "PixelShaderFunction"},
{"hlsl.matType.bool.frag", "main"},
{"hlsl.matType.int.frag", "main"},
{"hlsl.max.frag", "PixelShaderFunction"},
{"hlsl.nested-runtimeArray.frag", "main"},
{"hlsl.preprocessor.frag", "main"},
{"hlsl.precedence.frag", "PixelShaderFunction"},
{"hlsl.precedence2.frag", "PixelShaderFunction"},
{"hlsl.scalar2matrix.frag", "main"},
{"hlsl.semantic.geom", "main"},
{"hlsl.semantic.vert", "main"},
{"hlsl.semantic-1.vert", "main"},
{"hlsl.scope.frag", "PixelShaderFunction"},
{"hlsl.sin.frag", "PixelShaderFunction"},
{"hlsl.struct.frag", "PixelShaderFunction"},
{"hlsl.switch.frag", "PixelShaderFunction"},
{"hlsl.swizzle.frag", "PixelShaderFunction"},
{"hlsl.target.frag", "main"},
{"hlsl.targetStruct1.frag", "main"},
{"hlsl.targetStruct2.frag", "main"},
{"hlsl.templatetypes.frag", "PixelShaderFunction"},
{"hlsl.tristream-append.geom", "main"},
{"hlsl.tx.bracket.frag", "main"},
{"hlsl.tx.overload.frag", "main"},
{"hlsl.type.half.frag", "main"},
{"hlsl.type.identifier.frag", "main"},
{"hlsl.typeGraphCopy.vert", "main"},
{"hlsl.typedef.frag", "PixelShaderFunction"},
{"hlsl.whileLoop.frag", "PixelShaderFunction"},
{"hlsl.void.frag", "PixelShaderFunction"},
{"hlsl.type.type.conversion.all.frag", "main"},
{"hlsl.instance.geom", "GeometryShader"}
}),
FileNameAsCustomTestSuffix
);
// clang-format on
// clang-format off
INSTANTIATE_TEST_SUITE_P(
ToSpirv, HlslVulkan1_1CompileTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.wavebroadcast.comp", "CSMain"},
{"hlsl.waveprefix.comp", "CSMain"},
{"hlsl.wavequad.comp", "CSMain"},
{"hlsl.wavequery.comp", "CSMain"},
{"hlsl.wavequery.frag", "PixelShaderFunction"},
{"hlsl.wavereduction.comp", "CSMain"},
{"hlsl.wavevote.comp", "CSMain"},
{ "hlsl.type.type.conversion.valid.frag", "main" },
{"hlsl.int.dot.frag", "main"}
}),
FileNameAsCustomTestSuffix
);
// clang-format on
// clang-format off
INSTANTIATE_TEST_SUITE_P(
ToSpirv, HlslSpv1_6CompileTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.spv.1.6.discard.frag", "PixelShaderFunction"},
{"hlsl.structcopylogical.comp","main"},
}),
FileNameAsCustomTestSuffix
);
// clang-format on
// clang-format off
INSTANTIATE_TEST_SUITE_P(
ToSpirv, HlslCompileAndFlattenTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.array.flatten.frag", "main"},
{"hlsl.partialFlattenMixed.vert", "main"},
}),
FileNameAsCustomTestSuffix
);
// clang-format on
#if ENABLE_OPT
// clang-format off
INSTANTIATE_TEST_SUITE_P(
ToSpirv, HlslLegalizeTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.aliasOpaque.frag", "main"},
{"hlsl.flattenOpaque.frag", "main"},
{"hlsl.flattenOpaqueInit.vert", "main"},
{"hlsl.flattenOpaqueInitMix.vert", "main"},
{"hlsl.flattenSubset.frag", "main"},
{"hlsl.flattenSubset2.frag", "main"},
{"hlsl.intrinsics.evalfns.frag", "main"},
{"hlsl.partialFlattenLocal.vert", "main"},
{"hlsl.partialFlattenMixed.vert", "main"}
}),
FileNameAsCustomTestSuffix
);
// clang-format on
#endif
// clang-format off
INSTANTIATE_TEST_SUITE_P(
ToSpirv, HlslDebugTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.pp.line2.frag", "MainPs"}
}),
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_SUITE_P(
ToSpirv, HlslDX9CompatibleTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.round.dx9.frag", "main"},
{"hlsl.sample.dx9.frag", "main"},
{"hlsl.sample.dx9.vert", "main"},
}),
FileNameAsCustomTestSuffix
);
// clang-format off
INSTANTIATE_TEST_SUITE_P(
ToSpirv, HlslLegalDebugTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.pp.line4.frag", "MainPs"}
}),
FileNameAsCustomTestSuffix
);
// clang-format on
// clang-format off
INSTANTIATE_TEST_SUITE_P(
ToSpirv, HlslNonSemanticShaderDebugInfoTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"spv.debuginfo.hlsl.vert", "main"},
{"spv.debuginfo.hlsl.frag", "main"},
{"spv.debuginfo.hlsl.comp", "main"},
{"spv.debuginfo.hlsl.geom", "main"},
{"spv.debuginfo.hlsl.tesc", "main"},
{"spv.debuginfo.hlsl.tese", "main"},
}),
FileNameAsCustomTestSuffix
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest

55
externals/glslang/gtests/Initializer.h vendored Normal file
View File

@@ -0,0 +1,55 @@
//
// Copyright (C) 2016 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#ifndef GLSLANG_GTESTS_INITIALIZER_H
#define GLSLANG_GTESTS_INITIALIZER_H
#include "glslang/Public/ShaderLang.h"
namespace glslangtest {
// Initializes glslang on creation, and destroys it on completion.
// This object is expected to be a singleton, so that internal glslang state
// can be correctly handled.
//
class GlslangInitializer {
public:
GlslangInitializer() { glslang::InitializeProcess(); }
~GlslangInitializer() { glslang::FinalizeProcess(); }
};
} // namespace glslangtest
#endif // GLSLANG_GTESTS_INITIALIZER_H

View File

@@ -0,0 +1,133 @@
//
// Copyright (C) 2016-2017 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include <memory>
#include <gtest/gtest.h>
#include "TestFixture.h"
namespace glslangtest {
namespace {
using LinkTestVulkan = GlslangTest<
::testing::TestWithParam<std::vector<std::string>>>;
TEST_P(LinkTestVulkan, FromFile)
{
const auto& fileNames = GetParam();
const size_t fileCount = fileNames.size();
const EShMessages controls = DeriveOptions(Source::GLSL, Semantics::Vulkan, Target::AST);
GlslangResult result;
result.validationResult = false;
// Compile each input shader file.
bool success = true;
std::vector<std::unique_ptr<glslang::TShader>> shaders;
for (size_t i = 0; i < fileCount; ++i) {
std::string contents;
tryLoadFile(GlobalTestSettings.testRoot + "/" + fileNames[i],
"input", &contents);
shaders.emplace_back(
new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i]))));
auto* shader = shaders.back().get();
shader->setAutoMapLocations(true);
success &= compile(shader, contents, "", controls);
result.shaderResults.push_back(
{fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog()});
}
// Link all of them.
glslang::TProgram program;
for (const auto& shader : shaders) program.addShader(shader.get());
success &= program.link(controls);
result.linkingOutput = program.getInfoLog();
result.linkingError = program.getInfoDebugLog();
#if !defined(GLSLANG_WEB)
if (success)
program.mapIO();
#endif
if (success && (controls & EShMsgSpvRules)) {
spv::SpvBuildLogger logger;
std::vector<uint32_t> spirv_binary;
options().disableOptimizer = true;
glslang::GlslangToSpv(*program.getIntermediate(shaders.front()->getStage()),
spirv_binary, &logger, &options());
std::ostringstream disassembly_stream;
spv::Parameterize();
spv::Disassemble(disassembly_stream, spirv_binary);
result.spirvWarningsErrors = logger.getAllMessages();
result.spirv = disassembly_stream.str();
result.validationResult = !options().validate || logger.getAllMessages().empty();
}
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
// Check with expected results.
const std::string expectedOutputFname =
GlobalTestSettings.testRoot + "/baseResults/" + fileNames.front() + ".out";
std::string expectedOutput;
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname,
result.spirvWarningsErrors);
}
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, LinkTestVulkan,
::testing::ValuesIn(std::vector<std::vector<std::string>>({
{"link1.vk.frag", "link2.vk.frag"},
{"spv.unit1.frag", "spv.unit2.frag", "spv.unit3.frag"},
{"link.vk.matchingPC.0.0.frag", "link.vk.matchingPC.0.1.frag",
"link.vk.matchingPC.0.2.frag"},
{"link.vk.differentPC.0.0.frag", "link.vk.differentPC.0.1.frag",
"link.vk.differentPC.0.2.frag"},
{"link.vk.differentPC.1.0.frag", "link.vk.differentPC.1.1.frag",
"link.vk.differentPC.1.2.frag"},
{"link.vk.pcNamingValid.0.0.vert", "link.vk.pcNamingValid.0.1.vert"},
{"link.vk.pcNamingInvalid.0.0.vert", "link.vk.pcNamingInvalid.0.1.vert"},
{"link.vk.multiBlocksValid.0.0.vert", "link.vk.multiBlocksValid.0.1.vert"},
{"link.vk.multiBlocksValid.1.0.geom", "link.vk.multiBlocksValid.1.1.geom"},
{"link.vk.inconsistentGLPerVertex.0.vert", "link.vk.inconsistentGLPerVertex.0.geom"},
}))
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest

View File

@@ -0,0 +1,120 @@
//
// Copyright (C) 2016 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include <memory>
#include <gtest/gtest.h>
#include "TestFixture.h"
namespace glslangtest {
namespace {
using LinkTest = GlslangTest<
::testing::TestWithParam<std::vector<std::string>>>;
TEST_P(LinkTest, FromFile)
{
const auto& fileNames = GetParam();
const size_t fileCount = fileNames.size();
const EShMessages controls = DeriveOptions(Source::GLSL, Semantics::OpenGL, Target::AST);
GlslangResult result;
result.validationResult = true;
// Compile each input shader file.
std::vector<std::unique_ptr<glslang::TShader>> shaders;
for (size_t i = 0; i < fileCount; ++i) {
std::string contents;
tryLoadFile(GlobalTestSettings.testRoot + "/" + fileNames[i],
"input", &contents);
shaders.emplace_back(
new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i]))));
auto* shader = shaders.back().get();
compile(shader, contents, "", controls);
result.shaderResults.push_back(
{fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog()});
}
// Link all of them.
glslang::TProgram program;
for (const auto& shader : shaders) program.addShader(shader.get());
program.link(controls);
result.linkingOutput = program.getInfoLog();
result.linkingError = program.getInfoDebugLog();
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
// Check with expected results.
const std::string expectedOutputFname =
GlobalTestSettings.testRoot + "/baseResults/" + fileNames.front() + ".out";
std::string expectedOutput;
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname);
}
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, LinkTest,
::testing::ValuesIn(std::vector<std::vector<std::string>>({
{"mains1.frag", "mains2.frag", "noMain1.geom", "noMain2.geom"},
{"implicitArraySize.vert", "implicitArraySize.frag"},
{"implicitArraySizeBuiltin.vert", "implicitArraySizeBuiltin.geom"},
{"implicitArraySize1.geom", "implicitArraySize2.geom"},
{"noMain.vert", "mains.frag"},
{"link1.frag", "link2.frag", "link3.frag"},
{"recurse1.vert", "recurse1.frag", "recurse2.frag"},
{"300link.frag"},
{"300link2.frag"},
{"300link3.frag"},
{"empty.frag", "empty2.frag", "empty3.frag"},
{"150.tesc", "150.tese", "400.tesc", "400.tese", "410.tesc", "420.tesc", "420.tese"},
{"max_vertices_0.geom"},
{"contradict_0.geom", "contradict_1.geom"},
{"es-link1.frag", "es-link2.frag"},
{"missingBodies.vert"},
{"link.multiAnonBlocksInvalid.0.0.vert", "link.multiAnonBlocksInvalid.0.1.vert"},
{"link.multiAnonBlocksValid.0.0.vert", "link.multiAnonBlocksValid.0.1.vert"},
{"link.multiBlocksInvalid.0.0.vert", "link.multiBlocksInvalid.0.1.vert"},
{"link.multiBlocksValid.1.0.vert", "link.multiBlocksValid.1.1.vert"},
{"link.tesselation.vert", "link.tesselation.frag"},
{"link.tesselation.tese", "link.tesselation.tesc"},
{"link.redeclareBuiltin.vert", "link.redeclareBuiltin.geom"},
}))
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest

View File

@@ -0,0 +1,76 @@
//
// Copyright (C) 2016 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include <gtest/gtest.h>
#include "TestFixture.h"
namespace glslangtest {
namespace {
using PreprocessingTest = GlslangTest<::testing::TestWithParam<std::string>>;
TEST_P(PreprocessingTest, FromFile)
{
loadFilePreprocessAndCheck(GlobalTestSettings.testRoot, GetParam());
}
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, PreprocessingTest,
::testing::ValuesIn(std::vector<std::string>({
"preprocessor.bad_arg.vert",
"preprocessor.cpp_style_line_directive.vert",
"preprocessor.cpp_style___FILE__.vert",
"preprocessor.edge_cases.vert",
"preprocessor.errors.vert",
"preprocessor.extensions.vert",
"preprocessor.function_macro.vert",
"preprocessor.include.enabled.vert",
"preprocessor.include.disabled.vert",
"preprocessor.line.vert",
"preprocessor.line.frag",
"preprocessor.pragma.vert",
"preprocessor.simple.vert",
"preprocessor.success_if_parse_would_fail.vert",
"preprocessor.defined.vert",
"preprocessor.many.endif.vert",
"preprocessor.eof_missing.vert",
})),
FileNameAsCustomTestSuffix
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest

26
externals/glslang/gtests/README.md vendored Normal file
View File

@@ -0,0 +1,26 @@
Glslang Tests based on the Google Test Framework
================================================
This directory contains [Google Test][gtest] based test fixture and test
cases for glslang.
Apart from typical unit tests, necessary utility methods are added into
the [`GlslangTests`](TestFixture.h) fixture to provide the ability to do
file-based integration tests. Various `*.FromFile.cpp` files lists names
of files containing input shader code in the `Test/` directory. Utility
methods will load the input shader source, compile them, and compare with
the corresponding expected output in the `Test/baseResults/` directory.
How to run the tests
--------------------
Please make sure you have a copy of [Google Test][gtest] checked out under
the `External` directory before building. After building, just run the
`ctest` command or the `gtests/glslangtests` binary in your build directory.
The `gtests/glslangtests` binary also provides an `--update-mode` command
line option, which, if supplied, will overwrite the golden files under
the `Test/baseResults/` directory with real output from that invocation.
This serves as an easy way to update golden files.
[gtest]: https://github.com/google/googletest

View File

@@ -0,0 +1,118 @@
//
// Copyright (C) 2016 LunarG, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include <gtest/gtest.h>
#include "TestFixture.h"
namespace glslangtest {
namespace {
struct RemapTestArgs {
const char* fileName;
const char* entryPoint;
Source sourceLanguage;
unsigned int remapOpts;
};
// We are using FileNameEntryPointPair objects as parameters for instantiating
// the template, so the global FileNameAsCustomTestSuffix() won't work since
// it assumes std::string as parameters. Thus, an overriding one here.
std::string FileNameAsCustomTestSuffix(
const ::testing::TestParamInfo<RemapTestArgs>& info) {
std::string name = info.param.fileName;
// A valid test case suffix cannot have '.' and '-' inside.
std::replace(name.begin(), name.end(), '.', '_');
std::replace(name.begin(), name.end(), '-', '_');
return name;
}
using RemapTest = GlslangTest<::testing::TestWithParam<RemapTestArgs>>;
// Remapping SPIR-V modules.
TEST_P(RemapTest, FromFile)
{
if (GetSuffix(GetParam().fileName) == "spv") {
loadFileRemapAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
GetParam().sourceLanguage,
Semantics::Vulkan,
Target::Spv,
GetParam().remapOpts);
} else {
loadFileCompileRemapAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
GetParam().sourceLanguage,
Semantics::Vulkan,
Target::Spv,
GetParam().entryPoint,
GetParam().remapOpts);
}
}
// clang-format off
INSTANTIATE_TEST_SUITE_P(
ToSpirv, RemapTest,
::testing::ValuesIn(std::vector<RemapTestArgs>{
// GLSL remapper tests
// testname entry language remapper_options
{ "remap.basic.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE },
{ "remap.basic.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING },
{ "remap.basic.dcefunc.frag", "main", Source::GLSL, spv::spirvbin_t::DCE_FUNCS },
{ "remap.basic.strip.frag", "main", Source::GLSL, spv::spirvbin_t::STRIP },
{ "remap.specconst.comp", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING },
{ "remap.switch.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE },
{ "remap.switch.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING },
{ "remap.literal64.none.spv", "main", Source::GLSL, spv::spirvbin_t::NONE },
{ "remap.literal64.everything.spv", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING },
{ "remap.if.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE },
{ "remap.if.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING },
{ "remap.similar_1a.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE },
{ "remap.similar_1b.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE },
{ "remap.similar_1a.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING },
{ "remap.similar_1b.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING },
{ "remap.uniformarray.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE },
{ "remap.uniformarray.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING },
// HLSL remapper tests
{ "remap.hlsl.sample.basic.strip.frag", "main", Source::HLSL, spv::spirvbin_t::STRIP },
{ "remap.hlsl.sample.basic.everything.frag", "main", Source::HLSL, spv::spirvbin_t::DO_EVERYTHING },
{ "remap.hlsl.sample.basic.none.frag", "main", Source::HLSL, spv::spirvbin_t::NONE },
{ "remap.hlsl.templatetypes.none.frag", "main", Source::HLSL, spv::spirvbin_t::NONE },
{ "remap.hlsl.templatetypes.everything.frag", "main", Source::HLSL, spv::spirvbin_t::DO_EVERYTHING },
}),
FileNameAsCustomTestSuffix
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest

51
externals/glslang/gtests/Settings.cpp vendored Normal file
View File

@@ -0,0 +1,51 @@
//
// Copyright (C) 2016 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include "Settings.h"
namespace glslangtest {
// We need CMake to provide us the absolute path to the directory containing
// test files, so we are certain to find those files no matter where the test
// harness binary is generated. This provides out-of-source build capability.
// This will be used as the default test root, but can be overridden with
// the --test-root argument.
#ifndef GLSLANG_TEST_DIRECTORY
#error \
"GLSLANG_TEST_DIRECTORY needs to be defined for gtest to locate test files."
#endif
GTestSettings GlobalTestSettings = {nullptr, false, GLSLANG_TEST_DIRECTORY};
} // namespace glslangtest

58
externals/glslang/gtests/Settings.h vendored Normal file
View File

@@ -0,0 +1,58 @@
//
// Copyright (C) 2016 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#ifndef GLSLANG_GTESTS_SETTINGS_H
#define GLSLANG_GTESTS_SETTINGS_H
#include <string>
namespace glslangtest {
class GlslangInitializer;
struct GTestSettings {
// A handle to GlslangInitializer instance.
GlslangInitializer* initializer;
// An indicator of whether GTest should write real output to the file for
// the expected output.
bool updateMode;
// The root directory for test files.
std::string testRoot;
};
extern GTestSettings GlobalTestSettings;
} // namespace glslangtest
#endif // GLSLANG_GTESTS_SETTINGS_H

View File

@@ -0,0 +1,878 @@
//
// Copyright (C) 2016 Google, Inc.
// Copyright (C) 2019 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include <algorithm>
#include <gtest/gtest.h>
#include "TestFixture.h"
namespace glslangtest {
namespace {
struct IoMapData {
const char* fileName;
const char* entryPoint;
int baseSamplerBinding;
int baseTextureBinding;
int baseImageBinding;
int baseUboBinding;
int baseSsboBinding;
bool autoMapBindings;
bool flattenUniforms;
};
std::string FileNameAsCustomTestSuffixIoMap(
const ::testing::TestParamInfo<IoMapData>& info) {
std::string name = info.param.fileName;
// A valid test case suffix cannot have '.' and '-' inside.
std::replace(name.begin(), name.end(), '.', '_');
std::replace(name.begin(), name.end(), '-', '_');
return name;
}
using CompileVulkanToSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileVulkanToSpirvDeadCodeElimTest = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileVulkanToDebugSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileVulkan1_1ToSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileToSpirv14Test = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileToSpirv16Test = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileOpenGLToSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
using VulkanSemantics = GlslangTest<::testing::TestWithParam<std::string>>;
using OpenGLSemantics = GlslangTest<::testing::TestWithParam<std::string>>;
using VulkanAstSemantics = GlslangTest<::testing::TestWithParam<std::string>>;
using HlslIoMap = GlslangTest<::testing::TestWithParam<IoMapData>>;
using GlslIoMap = GlslangTest<::testing::TestWithParam<IoMapData>>;
using CompileVulkanToSpirvTestAMD = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileVulkanToSpirvTestNV = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileVulkanToSpirv14TestNV = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileUpgradeTextureToSampledTextureAndDropSamplersTest = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileVulkanToNonSemanticShaderDebugInfoTest = GlslangTest<::testing::TestWithParam<std::string>>;
// Compiling GLSL to SPIR-V under Vulkan semantics. Expected to successfully
// generate SPIR-V.
TEST_P(CompileVulkanToSpirvTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv);
}
TEST_P(CompileVulkanToSpirvDeadCodeElimTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv);
}
// Compiling GLSL to SPIR-V with debug info under Vulkan semantics. Expected
// to successfully generate SPIR-V.
TEST_P(CompileVulkanToDebugSpirvTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan,
glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv, true, "",
"/baseResults/", false, true);
}
TEST_P(CompileVulkan1_1ToSpirvTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_1, glslang::EShTargetSpv_1_3,
Target::Spv);
}
TEST_P(CompileToSpirv14Test, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_1, glslang::EShTargetSpv_1_4,
Target::Spv);
}
TEST_P(CompileToSpirv16Test, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_3, glslang::EShTargetSpv_1_6,
Target::Spv);
}
// Compiling GLSL to SPIR-V under OpenGL semantics. Expected to successfully
// generate SPIR-V.
TEST_P(CompileOpenGLToSpirvTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::OpenGL, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv);
}
// GLSL-level Vulkan semantics test. Expected to error out before generating
// SPIR-V.
TEST_P(VulkanSemantics, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv, false);
}
// GLSL-level Vulkan semantics test. Expected to error out before generating
// SPIR-V.
TEST_P(OpenGLSemantics, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::OpenGL, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv, false);
}
// GLSL-level Vulkan semantics test that need to see the AST for validation.
TEST_P(VulkanAstSemantics, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::AST);
}
// HLSL-level Vulkan semantics tests.
TEST_P(HlslIoMap, FromFile)
{
loadFileCompileIoMapAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::HLSL, Semantics::Vulkan,
Target::Spv, GetParam().entryPoint,
GetParam().baseSamplerBinding,
GetParam().baseTextureBinding,
GetParam().baseImageBinding,
GetParam().baseUboBinding,
GetParam().baseSsboBinding,
GetParam().autoMapBindings,
GetParam().flattenUniforms);
}
// GLSL-level Vulkan semantics tests.
TEST_P(GlslIoMap, FromFile)
{
loadFileCompileIoMapAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::GLSL, Semantics::Vulkan,
Target::Spv, GetParam().entryPoint,
GetParam().baseSamplerBinding,
GetParam().baseTextureBinding,
GetParam().baseImageBinding,
GetParam().baseUboBinding,
GetParam().baseSsboBinding,
GetParam().autoMapBindings,
GetParam().flattenUniforms);
}
// Compiling GLSL to SPIR-V under Vulkan semantics (AMD extensions enabled).
// Expected to successfully generate SPIR-V.
TEST_P(CompileVulkanToSpirvTestAMD, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv);
}
// Compiling GLSL to SPIR-V under Vulkan semantics (NV extensions enabled).
// Expected to successfully generate SPIR-V.
TEST_P(CompileVulkanToSpirvTestNV, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv);
}
TEST_P(CompileVulkanToSpirv14TestNV, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_1, glslang::EShTargetSpv_1_4,
Target::Spv);
}
TEST_P(CompileUpgradeTextureToSampledTextureAndDropSamplersTest, FromFile)
{
loadCompileUpgradeTextureToSampledTextureAndDropSamplersAndCheck(GlobalTestSettings.testRoot,
GetParam(),
Source::GLSL,
Semantics::Vulkan,
Target::Spv);
}
TEST_P(CompileVulkanToNonSemanticShaderDebugInfoTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0,
Target::Spv, true, "", "/baseResults/", false, false, true);
}
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileVulkanToSpirvTest,
::testing::ValuesIn(std::vector<std::string>({
// Test looping constructs.
// No tests yet for making sure break and continue from a nested loop
// goes to the innermost target.
"spv.barrier.vert",
"spv.do-simple.vert",
"spv.do-while-continue-break.vert",
"spv.for-complex-condition.vert",
"spv.for-continue-break.vert",
"spv.for-simple.vert",
"spv.for-notest.vert",
"spv.for-nobody.vert",
"spv.while-continue-break.vert",
"spv.while-simple.vert",
// vulkan-specific tests
"rayQuery.rgen",
"rayQuery-no-cse.rgen",
"rayQuery-initialize.rgen",
"rayQuery-allOps.rgen",
"rayQuery-allOps.Error.rgen",
"rayQuery-committed.Error.rgen",
"rayQuery-allOps.comp",
"rayQuery-allOps.frag",
"rayQuery-initialization.Error.comp",
"rayQuery-global.rgen",
"rayQuery-types.comp",
"rayQuery-OpConvertUToAccelerationStructureKHR.comp",
"spv.set.vert",
"spv.double.comp",
"spv.100ops.frag",
"spv.130.frag",
"spv.140.frag",
"spv.150.geom",
"spv.150.vert",
"spv.16bitstorage.frag",
"spv.16bitstorage_Error.frag",
"spv.16bitstorage-int.frag",
"spv.16bitstorage_Error-int.frag",
"spv.16bitstorage-uint.frag",
"spv.16bitstorage_Error-uint.frag",
"spv.300BuiltIns.vert",
"spv.300layout.frag",
"spv.300layout.vert",
"spv.300layoutp.vert",
"spv.310.comp",
"spv.310.bitcast.frag",
"spv.330.geom",
"spv.400.frag",
"spv.400.tesc",
"spv.400.tese",
"spv.420.geom",
"spv.430.frag",
"spv.430.vert",
"spv.450.tesc",
"spv.450.geom",
"spv.450.noRedecl.tesc",
"spv.8bitstorage-int.frag",
"spv.8bitstorage_Error-int.frag",
"spv.8bitstorage-uint.frag",
"spv.8bitstorage_Error-uint.frag",
"spv.8bitstorage-ubo.vert",
"spv.8bitstorage-ssbo.vert",
"spv.8bit-16bit-construction.frag",
"spv.accessChain.frag",
"spv.aggOps.frag",
"spv.always-discard.frag",
"spv.always-discard2.frag",
"spv.arbPostDepthCoverage.frag",
"spv.arbPostDepthCoverage_Error.frag",
"spv.atomicCounter.comp",
"spv.bitCast.frag",
"spv.bool.vert",
"spv.boolInBlock.frag",
"spv.branch-return.vert",
"spv.bufferhandle1.frag",
"spv.bufferhandle10.frag",
"spv.bufferhandle11.frag",
"spv.bufferhandle12.frag",
"spv.bufferhandle13.frag",
"spv.bufferhandle14.frag",
"spv.bufferhandle15.frag",
"spv.bufferhandle16.frag",
"spv.bufferhandle17_Errors.frag",
"spv.bufferhandle18.frag",
"spv.bufferhandle19_Errors.frag",
"spv.bufferhandle2.frag",
"spv.bufferhandle3.frag",
"spv.bufferhandle4.frag",
"spv.bufferhandle5.frag",
"spv.bufferhandle6.frag",
"spv.bufferhandle7.frag",
"spv.bufferhandle8.frag",
"spv.bufferhandle9.frag",
"spv.bufferhandleUvec2.frag",
"spv.bufferhandle_Error.frag",
"spv.builtInXFB.vert",
"spv.conditionalDemote.frag",
"spv.conditionalDiscard.frag",
"spv.constructComposite.comp",
"spv.constStruct.vert",
"spv.constConstruct.vert",
"spv.controlFlowAttributes.frag",
"spv.conversion.frag",
"spv.coopmat.comp",
"spv.coopmat_Error.comp",
"spv.dataOut.frag",
"spv.dataOutIndirect.frag",
"spv.dataOutIndirect.vert",
"spv.debugPrintf.frag",
"spv.debugPrintf_Error.frag",
"spv.demoteDisabled.frag",
"spv.deepRvalue.frag",
"spv.depthOut.frag",
"spv.depthUnchanged.frag",
"spv.discard-dce.frag",
"spv.doWhileLoop.frag",
"spv.earlyReturnDiscard.frag",
"spv.ext.ShaderTileImage.color.frag",
"spv.ext.ShaderTileImage.depth_stencil.frag",
"spv.ext.ShaderTileImage.subpassinput.frag",
"spv.ext.ShaderTileImage.typemismatch.frag",
"spv.ext.ShaderTileImage.overlap.frag",
"spv.ext.ShaderTileImage.wronglayout.frag",
"spv.extPostDepthCoverage.frag",
"spv.extPostDepthCoverage_Error.frag",
"spv.float16convertonlyarith.comp",
"spv.float16convertonlystorage.comp",
"spv.flowControl.frag",
"spv.forLoop.frag",
"spv.forwardFun.frag",
"spv.fragmentDensity.frag",
"spv.fragmentDensity.vert",
"spv.fragmentDensity-es.frag",
"spv.fragmentDensity-neg.frag",
"spv.fsi.frag",
"spv.fsi_Error.frag",
"spv.fullyCovered.frag",
"spv.functionCall.frag",
"spv.functionNestedOpaque.vert",
"spv.functionSemantics.frag",
"spv.functionParameterTypes.frag",
"spv.GeometryShaderPassthrough.geom",
"spv.funcall.array.frag",
"spv.load.bool.array.interface.block.frag",
"spv.interpOps.frag",
"spv.int64.frag",
"spv.intcoopmat.comp",
"spv.intOps.vert",
"spv.intrinsicsSpirvByReference.vert",
"spv.intrinsicsSpirvDecorate.frag",
"spv.intrinsicsSpirvDecorateId.comp",
"spv.intrinsicsSpirvDecorateString.comp",
"spv.intrinsicsSpirvExecutionMode.frag",
"spv.intrinsicsSpirvInstruction.vert",
"spv.intrinsicsSpirvLiteral.vert",
"spv.intrinsicsSpirvStorageClass.rchit",
"spv.intrinsicsSpirvType.rgen",
"spv.intrinsicsSpirvTypeLocalVar.vert",
"spv.invariantAll.vert",
"spv.layer.tese",
"spv.layoutNested.vert",
"spv.length.frag",
"spv.localAggregates.frag",
"spv.loops.frag",
"spv.loopsArtificial.frag",
"spv.matFun.vert",
"spv.matrix.frag",
"spv.matrix2.frag",
"spv.memoryQualifier.frag",
"spv.merge-unreachable.frag",
"spv.multiStruct.comp",
"spv.multiStructFuncall.frag",
"spv.newTexture.frag",
"spv.noDeadDecorations.vert",
"spv.nonSquare.vert",
"spv.nonuniform.frag",
"spv.nonuniform2.frag",
"spv.nonuniform3.frag",
"spv.nonuniform4.frag",
"spv.nonuniform5.frag",
"spv.noWorkgroup.comp",
"spv.nullInit.comp",
"spv.offsets.frag",
"spv.Operations.frag",
"spv.paramMemory.frag",
"spv.paramMemory.420.frag",
"spv.precision.frag",
"spv.precisionArgs.frag",
"spv.precisionNonESSamp.frag",
"spv.precisionTexture.frag",
"spv.prepost.frag",
"spv.privateVariableTypes.frag",
"spv.qualifiers.vert",
"spv.sample.frag",
"spv.sampleId.frag",
"spv.samplePosition.frag",
"spv.sampleMaskOverrideCoverage.frag",
"spv.scalarlayout.frag",
"spv.scalarlayoutfloat16.frag",
"spv.shaderBallot.comp",
"spv.shaderDrawParams.vert",
"spv.shaderGroupVote.comp",
"spv.shaderStencilExport.frag",
"spv.shiftOps.frag",
"spv.simpleFunctionCall.frag",
"spv.simpleMat.vert",
"spv.sparseTexture.frag",
"spv.sparseTextureClamp.frag",
"spv.structAssignment.frag",
"spv.structCopy.comp",
"spv.structDeref.frag",
"spv.structure.frag",
"spv.switch.frag",
"spv.swizzle.frag",
"spv.swizzleInversion.frag",
"spv.test.frag",
"spv.test.vert",
"spv.texture.frag",
"spv.texture.vert",
"spv.textureBuffer.vert",
"spv.image.frag",
"spv.imageAtomic64.frag",
"spv.imageAtomic64.comp",
"spv.types.frag",
"spv.uint.frag",
"spv.uniformArray.frag",
"spv.variableArrayIndex.frag",
"spv.varyingArray.frag",
"spv.varyingArrayIndirect.frag",
"spv.vecMatConstruct.frag",
"spv.voidFunction.frag",
"spv.whileLoop.frag",
"spv.AofA.frag",
"spv.queryL.frag",
"spv.separate.frag",
"spv.shortCircuit.frag",
"spv.pushConstant.vert",
"spv.pushConstantAnon.vert",
"spv.subpass.frag",
"spv.specConstant.vert",
"spv.specConstant.comp",
"spv.specConstantComposite.vert",
"spv.specConstantOperations.vert",
"spv.specConstant.float16.comp",
"spv.specConstant.int16.comp",
"spv.specConstant.int8.comp",
"spv.storageBuffer.vert",
"spv.terminate.frag",
"spv.subgroupUniformControlFlow.vert",
"spv.subgroupSizeARB.frag",
"spv.precise.tese",
"spv.precise.tesc",
"spv.viewportindex.tese",
"spv.volatileAtomic.comp",
"spv.vulkan100.subgroupArithmetic.comp",
"spv.vulkan100.subgroupPartitioned.comp",
"spv.xfb.vert",
"spv.xfb2.vert",
"spv.xfb3.vert",
"spv.samplerlessTextureFunctions.frag",
"spv.smBuiltins.vert",
"spv.smBuiltins.frag",
"spv.ARMCoreBuiltIns.vert",
"spv.ARMCoreBuiltIns.frag",
"spv.builtin.PrimitiveShadingRateEXT.vert",
"spv.builtin.ShadingRateEXT.frag",
"spv.atomicAdd.bufferReference.comp",
"spv.fragmentShaderBarycentric3.frag",
"spv.fragmentShaderBarycentric4.frag",
})),
FileNameAsCustomTestSuffix
);
// Cases with deliberately unreachable code.
// By default the compiler will aggressively eliminate
// unreachable merges and continues.
INSTANTIATE_TEST_SUITE_P(
GlslWithDeadCode, CompileVulkanToSpirvDeadCodeElimTest,
::testing::ValuesIn(std::vector<std::string>({
"spv.dead-after-continue.vert",
"spv.dead-after-discard.frag",
"spv.dead-after-return.vert",
"spv.dead-after-loop-break.vert",
"spv.dead-after-switch-break.vert",
"spv.dead-complex-continue-after-return.vert",
"spv.dead-complex-merge-after-return.vert",
})),
FileNameAsCustomTestSuffix
);
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileVulkanToDebugSpirvTest,
::testing::ValuesIn(std::vector<std::string>({
"spv.pp.line.frag",
})),
FileNameAsCustomTestSuffix
);
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileVulkan1_1ToSpirvTest,
::testing::ValuesIn(std::vector<std::string>({
"spv.1.3.8bitstorage-ubo.vert",
"spv.1.3.8bitstorage-ssbo.vert",
"spv.1.3.coopmat.comp",
"spv.deviceGroup.frag",
"spv.drawParams.vert",
"spv.int8.frag",
"spv.vulkan110.int16.frag",
"spv.int32.frag",
"spv.explicittypes.frag",
"spv.float16NoRelaxed.vert",
"spv.float32.frag",
"spv.float64.frag",
"spv.memoryScopeSemantics.comp",
"spv.memoryScopeSemantics_Error.comp",
"spv.multiView.frag",
"spv.queueFamilyScope.comp",
"spv.RayGenShader11.rgen",
"spv.subgroup.frag",
"spv.subgroup.geom",
"spv.subgroup.tesc",
"spv.subgroup.tese",
"spv.subgroup.vert",
"spv.subgroupArithmetic.comp",
"spv.subgroupBasic.comp",
"spv.subgroupBallot.comp",
"spv.subgroupBallotNeg.comp",
"spv.subgroupClustered.comp",
"spv.subgroupClusteredNeg.comp",
"spv.subgroupPartitioned.comp",
"spv.subgroupShuffle.comp",
"spv.subgroupShuffleRelative.comp",
"spv.subgroupQuad.comp",
"spv.subgroupVote.comp",
"spv.subgroupExtendedTypesArithmetic.comp",
"spv.subgroupExtendedTypesArithmeticNeg.comp",
"spv.subgroupExtendedTypesBallot.comp",
"spv.subgroupExtendedTypesBallotNeg.comp",
"spv.subgroupExtendedTypesClustered.comp",
"spv.subgroupExtendedTypesClusteredNeg.comp",
"spv.subgroupExtendedTypesPartitioned.comp",
"spv.subgroupExtendedTypesPartitionedNeg.comp",
"spv.subgroupExtendedTypesShuffle.comp",
"spv.subgroupExtendedTypesShuffleNeg.comp",
"spv.subgroupExtendedTypesShuffleRelative.comp",
"spv.subgroupExtendedTypesShuffleRelativeNeg.comp",
"spv.subgroupExtendedTypesQuad.comp",
"spv.subgroupExtendedTypesQuadNeg.comp",
"spv.subgroupExtendedTypesVote.comp",
"spv.subgroupExtendedTypesVoteNeg.comp",
"spv.vulkan110.storageBuffer.vert",
})),
FileNameAsCustomTestSuffix
);
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileToSpirv14Test,
::testing::ValuesIn(std::vector<std::string>({
"spv.1.4.LoopControl.frag",
"spv.1.4.NonWritable.frag",
"spv.1.4.OpEntryPoint.frag",
"spv.1.4.OpEntryPoint.opaqueParams.vert",
"spv.1.4.OpSelect.frag",
"spv.1.4.OpCopyLogical.comp",
"spv.1.4.OpCopyLogicalBool.comp",
"spv.1.4.OpCopyLogical.funcall.frag",
"spv.1.4.funcall.array.frag",
"spv.1.4.load.bool.array.interface.block.frag",
"spv.1.4.image.frag",
"spv.1.4.sparseTexture.frag",
"spv.1.4.texture.frag",
"spv.1.4.constructComposite.comp",
"spv.ext.AnyHitShader.rahit",
"spv.ext.AnyHitShader_Errors.rahit",
"spv.ext.ClosestHitShader.rchit",
"spv.ext.ClosestHitShader_Subgroup.rchit",
"spv.ext.ClosestHitShader_Errors.rchit",
"spv.ext.IntersectShader.rint",
"spv.ext.IntersectShader_Errors.rint",
"spv.ext.MissShader.rmiss",
"spv.ext.MissShader_Errors.rmiss",
"spv.ext.RayPrimCull_Errors.rgen",
"spv.ext.RayCallable.rcall",
"spv.ext.RayCallable_Errors.rcall",
"spv.ext.RayConstants.rgen",
"spv.ext.RayGenShader.rgen",
"spv.ext.RayGenShader_Errors.rgen",
"spv.ext.RayGenShader11.rgen",
"spv.ext.RayGenShaderArray.rgen",
"spv.ext.RayGenSBTlayout.rgen",
"spv.ext.RayGenSBTlayout140.rgen",
"spv.ext.RayGenSBTlayout430.rgen",
"spv.ext.RayGenSBTlayoutscalar.rgen",
"spv.ext.World3x4.rahit",
"spv.ext.AccelDecl.frag",
"spv.ext.RayQueryDecl.frag",
// SPV_KHR_workgroup_memory_explicit_layout depends on SPIR-V 1.4.
"spv.WorkgroupMemoryExplicitLayout.SingleBlock.comp",
"spv.WorkgroupMemoryExplicitLayout.MultiBlock.comp",
"spv.WorkgroupMemoryExplicitLayout.8BitAccess.comp",
"spv.WorkgroupMemoryExplicitLayout.16BitAccess.comp",
"spv.WorkgroupMemoryExplicitLayout.NonBlock.comp",
"spv.WorkgroupMemoryExplicitLayout.MixBlockNonBlock_Errors.comp",
"spv.WorkgroupMemoryExplicitLayout.std140.comp",
"spv.WorkgroupMemoryExplicitLayout.std430.comp",
"spv.WorkgroupMemoryExplicitLayout.scalar.comp",
// SPV_EXT_mesh_shader
"spv.ext.meshShaderBuiltins.mesh",
"spv.ext.meshShaderRedeclBuiltins.mesh",
"spv.ext.meshShaderTaskMem.mesh",
"spv.ext.meshShaderUserDefined.mesh",
"spv.ext.meshTaskShader.task",
"spv.atomiAddEXT.error.mesh",
"spv.atomiAddEXT.task",
"spv.460.subgroupEXT.task",
"spv.460.subgroupEXT.mesh",
// SPV_NV_shader_execution_reorder
"spv.nv.hitobject-allops.rgen",
"spv.nv.hitobject-allops.rchit",
"spv.nv.hitobject-allops.rmiss",
})),
FileNameAsCustomTestSuffix
);
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileToSpirv16Test,
::testing::ValuesIn(std::vector<std::string>({
"spv.1.6.conditionalDiscard.frag",
"spv.1.6.helperInvocation.frag",
"spv.1.6.helperInvocation.memmodel.frag",
"spv.1.6.specConstant.comp",
"spv.1.6.samplerBuffer.frag",
"spv.1.6.separate.frag",
})),
FileNameAsCustomTestSuffix
);
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Hlsl, HlslIoMap,
::testing::ValuesIn(std::vector<IoMapData>{
{ "spv.register.autoassign.frag", "main_ep", 5, 10, 0, 20, 30, true, false },
{ "spv.register.noautoassign.frag", "main_ep", 5, 10, 0, 15, 30, false, false },
{ "spv.register.autoassign-2.frag", "main", 5, 10, 0, 15, 30, true, true },
{ "spv.register.subpass.frag", "main", 0, 20, 0, 0, 0, true, true },
{ "spv.buffer.autoassign.frag", "main", 5, 10, 0, 15, 30, true, true },
{ "spv.ssbo.autoassign.frag", "main", 5, 10, 0, 15, 30, true, true },
{ "spv.ssboAlias.frag", "main", 0, 0, 0, 0, 83, true, false },
{ "spv.rw.autoassign.frag", "main", 5, 10, 20, 15, 30, true, true },
{ "spv.register.autoassign.rangetest.frag", "main",
glslang::TQualifier::layoutBindingEnd-2,
glslang::TQualifier::layoutBindingEnd+5,
20, 30, true, false },
}),
FileNameAsCustomTestSuffixIoMap
);
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Hlsl, GlslIoMap,
::testing::ValuesIn(std::vector<IoMapData>{
{ "spv.glsl.register.autoassign.frag", "main", 5, 10, 0, 20, 30, true, false },
{ "spv.glsl.register.noautoassign.frag", "main", 5, 10, 0, 15, 30, false, false },
}),
FileNameAsCustomTestSuffixIoMap
);
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileOpenGLToSpirvTest,
::testing::ValuesIn(std::vector<std::string>({
"spv.460.frag",
"spv.460.vert",
"spv.460.comp",
"spv.atomic.comp",
"spv.atomicFloat.comp",
"spv.atomicFloat_Error.comp",
"spv.glFragColor.frag",
"spv.rankShift.comp",
"spv.specConst.vert",
"spv.specTexture.frag",
"spv.OVR_multiview.vert",
"spv.uniformInitializer.frag",
"spv.uniformInitializerSpecConstant.frag",
"spv.uniformInitializerStruct.frag",
"spv.xfbOffsetOnBlockMembersAssignment.vert",
"spv.xfbOffsetOnStructMembersAssignment.vert",
"spv.xfbOverlapOffsetCheckWithBlockAndMember.vert",
"spv.xfbStrideJustOnce.vert",
})),
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_SUITE_P(
Glsl, VulkanSemantics,
::testing::ValuesIn(std::vector<std::string>({
"vulkan.frag",
"vulkan.vert",
"vulkan.comp",
"samplerlessTextureFunctions.frag",
"spv.specConstArrayCheck.vert",
})),
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_SUITE_P(
Glsl, OpenGLSemantics,
::testing::ValuesIn(std::vector<std::string>({
"glspv.esversion.vert",
"glspv.version.frag",
"glspv.version.vert",
"glspv.frag",
"glspv.vert",
})),
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_SUITE_P(
Glsl, VulkanAstSemantics,
::testing::ValuesIn(std::vector<std::string>({
"vulkan.ast.vert",
})),
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileVulkanToSpirvTestAMD,
::testing::ValuesIn(std::vector<std::string>({
"spv.16bitxfb.vert",
"spv.float16.frag",
"spv.float16Fetch.frag",
"spv.imageLoadStoreLod.frag",
"spv.int16.frag",
"spv.int16.amd.frag",
"spv.shaderBallotAMD.comp",
"spv.shaderFragMaskAMD.frag",
"spv.textureGatherBiasLod.frag",
})),
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileVulkanToSpirvTestNV,
::testing::ValuesIn(std::vector<std::string>({
"spv.sampleMaskOverrideCoverage.frag",
"spv.GeometryShaderPassthrough.geom",
"spv.viewportArray2.vert",
"spv.viewportArray2.tesc",
"spv.stereoViewRendering.vert",
"spv.stereoViewRendering.tesc",
"spv.multiviewPerViewAttributes.vert",
"spv.multiviewPerViewAttributes.tesc",
"spv.atomicInt64.comp",
"spv.atomicStoreInt64.comp",
"spv.shadingRate.frag",
"spv.RayGenShader.rgen",
"spv.RayGenShaderArray.rgen",
"spv.RayGenShader_Errors.rgen",
"spv.RayConstants.rgen",
"spv.IntersectShader.rint",
"spv.IntersectShader_Errors.rint",
"spv.AnyHitShader.rahit",
"spv.AnyHitShader_Errors.rahit",
"spv.ClosestHitShader.rchit",
"spv.ClosestHitShader_Errors.rchit",
"spv.MissShader.rmiss",
"spv.MissShader_Errors.rmiss",
"spv.RayCallable.rcall",
"spv.RayCallable_Errors.rcall",
"spv.fragmentShaderBarycentric.frag",
"spv.fragmentShaderBarycentric2.frag",
"spv.computeShaderDerivatives.comp",
"spv.computeShaderDerivatives2.comp",
"spv.shaderImageFootprint.frag",
"spv.meshShaderBuiltins.mesh",
"spv.meshShaderUserDefined.mesh",
"spv.meshShaderPerViewBuiltins.mesh",
"spv.meshShaderPerViewUserDefined.mesh",
"spv.meshShaderPerView_Errors.mesh",
"spv.meshShaderSharedMem.mesh",
"spv.meshShaderTaskMem.mesh",
"spv.320.meshShaderUserDefined.mesh",
"spv.meshShaderRedeclBuiltins.mesh",
"spv.meshShaderRedeclPerViewBuiltins.mesh",
"spv.meshTaskShader.task",
"spv.perprimitiveNV.frag",
})),
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileVulkanToSpirv14TestNV,
::testing::ValuesIn(std::vector<std::string>({
"spv.RayGenShaderMotion.rgen",
"spv.IntersectShaderMotion.rint",
"spv.AnyHitShaderMotion.rahit",
"spv.ClosestHitShaderMotion.rchit",
"spv.MissShaderMotion.rmiss",
})),
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileUpgradeTextureToSampledTextureAndDropSamplersTest,
::testing::ValuesIn(std::vector<std::string>({
"spv.texture.sampler.transform.frag",
})),
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_SUITE_P(
Glsl, CompileVulkanToNonSemanticShaderDebugInfoTest,
::testing::ValuesIn(std::vector<std::string>({
"spv.debuginfo.glsl.vert",
"spv.debuginfo.glsl.frag",
"spv.debuginfo.glsl.comp",
"spv.debuginfo.glsl.geom",
"spv.debuginfo.glsl.tesc",
"spv.debuginfo.glsl.tese",
"spv.debuginfo.const_params.glsl.comp"
})),
FileNameAsCustomTestSuffix
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest

180
externals/glslang/gtests/TestFixture.cpp vendored Normal file
View File

@@ -0,0 +1,180 @@
//
// Copyright (C) 2016 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include "TestFixture.h"
namespace glslangtest {
std::string FileNameAsCustomTestSuffix(
const ::testing::TestParamInfo<std::string>& info)
{
std::string name = info.param;
// A valid test case suffix cannot have '.' and '-' inside.
std::replace(name.begin(), name.end(), '.', '_');
std::replace(name.begin(), name.end(), '-', '_');
return name;
}
EShLanguage GetShaderStage(const std::string& stage)
{
if (stage == "vert") {
return EShLangVertex;
} else if (stage == "tesc") {
return EShLangTessControl;
} else if (stage == "tese") {
return EShLangTessEvaluation;
} else if (stage == "geom") {
return EShLangGeometry;
} else if (stage == "frag") {
return EShLangFragment;
} else if (stage == "comp") {
return EShLangCompute;
} else if (stage == "rgen") {
return EShLangRayGen;
} else if (stage == "rint") {
return EShLangIntersect;
} else if (stage == "rahit") {
return EShLangAnyHit;
} else if (stage == "rchit") {
return EShLangClosestHit;
} else if (stage == "rmiss") {
return EShLangMiss;
} else if (stage == "rcall") {
return EShLangCallable;
} else if (stage == "task") {
return EShLangTask;
} else if (stage == "mesh") {
return EShLangMesh;
} else {
assert(0 && "Unknown shader stage");
return EShLangCount;
}
}
EShMessages DeriveOptions(Source source, Semantics semantics, Target target)
{
EShMessages result = EShMsgCascadingErrors;
switch (source) {
case Source::GLSL:
break;
case Source::HLSL:
result = static_cast<EShMessages>(result | EShMsgReadHlsl);
break;
}
switch (target) {
case Target::AST:
result = static_cast<EShMessages>(result | EShMsgAST);
break;
case Target::Spv:
result = static_cast<EShMessages>(result | EShMsgSpvRules);
result = static_cast<EShMessages>(result | EShMsgKeepUncalled);
break;
case Target::BothASTAndSpv:
result = static_cast<EShMessages>(result | EShMsgSpvRules | EShMsgAST);
result = static_cast<EShMessages>(result | EShMsgKeepUncalled);
break;
};
switch (semantics) {
case Semantics::OpenGL:
break;
case Semantics::Vulkan:
result = static_cast<EShMessages>(result | EShMsgVulkanRules | EShMsgSpvRules);
break;
}
result = static_cast<EShMessages>(result | EShMsgHlslLegalization);
return result;
}
std::pair<bool, std::string> ReadFile(const std::string& path)
{
std::ifstream fstream(path, std::ios::in);
if (fstream) {
std::string contents;
fstream.seekg(0, std::ios::end);
contents.reserve((std::string::size_type)fstream.tellg());
fstream.seekg(0, std::ios::beg);
contents.assign((std::istreambuf_iterator<char>(fstream)),
std::istreambuf_iterator<char>());
return std::make_pair(true, contents);
}
return std::make_pair(false, "");
}
std::pair<bool, std::vector<std::uint32_t> > ReadSpvBinaryFile(const std::string& path)
{
std::ifstream fstream(path, std::fstream::in | std::fstream::binary);
if (!fstream)
return std::make_pair(false, std::vector<std::uint32_t>());
std::vector<std::uint32_t> contents;
// Reserve space (for efficiency, not for correctness)
fstream.seekg(0, fstream.end);
contents.reserve(size_t(fstream.tellg()) / sizeof(std::uint32_t));
fstream.seekg(0, fstream.beg);
// There is no istream iterator traversing by uint32_t, so we must loop.
while (!fstream.eof()) {
std::uint32_t inWord;
fstream.read((char *)&inWord, sizeof(inWord));
if (!fstream.eof())
contents.push_back(inWord);
}
return std::make_pair(true, contents); // hopefully, c++11 move semantics optimizes the copy away.
}
bool WriteFile(const std::string& path, const std::string& contents)
{
std::ofstream fstream(path, std::ios::out);
if (!fstream) return false;
fstream << contents;
fstream.flush();
return true;
}
std::string GetSuffix(const std::string& name)
{
const size_t pos = name.rfind('.');
return (pos == std::string::npos) ? "" : name.substr(name.rfind('.') + 1);
}
} // namespace glslangtest

721
externals/glslang/gtests/TestFixture.h vendored Normal file
View File

@@ -0,0 +1,721 @@
//
// Copyright (C) 2016 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#ifndef GLSLANG_GTESTS_TEST_FIXTURE_H
#define GLSLANG_GTESTS_TEST_FIXTURE_H
#include <cstdint>
#include <fstream>
#include <sstream>
#include <streambuf>
#include <tuple>
#include <string>
#include <gtest/gtest.h>
#include "SPIRV/GlslangToSpv.h"
#include "SPIRV/disassemble.h"
#include "SPIRV/doc.h"
#include "SPIRV/SPVRemapper.h"
#include "glslang/Public/ResourceLimits.h"
#include "glslang/Public/ShaderLang.h"
#include "Initializer.h"
#include "Settings.h"
namespace glslangtest {
// This function is used to provide custom test name suffixes based on the
// shader source file names. Otherwise, the test name suffixes will just be
// numbers, which are not quite obvious.
std::string FileNameAsCustomTestSuffix(
const ::testing::TestParamInfo<std::string>& info);
enum class Source {
GLSL,
HLSL,
};
// Enum for shader compilation semantics.
enum class Semantics {
OpenGL,
Vulkan
};
// Enum for compilation target.
enum class Target {
AST,
Spv,
BothASTAndSpv,
};
EShLanguage GetShaderStage(const std::string& stage);
EShMessages DeriveOptions(Source, Semantics, Target);
// Reads the content of the file at the given |path|. On success, returns true
// and the contents; otherwise, returns false and an empty string.
std::pair<bool, std::string> ReadFile(const std::string& path);
std::pair<bool, std::vector<std::uint32_t> > ReadSpvBinaryFile(const std::string& path);
// Writes the given |contents| into the file at the given |path|. Returns true
// on successful output.
bool WriteFile(const std::string& path, const std::string& contents);
// Returns the suffix of the given |name|.
std::string GetSuffix(const std::string& name);
// Base class for glslang integration tests. It contains many handy utility-like
// methods such as reading shader source files, compiling into AST/SPIR-V, and
// comparing with expected outputs.
//
// To write value-Parameterized tests:
// using ValueParamTest = GlslangTest<::testing::TestWithParam<std::string>>;
// To use as normal fixture:
// using FixtureTest = GlslangTest<::testing::Test>;
template <typename GT>
class GlslangTest : public GT {
public:
GlslangTest()
: defaultVersion(100),
defaultProfile(ENoProfile),
forceVersionProfile(false),
isForwardCompatible(false) {
// Perform validation by default.
spirvOptions.validate = true;
}
// Tries to load the contents from the file at the given |path|. On success,
// writes the contents into |contents|. On failure, errors out.
void tryLoadFile(const std::string& path, const std::string& tag,
std::string* contents)
{
bool fileReadOk;
std::tie(fileReadOk, *contents) = ReadFile(path);
ASSERT_TRUE(fileReadOk) << "Cannot open " << tag << " file: " << path;
}
// Tries to load the contents from the file at the given |path|. On success,
// writes the contents into |contents|. On failure, errors out.
void tryLoadSpvFile(const std::string& path, const std::string& tag,
std::vector<uint32_t>& contents)
{
bool fileReadOk;
std::tie(fileReadOk, contents) = ReadSpvBinaryFile(path);
ASSERT_TRUE(fileReadOk) << "Cannot open " << tag << " file: " << path;
}
// Checks the equality of |expected| and |real|. If they are not equal,
// write |real| to the given file named as |fname| if update mode is on.
void checkEqAndUpdateIfRequested(const std::string& expected,
const std::string& real,
const std::string& fname,
const std::string& errorsAndWarnings = "")
{
// In order to output the message we want under proper circumstances,
// we need the following operator<< stuff.
EXPECT_EQ(expected, real)
<< (GlobalTestSettings.updateMode
? ("Mismatch found and update mode turned on - "
"flushing expected result output.\n")
: "")
<< "The following warnings/errors occurred:\n"
<< errorsAndWarnings;
// Update the expected output file if requested.
// It looks weird to duplicate the comparison between expected_output
// and stream.str(). However, if creating a variable for the comparison
// result, we cannot have pretty print of the string diff in the above.
if (GlobalTestSettings.updateMode && expected != real) {
EXPECT_TRUE(WriteFile(fname, real)) << "Flushing failed";
}
}
struct ShaderResult {
std::string shaderName;
std::string output;
std::string error;
};
// A struct for holding all the information returned by glslang compilation
// and linking.
struct GlslangResult {
std::vector<ShaderResult> shaderResults;
std::string linkingOutput;
std::string linkingError;
bool validationResult;
std::string spirvWarningsErrors;
std::string spirv; // Optional SPIR-V disassembly text.
};
// Compiles and the given source |code| of the given shader |stage| into
// the target under the semantics conveyed via |controls|. Returns true
// and modifies |shader| on success.
bool compile(glslang::TShader* shader, const std::string& code,
const std::string& entryPointName, EShMessages controls,
const TBuiltInResource* resources=nullptr,
const std::string* shaderName=nullptr)
{
const char* shaderStrings = code.data();
const int shaderLengths = static_cast<int>(code.size());
const char* shaderNames = nullptr;
if ((controls & EShMsgDebugInfo) && shaderName != nullptr) {
shaderNames = shaderName->data();
shader->setStringsWithLengthsAndNames(
&shaderStrings, &shaderLengths, &shaderNames, 1);
} else
shader->setStringsWithLengths(&shaderStrings, &shaderLengths, 1);
if (!entryPointName.empty()) shader->setEntryPoint(entryPointName.c_str());
return shader->parse(
(resources ? resources : GetDefaultResources()),
defaultVersion, isForwardCompatible, controls);
}
// Compiles and links the given source |code| of the given shader
// |stage| into the target under the semantics specified via |controls|.
// Returns a GlslangResult instance containing all the information generated
// during the process. If the target includes SPIR-V, also disassembles
// the result and returns disassembly text.
GlslangResult compileAndLink(
const std::string& shaderName, const std::string& code,
const std::string& entryPointName, EShMessages controls,
glslang::EShTargetClientVersion clientTargetVersion,
glslang::EShTargetLanguageVersion targetLanguageVersion,
bool flattenUniformArrays = false,
EShTextureSamplerTransformMode texSampTransMode = EShTexSampTransKeep,
bool enableOptimizer = false,
bool enableDebug = false,
bool enableNonSemanticShaderDebugInfo = false,
bool automap = true)
{
const EShLanguage stage = GetShaderStage(GetSuffix(shaderName));
glslang::TShader shader(stage);
if (automap) {
shader.setAutoMapLocations(true);
shader.setAutoMapBindings(true);
}
shader.setTextureSamplerTransformMode(texSampTransMode);
#ifdef ENABLE_HLSL
shader.setFlattenUniformArrays(flattenUniformArrays);
#endif
if (controls & EShMsgSpvRules) {
if (controls & EShMsgVulkanRules) {
shader.setEnvInput((controls & EShMsgReadHlsl) ? glslang::EShSourceHlsl
: glslang::EShSourceGlsl,
stage, glslang::EShClientVulkan, 100);
shader.setEnvClient(glslang::EShClientVulkan, clientTargetVersion);
shader.setEnvTarget(glslang::EShTargetSpv, targetLanguageVersion);
} else {
shader.setEnvInput((controls & EShMsgReadHlsl) ? glslang::EShSourceHlsl
: glslang::EShSourceGlsl,
stage, glslang::EShClientOpenGL, 100);
shader.setEnvClient(glslang::EShClientOpenGL, clientTargetVersion);
shader.setEnvTarget(glslang::EshTargetSpv, glslang::EShTargetSpv_1_0);
}
}
bool success = compile(
&shader, code, entryPointName, controls, nullptr, &shaderName);
glslang::TProgram program;
program.addShader(&shader);
success &= program.link(controls);
#if !defined(GLSLANG_WEB)
if (success)
program.mapIO();
#endif
if (success && (controls & EShMsgSpvRules)) {
spv::SpvBuildLogger logger;
std::vector<uint32_t> spirv_binary;
options().disableOptimizer = !enableOptimizer;
options().generateDebugInfo = enableDebug;
options().emitNonSemanticShaderDebugInfo = enableNonSemanticShaderDebugInfo;
options().emitNonSemanticShaderDebugSource = enableNonSemanticShaderDebugInfo;
glslang::GlslangToSpv(*program.getIntermediate(stage),
spirv_binary, &logger, &options());
std::ostringstream disassembly_stream;
spv::Parameterize();
spv::Disassemble(disassembly_stream, spirv_binary);
bool validation_result = !options().validate || logger.getAllMessages().empty();
return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},},
program.getInfoLog(), program.getInfoDebugLog(),
validation_result, logger.getAllMessages(), disassembly_stream.str()};
} else {
return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},},
program.getInfoLog(), program.getInfoDebugLog(), true, "", ""};
}
}
// Compiles and links the given source |code| of the given shader
// |stage| into the target under the semantics specified via |controls|.
// Returns a GlslangResult instance containing all the information generated
// during the process. If the target includes SPIR-V, also disassembles
// the result and returns disassembly text.
GlslangResult compileLinkIoMap(
const std::string shaderName, const std::string& code,
const std::string& entryPointName, EShMessages controls,
int baseSamplerBinding,
int baseTextureBinding,
int baseImageBinding,
int baseUboBinding,
int baseSsboBinding,
bool autoMapBindings,
bool flattenUniformArrays)
{
const EShLanguage stage = GetShaderStage(GetSuffix(shaderName));
glslang::TShader shader(stage);
shader.setShiftSamplerBinding(baseSamplerBinding);
shader.setShiftTextureBinding(baseTextureBinding);
shader.setShiftImageBinding(baseImageBinding);
shader.setShiftUboBinding(baseUboBinding);
shader.setShiftSsboBinding(baseSsboBinding);
shader.setAutoMapBindings(autoMapBindings);
shader.setAutoMapLocations(true);
#ifdef ENABLE_HLSL
shader.setFlattenUniformArrays(flattenUniformArrays);
#endif
bool success = compile(&shader, code, entryPointName, controls);
glslang::TProgram program;
program.addShader(&shader);
success &= program.link(controls);
#if !defined(GLSLANG_WEB)
if (success)
program.mapIO();
#endif
spv::SpvBuildLogger logger;
if (success && (controls & EShMsgSpvRules)) {
std::vector<uint32_t> spirv_binary;
glslang::GlslangToSpv(*program.getIntermediate(stage),
spirv_binary, &logger, &options());
std::ostringstream disassembly_stream;
spv::Parameterize();
spv::Disassemble(disassembly_stream, spirv_binary);
bool validation_result = !options().validate || logger.getAllMessages().empty();
return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},},
program.getInfoLog(), program.getInfoDebugLog(),
validation_result, logger.getAllMessages(), disassembly_stream.str()};
} else {
return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},},
program.getInfoLog(), program.getInfoDebugLog(), true, "", ""};
}
}
// This is like compileAndLink but with remapping of the SPV binary
// through spirvbin_t::remap(). While technically this could be merged
// with compileAndLink() above (with the remap step optionally being a no-op)
// it is given separately here for ease of future extraction.
GlslangResult compileLinkRemap(
const std::string shaderName, const std::string& code,
const std::string& entryPointName, EShMessages controls,
const unsigned int remapOptions = spv::spirvbin_t::NONE)
{
const EShLanguage stage = GetShaderStage(GetSuffix(shaderName));
glslang::TShader shader(stage);
shader.setAutoMapBindings(true);
shader.setAutoMapLocations(true);
bool success = compile(&shader, code, entryPointName, controls);
glslang::TProgram program;
program.addShader(&shader);
success &= program.link(controls);
#if !defined(GLSLANG_WEB)
if (success)
program.mapIO();
#endif
if (success && (controls & EShMsgSpvRules)) {
spv::SpvBuildLogger logger;
std::vector<std::string> whiteListStrings;
std::vector<uint32_t> spirv_binary;
glslang::GlslangToSpv(*program.getIntermediate(stage),
spirv_binary, &logger, &options());
spv::spirvbin_t(0 /*verbosity*/).remap(spirv_binary, whiteListStrings, remapOptions);
std::ostringstream disassembly_stream;
spv::Parameterize();
spv::Disassemble(disassembly_stream, spirv_binary);
bool validation_result = !options().validate || logger.getAllMessages().empty();
return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},},
program.getInfoLog(), program.getInfoDebugLog(),
validation_result, logger.getAllMessages(), disassembly_stream.str()};
} else {
return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},},
program.getInfoLog(), program.getInfoDebugLog(), true, "", ""};
}
}
// remap the binary in 'code' with the options in remapOptions
GlslangResult remap(
const std::string shaderName, const std::vector<uint32_t>& code,
EShMessages controls,
const unsigned int remapOptions = spv::spirvbin_t::NONE)
{
if ((controls & EShMsgSpvRules)) {
std::vector<uint32_t> spirv_binary(code); // scratch copy
std::vector<std::string> whiteListStrings;
spv::spirvbin_t(0 /*verbosity*/).remap(spirv_binary, whiteListStrings, remapOptions);
std::ostringstream disassembly_stream;
spv::Parameterize();
spv::Disassemble(disassembly_stream, spirv_binary);
return {{{shaderName, "", ""},},
"", "",
true, "", disassembly_stream.str()};
} else {
return {{{shaderName, "", ""},}, "", "", true, "", ""};
}
}
void outputResultToStream(std::ostringstream* stream,
const GlslangResult& result,
EShMessages controls)
{
const auto outputIfNotEmpty = [&stream](const std::string& str) {
if (!str.empty()) *stream << str << "\n";
};
for (const auto& shaderResult : result.shaderResults) {
*stream << shaderResult.shaderName << "\n";
outputIfNotEmpty(shaderResult.output);
outputIfNotEmpty(shaderResult.error);
}
outputIfNotEmpty(result.linkingOutput);
outputIfNotEmpty(result.linkingError);
if (!result.validationResult) {
*stream << "Validation failed\n";
}
if (controls & EShMsgSpvRules) {
*stream
<< (result.spirv.empty()
? "SPIR-V is not generated for failed compile or link\n"
: result.spirv);
}
}
void loadFileCompileAndCheck(const std::string& testDir,
const std::string& testName,
Source source,
Semantics semantics,
glslang::EShTargetClientVersion clientTargetVersion,
glslang::EShTargetLanguageVersion targetLanguageVersion,
Target target,
bool automap = true,
const std::string& entryPointName="",
const std::string& baseDir="/baseResults/",
const bool enableOptimizer = false,
const bool enableDebug = false,
const bool enableNonSemanticShaderDebugInfo = false)
{
const std::string inputFname = testDir + "/" + testName;
const std::string expectedOutputFname =
testDir + baseDir + testName + ".out";
std::string input, expectedOutput;
tryLoadFile(inputFname, "input", &input);
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
EShMessages controls = DeriveOptions(source, semantics, target);
if (enableOptimizer)
controls = static_cast<EShMessages>(controls & ~EShMsgHlslLegalization);
if (enableDebug)
controls = static_cast<EShMessages>(controls | EShMsgDebugInfo);
GlslangResult result = compileAndLink(testName, input, entryPointName, controls, clientTargetVersion,
targetLanguageVersion, false, EShTexSampTransKeep, enableOptimizer, enableDebug,
enableNonSemanticShaderDebugInfo, automap);
// Generate the hybrid output in the way of glslangValidator.
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(),
expectedOutputFname, result.spirvWarningsErrors);
}
void loadFileCompileAndCheckWithOptions(const std::string &testDir,
const std::string &testName,
Source source,
Semantics semantics,
glslang::EShTargetClientVersion clientTargetVersion,
glslang::EShTargetLanguageVersion targetLanguageVersion,
Target target, bool automap = true, const std::string &entryPointName = "",
const std::string &baseDir = "/baseResults/",
const EShMessages additionalOptions = EShMessages::EShMsgDefault)
{
const std::string inputFname = testDir + "/" + testName;
const std::string expectedOutputFname = testDir + baseDir + testName + ".out";
std::string input, expectedOutput;
tryLoadFile(inputFname, "input", &input);
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
EShMessages controls = DeriveOptions(source, semantics, target);
controls = static_cast<EShMessages>(controls | additionalOptions);
GlslangResult result = compileAndLink(testName, input, entryPointName, controls, clientTargetVersion,
targetLanguageVersion, false, EShTexSampTransKeep, false, automap);
// Generate the hybrid output in the way of glslangValidator.
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname);
}
void loadFileCompileFlattenUniformsAndCheck(const std::string& testDir,
const std::string& testName,
Source source,
Semantics semantics,
Target target,
const std::string& entryPointName="")
{
const std::string inputFname = testDir + "/" + testName;
const std::string expectedOutputFname =
testDir + "/baseResults/" + testName + ".out";
std::string input, expectedOutput;
tryLoadFile(inputFname, "input", &input);
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
const EShMessages controls = DeriveOptions(source, semantics, target);
GlslangResult result = compileAndLink(testName, input, entryPointName, controls,
glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0, true);
// Generate the hybrid output in the way of glslangValidator.
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(),
expectedOutputFname, result.spirvWarningsErrors);
}
void loadFileCompileIoMapAndCheck(const std::string& testDir,
const std::string& testName,
Source source,
Semantics semantics,
Target target,
const std::string& entryPointName,
int baseSamplerBinding,
int baseTextureBinding,
int baseImageBinding,
int baseUboBinding,
int baseSsboBinding,
bool autoMapBindings,
bool flattenUniformArrays)
{
const std::string inputFname = testDir + "/" + testName;
const std::string expectedOutputFname =
testDir + "/baseResults/" + testName + ".out";
std::string input, expectedOutput;
tryLoadFile(inputFname, "input", &input);
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
const EShMessages controls = DeriveOptions(source, semantics, target);
GlslangResult result = compileLinkIoMap(testName, input, entryPointName, controls,
baseSamplerBinding, baseTextureBinding, baseImageBinding,
baseUboBinding, baseSsboBinding,
autoMapBindings,
flattenUniformArrays);
// Generate the hybrid output in the way of glslangValidator.
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(),
expectedOutputFname, result.spirvWarningsErrors);
}
void loadFileCompileRemapAndCheck(const std::string& testDir,
const std::string& testName,
Source source,
Semantics semantics,
Target target,
const std::string& entryPointName="",
const unsigned int remapOptions = spv::spirvbin_t::NONE)
{
const std::string inputFname = testDir + "/" + testName;
const std::string expectedOutputFname =
testDir + "/baseResults/" + testName + ".out";
std::string input, expectedOutput;
tryLoadFile(inputFname, "input", &input);
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
const EShMessages controls = DeriveOptions(source, semantics, target);
GlslangResult result = compileLinkRemap(testName, input, entryPointName, controls, remapOptions);
// Generate the hybrid output in the way of glslangValidator.
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(),
expectedOutputFname, result.spirvWarningsErrors);
}
void loadFileRemapAndCheck(const std::string& testDir,
const std::string& testName,
Source source,
Semantics semantics,
Target target,
const unsigned int remapOptions = spv::spirvbin_t::NONE)
{
const std::string inputFname = testDir + "/" + testName;
const std::string expectedOutputFname =
testDir + "/baseResults/" + testName + ".out";
std::vector<std::uint32_t> input;
std::string expectedOutput;
tryLoadSpvFile(inputFname, "input", input);
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
const EShMessages controls = DeriveOptions(source, semantics, target);
GlslangResult result = remap(testName, input, controls, remapOptions);
// Generate the hybrid output in the way of glslangValidator.
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(),
expectedOutputFname, result.spirvWarningsErrors);
}
// Preprocesses the given |source| code. On success, returns true, the
// preprocessed shader, and warning messages. Otherwise, returns false, an
// empty string, and error messages.
std::tuple<bool, std::string, std::string> preprocess(
const std::string& source)
{
const char* shaderStrings = source.data();
const int shaderLengths = static_cast<int>(source.size());
glslang::TShader shader(EShLangVertex);
shader.setStringsWithLengths(&shaderStrings, &shaderLengths, 1);
std::string ppShader;
glslang::TShader::ForbidIncluder includer;
const bool success = shader.preprocess(
GetDefaultResources(), defaultVersion, defaultProfile,
forceVersionProfile, isForwardCompatible, (EShMessages)(EShMsgOnlyPreprocessor | EShMsgCascadingErrors),
&ppShader, includer);
std::string log = shader.getInfoLog();
log += shader.getInfoDebugLog();
if (success) {
return std::make_tuple(true, ppShader, log);
} else {
return std::make_tuple(false, "", log);
}
}
void loadFilePreprocessAndCheck(const std::string& testDir,
const std::string& testName)
{
const std::string inputFname = testDir + "/" + testName;
const std::string expectedOutputFname =
testDir + "/baseResults/" + testName + ".out";
const std::string expectedErrorFname =
testDir + "/baseResults/" + testName + ".err";
std::string input, expectedOutput, expectedError;
tryLoadFile(inputFname, "input", &input);
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
tryLoadFile(expectedErrorFname, "expected error", &expectedError);
bool ppOk;
std::string output, error;
std::tie(ppOk, output, error) = preprocess(input);
if (!output.empty()) output += '\n';
if (!error.empty()) error += '\n';
checkEqAndUpdateIfRequested(expectedOutput, output,
expectedOutputFname);
checkEqAndUpdateIfRequested(expectedError, error,
expectedErrorFname);
}
void loadCompileUpgradeTextureToSampledTextureAndDropSamplersAndCheck(const std::string& testDir,
const std::string& testName,
Source source,
Semantics semantics,
Target target,
const std::string& entryPointName = "")
{
const std::string inputFname = testDir + "/" + testName;
const std::string expectedOutputFname = testDir + "/baseResults/" + testName + ".out";
std::string input, expectedOutput;
tryLoadFile(inputFname, "input", &input);
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
const EShMessages controls = DeriveOptions(source, semantics, target);
GlslangResult result = compileAndLink(testName, input, entryPointName, controls,
glslang::EShTargetVulkan_1_0, glslang::EShTargetSpv_1_0, false,
EShTexSampTransUpgradeTextureRemoveSampler);
// Generate the hybrid output in the way of glslangValidator.
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(),
expectedOutputFname, result.spirvWarningsErrors);
}
glslang::SpvOptions& options() { return spirvOptions; }
private:
const int defaultVersion;
const EProfile defaultProfile;
const bool forceVersionProfile;
const bool isForwardCompatible;
glslang::SpvOptions spirvOptions;
};
} // namespace glslangtest
#endif // GLSLANG_GTESTS_TEST_FIXTURE_H

View File

@@ -0,0 +1,306 @@
//
// Copyright (C) 2016-2017 Google, Inc.
// Copyright (C) 2020 The Khronos Group 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
//
#include <algorithm>
#include <gtest/gtest.h>
#include "TestFixture.h"
#include "glslang/MachineIndependent/iomapper.h"
#include "glslang/MachineIndependent/reflection.h"
#ifndef GLSLANG_WEB
namespace glslangtest {
namespace {
struct vkRelaxedData {
std::vector<std::string> fileNames;
std::vector<std::vector<std::string>> resourceSetBindings;
};
using VulkanRelaxedTest = GlslangTest <::testing::TestWithParam<vkRelaxedData>>;
template<class T>
std::string interfaceName(T symbol) {
return symbol.getType()->getBasicType() == glslang::EbtBlock ? std::string(symbol.getType()->getTypeName().c_str()) : symbol.name;
}
bool verifyIOMapping(std::string& linkingError, glslang::TProgram& program) {
bool success = true;
// Verify IO Mapping by generating reflection for each stage individually
// and comparing layout qualifiers on the results
int reflectionOptions = EShReflectionDefault;
//reflectionOptions |= EShReflectionStrictArraySuffix;
//reflectionOptions |= EShReflectionBasicArraySuffix;
reflectionOptions |= EShReflectionIntermediateIO;
reflectionOptions |= EShReflectionSeparateBuffers;
reflectionOptions |= EShReflectionAllBlockVariables;
//reflectionOptions |= EShReflectionUnwrapIOBlocks;
success &= program.buildReflection(reflectionOptions);
// check that the reflection output from the individual stages all makes sense..
std::vector<glslang::TReflection> stageReflections;
for (int s = 0; s < EShLangCount; ++s) {
if (program.getIntermediate((EShLanguage)s)) {
stageReflections.emplace_back((EShReflectionOptions)reflectionOptions, (EShLanguage)s, (EShLanguage)s);
success &= stageReflections.back().addStage((EShLanguage)s, *program.getIntermediate((EShLanguage)s));
}
}
// check that input/output locations match between stages
auto it = stageReflections.begin();
auto nextIt = it + 1;
for (; nextIt != stageReflections.end(); it++, nextIt++) {
int numOut = it->getNumPipeOutputs();
std::map<std::string, const glslang::TObjectReflection*> pipeOut;
for (int i = 0; i < numOut; i++) {
const glslang::TObjectReflection& out = it->getPipeOutput(i);
std::string name = interfaceName(out);
pipeOut[name] = &out;
}
int numIn = nextIt->getNumPipeInputs();
for (int i = 0; i < numIn; i++) {
auto in = nextIt->getPipeInput(i);
std::string name = interfaceName(in);
auto out = pipeOut.find(name);
if (out != pipeOut.end()) {
auto inQualifier = in.getType()->getQualifier();
auto outQualifier = out->second->getType()->getQualifier();
success &= outQualifier.layoutLocation == inQualifier.layoutLocation;
// These are not part of a matched interface. Other cases still need to be added.
} else if (name != "gl_FrontFacing" && name != "gl_FragCoord") {
success &= false;
}
}
}
// compare uniforms in each stage to the program
{
int totalUniforms = program.getNumUniformVariables();
std::map<std::string, const glslang::TObjectReflection*> programUniforms;
for (int i = 0; i < totalUniforms; i++) {
const glslang::TObjectReflection& uniform = program.getUniform(i);
std::string name = interfaceName(uniform);
programUniforms[name] = &uniform;
}
it = stageReflections.begin();
for (; it != stageReflections.end(); it++) {
int numUniform = it->getNumUniforms();
std::map<std::string, glslang::TObjectReflection> uniforms;
for (int i = 0; i < numUniform; i++) {
glslang::TObjectReflection uniform = it->getUniform(i);
std::string name = interfaceName(uniform);
auto programUniform = programUniforms.find(name);
if (programUniform != programUniforms.end()) {
auto stageQualifier = uniform.getType()->getQualifier();
auto programQualifier = programUniform->second->getType()->getQualifier();
success &= stageQualifier.layoutLocation == programQualifier.layoutLocation;
success &= stageQualifier.layoutBinding == programQualifier.layoutBinding;
success &= stageQualifier.layoutSet == programQualifier.layoutSet;
}
else {
success &= false;
}
}
}
}
// compare uniform blocks in each stage to the program table
{
int totalUniforms = program.getNumUniformBlocks();
std::map<std::string, const glslang::TObjectReflection*> programUniforms;
for (int i = 0; i < totalUniforms; i++) {
const glslang::TObjectReflection& uniform = program.getUniformBlock(i);
std::string name = interfaceName(uniform);
programUniforms[name] = &uniform;
}
it = stageReflections.begin();
for (; it != stageReflections.end(); it++) {
int numUniform = it->getNumUniformBlocks();
std::map<std::string, glslang::TObjectReflection> uniforms;
for (int i = 0; i < numUniform; i++) {
glslang::TObjectReflection uniform = it->getUniformBlock(i);
std::string name = interfaceName(uniform);
auto programUniform = programUniforms.find(name);
if (programUniform != programUniforms.end()) {
auto stageQualifier = uniform.getType()->getQualifier();
auto programQualifier = programUniform->second->getType()->getQualifier();
success &= stageQualifier.layoutLocation == programQualifier.layoutLocation;
success &= stageQualifier.layoutBinding == programQualifier.layoutBinding;
success &= stageQualifier.layoutSet == programQualifier.layoutSet;
}
else {
success &= false;
}
}
}
}
if (!success) {
linkingError += "Mismatched cross-stage IO\n";
}
return success;
}
TEST_P(VulkanRelaxedTest, FromFile)
{
const auto& fileNames = GetParam().fileNames;
const auto& resourceSetBindings = GetParam().resourceSetBindings;
Semantics semantics = Semantics::Vulkan;
const size_t fileCount = fileNames.size();
const EShMessages controls = DeriveOptions(Source::GLSL, semantics, Target::BothASTAndSpv);
GlslangResult result;
// Compile each input shader file.
bool success = true;
std::vector<std::unique_ptr<glslang::TShader>> shaders;
for (size_t i = 0; i < fileCount; ++i) {
std::string contents;
tryLoadFile(GlobalTestSettings.testRoot + "/" + fileNames[i],
"input", &contents);
shaders.emplace_back(
new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i]))));
auto* shader = shaders.back().get();
shader->setAutoMapLocations(true);
shader->setAutoMapBindings(true);
shader->setEnvInput(glslang::EShSourceGlsl, shader->getStage(), glslang::EShClientVulkan, 100);
shader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
shader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0);
// Use vulkan relaxed option
shader->setEnvInputVulkanRulesRelaxed();
success &= compile(shader, contents, "", controls);
result.shaderResults.push_back(
{ fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog() });
}
// Link all of them.
glslang::TProgram program;
for (const auto& shader : shaders) program.addShader(shader.get());
success &= program.link(controls);
result.linkingOutput = program.getInfoLog();
result.linkingError = program.getInfoDebugLog();
if (!resourceSetBindings.empty()) {
assert(resourceSetBindings.size() == fileNames.size());
for (size_t i = 0; i < shaders.size(); i++)
shaders[i]->setResourceSetBinding(resourceSetBindings[i]);
}
unsigned int stage = 0;
glslang::TIntermediate* firstIntermediate = nullptr;
while (!program.getIntermediate((EShLanguage)stage) && stage < EShLangCount) { stage++; }
firstIntermediate = program.getIntermediate((EShLanguage)stage);
glslang::TDefaultGlslIoResolver resolver(*firstIntermediate);
glslang::TGlslIoMapper ioMapper;
if (success) {
success &= program.mapIO(&resolver, &ioMapper);
result.linkingOutput = program.getInfoLog();
result.linkingError = program.getInfoDebugLog();
}
success &= verifyIOMapping(result.linkingError, program);
result.validationResult = success;
if (success && (controls & EShMsgSpvRules)) {
for (int stage = 0; stage < EShLangCount; ++stage) {
if (program.getIntermediate((EShLanguage)stage)) {
spv::SpvBuildLogger logger;
std::vector<uint32_t> spirv_binary;
options().disableOptimizer = false;
glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage),
spirv_binary, &logger, &options());
std::ostringstream disassembly_stream;
spv::Parameterize();
spv::Disassemble(disassembly_stream, spirv_binary);
result.spirvWarningsErrors += logger.getAllMessages();
result.spirv += disassembly_stream.str();
result.validationResult &= !options().validate || logger.getAllMessages().empty();
}
}
}
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
// Check with expected results.
const std::string expectedOutputFname =
GlobalTestSettings.testRoot + "/baseResults/" + fileNames.front() + ".out";
std::string expectedOutput;
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname,
result.spirvWarningsErrors);
}
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, VulkanRelaxedTest,
::testing::ValuesIn(std::vector<vkRelaxedData>({
{{"vk.relaxed.frag"}},
{{"vk.relaxed.link1.frag", "vk.relaxed.link2.frag"}},
{{"vk.relaxed.stagelink.0.0.vert", "vk.relaxed.stagelink.0.1.vert", "vk.relaxed.stagelink.0.2.vert", "vk.relaxed.stagelink.0.0.frag", "vk.relaxed.stagelink.0.1.frag", "vk.relaxed.stagelink.0.2.frag"}},
{{"vk.relaxed.stagelink.vert", "vk.relaxed.stagelink.frag"}},
{{"vk.relaxed.errorcheck.vert", "vk.relaxed.errorcheck.frag"}},
{{"vk.relaxed.changeSet.vert", "vk.relaxed.changeSet.frag" }, { {"0"}, {"1"} } },
}))
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest
#endif

79
externals/glslang/gtests/main.cpp vendored Normal file
View File

@@ -0,0 +1,79 @@
//
// Copyright (C) 2016 Google, 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
#include <memory>
#include <string>
#include <gtest/gtest.h>
#include "Initializer.h"
#include "Settings.h"
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
std::unique_ptr<glslangtest::GlslangInitializer> initializer(
new glslangtest::GlslangInitializer);
glslangtest::GlobalTestSettings.initializer = initializer.get();
for (int i = 1; i < argc; ++i) {
if (std::string("--update-mode") == argv[i]) {
glslangtest::GlobalTestSettings.updateMode = true;
}
if (std::string("--test-root") == argv[i]) {
// Allow the user set the test root directory. This is useful
// for testing with files from another source tree.
if (i + 1 < argc) {
glslangtest::GlobalTestSettings.testRoot = argv[i + 1];
i++;
} else {
printf("error: --test-root requires an argument\n");
return 1;
}
}
if (std::string("--help") == argv[i]) {
printf("\nExtra options:\n\n");
printf(" --update-mode\n Update the golden results for the tests.\n");
printf(" --test-root <arg>\n Specify the test root directory (useful for testing with\n files from another source tree).\n");
}
}
const int result = RUN_ALL_TESTS();
glslangtest::GlobalTestSettings.initializer = nullptr;
return result;
}

39
externals/glslang/gtests/pch.h vendored Normal file
View File

@@ -0,0 +1,39 @@
#ifndef _PCH_H
#define _PCH_H
//
// Copyright (C) 2018 The Khronos Group 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:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE
// COPYRIGHT HOLDERS OR 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.
//
#include "TestFixture.h"
#endif /* _PCH_H */