Externals: Update glslang to upstream commit 32d3ec3

This commit is contained in:
Stenzek
2018-06-02 07:26:43 +00:00
parent 160d16f1b3
commit bc96557ec4
149 changed files with 47830 additions and 13886 deletions

56
Externals/glslang/gtests/AST.FromFile.cpp vendored Normal file → Executable file
View File

@ -41,13 +41,27 @@ namespace {
using CompileToAstTest = GlslangTest<::testing::TestWithParam<std::string>>;
#ifdef NV_EXTENSIONS
using CompileToAstTestNV = GlslangTest<::testing::TestWithParam<std::string>>;
#endif
TEST_P(CompileToAstTest, FromFile)
{
loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(),
Source::GLSL, Semantics::OpenGL,
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::OpenGL, glslang::EShTargetVulkan_1_0,
Target::AST);
}
#ifdef NV_EXTENSIONS
// 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,
Target::AST);
}
#endif
// clang-format off
INSTANTIATE_TEST_CASE_P(
Glsl, CompileToAstTest,
@ -62,6 +76,7 @@ INSTANTIATE_TEST_CASE_P(
"versionsErrors.frag",
"versionsErrors.vert",
"100.frag",
"100samplerExternal.frag",
"120.vert",
"120.frag",
"130.vert",
@ -77,8 +92,14 @@ INSTANTIATE_TEST_CASE_P(
"matrixError.vert",
"cppSimple.vert",
"cppIndent.vert",
"cppIntMinOverNegativeOne.frag",
"cppNest.vert",
"cppBad.vert",
"cppBad2.vert",
"cppComplexExpr.vert",
"cppDeepNest.frag",
"cppPassMacroName.frag",
"cppRelaxSkipTokensErrors.vert",
"badChars.frag",
"pointCoord.frag",
"array.frag",
@ -91,6 +112,7 @@ INSTANTIATE_TEST_CASE_P(
"300layout.frag",
"300operations.frag",
"300block.frag",
"300samplerExternal.frag",
"310.comp",
"310.vert",
"310.geom",
@ -99,10 +121,18 @@ INSTANTIATE_TEST_CASE_P(
"310.tese",
"310implicitSizeArrayError.vert",
"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",
@ -134,6 +164,7 @@ INSTANTIATE_TEST_CASE_P(
"430.vert",
"430.comp",
"430AofA.frag",
"435.vert",
"440.vert",
"440.frag",
"450.vert",
@ -142,8 +173,11 @@ INSTANTIATE_TEST_CASE_P(
"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",
@ -166,17 +200,24 @@ INSTANTIATE_TEST_CASE_P(
"loopsArtificial.frag",
"matrix.frag",
"matrix2.frag",
"mixedArrayDecls.frag",
"nonuniform.frag",
"newTexture.frag",
"Operations.frag",
"overlongLiteral.frag",
"prepost.frag",
"runtimeArray.vert",
"simpleFunctionCall.frag",
"stringToDouble.vert",
"structAssignment.frag",
"structDeref.frag",
"structure.frag",
"swizzle.frag",
"invalidSwizzle.vert",
"syntaxError.frag",
"test.frag",
"texture.frag",
"tokenPaste.vert",
"types.frag",
"uniformArray.frag",
"variableArrayIndex.frag",
@ -189,9 +230,20 @@ INSTANTIATE_TEST_CASE_P(
"precise.tesc",
"precise_struct_block.vert",
"maxClipDistances.vert",
"findFunction.frag",
})),
FileNameAsCustomTestSuffix
);
#ifdef NV_EXTENSIONS
INSTANTIATE_TEST_CASE_P(
Glsl, CompileToAstTestNV,
::testing::ValuesIn(std::vector<std::string>({
"nvShaderNoperspectiveInterpolation.frag",
})),
FileNameAsCustomTestSuffix
);
#endif
// clang-format on
} // anonymous namespace

View File

@ -46,7 +46,7 @@ using DefaultResourceTest = GlslangTest<::testing::Test>;
TEST_F(DefaultResourceTest, FromFile)
{
const std::string path = GLSLANG_TEST_DIRECTORY "/baseResults/test.conf";
const std::string path = GlobalTestSettings.testRoot + "/baseResults/test.conf";
std::string expectedConfig;
tryLoadFile(path, "expected resource limit", &expectedConfig);
const std::string realConfig = glslang::GetDefaultTBuiltInResourceString();

View File

@ -1,40 +1,59 @@
if (TARGET gmock)
message(STATUS "Google Mock found - building tests")
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
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}/Config.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Hlsl.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Link.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Pp.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Spv.FromFile.cpp
)
# Test related source files
${CMAKE_CURRENT_SOURCE_DIR}/AST.FromFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BuiltInResource.FromFile.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
add_executable(glslangtests ${TEST_SOURCES})
set_property(TARGET glslangtests PROPERTY FOLDER tests)
glslang_set_link_args(glslangtests)
install(TARGETS glslangtests
RUNTIME DESTINATION bin)
# -- Remapper tests
${CMAKE_CURRENT_SOURCE_DIR}/Remap.FromFile.cpp)
target_compile_definitions(glslangtests
PRIVATE GLSLANG_TEST_DIRECTORY="${CMAKE_CURRENT_SOURCE_DIR}/../Test")
target_include_directories(glslangtests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}
${gmock_SOURCE_DIR}/include
${gtest_SOURCE_DIR}/include)
target_link_libraries(glslangtests PRIVATE
glslang OSDependent OGLCompiler HLSL glslang
SPIRV glslang-default-resource-limits gmock)
add_test(NAME glslang-gtests COMMAND glslangtests)
add_executable(glslangtests ${TEST_SOURCES})
set_property(TARGET glslangtests PROPERTY FOLDER tests)
glslang_set_link_args(glslangtests)
if(ENABLE_GLSLANG_INSTALL)
install(TARGETS glslangtests
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif(ENABLE_GLSLANG_INSTALL)
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)
set(LIBRARIES
SPVRemapper glslang OSDependent OGLCompiler glslang
SPIRV glslang-default-resource-limits)
if(ENABLE_HLSL)
set(LIBRARIES ${LIBRARIES} HLSL)
endif(ENABLE_HLSL)
target_link_libraries(glslangtests PRIVATE ${LIBRARIES} gmock)
add_test(NAME glslang-gtests
COMMAND glslangtests --test-root "${GLSLANG_TEST_DIRECTORY}")
endif()
endif()

View File

@ -54,8 +54,8 @@ TEST_P(ConfigTest, FromFile)
// Get the contents for input shader and limit configurations.
std::string shaderContents, configContents;
tryLoadFile(GLSLANG_TEST_DIRECTORY "/" + testCase.input, "input", &shaderContents);
tryLoadFile(GLSLANG_TEST_DIRECTORY "/" + testCase.config, "limits config", &configContents);
tryLoadFile(GlobalTestSettings.testRoot + "/" + testCase.input, "input", &shaderContents);
tryLoadFile(GlobalTestSettings.testRoot + "/" + testCase.config, "limits config", &configContents);
// Decode limit configurations.
TBuiltInResource resources = {};
@ -86,7 +86,7 @@ TEST_P(ConfigTest, FromFile)
// Check with expected results.
const std::string expectedOutputFname =
GLSLANG_TEST_DIRECTORY "/baseResults/" + testCase.output;
GlobalTestSettings.testRoot + "/baseResults/" + testCase.output;
std::string expectedOutput;
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
@ -97,7 +97,7 @@ TEST_P(ConfigTest, FromFile)
INSTANTIATE_TEST_CASE_P(
Glsl, ConfigTest,
::testing::ValuesIn(std::vector<TestCaseSpec>({
{"specExamples.vert", "baseResults/test.conf", "specExamples.vert.out", (EShMessages)(EShMsgAST | EShMsgCascadingErrors)},
{"specExamples.vert", "baseResults/test.conf", "specExamplesConf.vert.out", (EShMessages)(EShMsgAST | EShMsgCascadingErrors)},
{"100Limits.vert", "100.conf", "100LimitsConf.vert.out", EShMsgCascadingErrors},
})),
);

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

File diff suppressed because it is too large Load Diff

View File

@ -58,42 +58,228 @@ std::string FileNameAsCustomTestSuffix(
}
using HlslCompileTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslVulkan1_1CompileTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslCompileAndFlattenTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslLegalizeTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
// Compiling HLSL to SPIR-V under Vulkan semantics. Expected to successfully
// generate both AST and SPIR-V.
// Compiling HLSL to pre-legalized SPIR-V under Vulkan semantics. Expected
// to successfully generate both AST and SPIR-V.
TEST_P(HlslCompileTest, FromFile)
{
loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam().fileName,
Source::HLSL, Semantics::Vulkan,
Target::BothASTAndSpv, GetParam().entryPoint);
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_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,
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,
Target::Spv, true, GetParam().entryPoint,
"/baseLegalResults/", true);
}
// clang-format off
INSTANTIATE_TEST_CASE_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.emptystructreturn.frag", "main"},
{"hlsl.emptystructreturn.vert", "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.void.tesc", "main"},
{"hlsl.hull.ctrlpt-1.tesc", "main"},
{"hlsl.hull.ctrlpt-2.tesc", "main"},
{"hlsl.groupid.comp", "main"},
{"hlsl.identifier.sample.frag", "main"},
{"hlsl.if.frag", "PixelShaderFunction"},
{"hlsl.imagefetch-subvec4.comp", "main"},
{"hlsl.implicitBool.frag", "main"},
{"hlsl.inf.vert", "main"},
{"hlsl.inoutquals.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.evalfns.frag", "main"},
{"hlsl.intrinsics.d3dcolortoubyte4.frag", "main"},
{"hlsl.intrinsics.double.frag", "PixelShaderFunction"},
{"hlsl.intrinsics.f1632.frag", "PixelShaderFunction"},
{"hlsl.intrinsics.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.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.promote.atomic.frag", "main"},
{"hlsl.promote.binary.frag", "main"},
{"hlsl.promote.vec1.frag", "main"},
{"hlsl.promotions.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"},
@ -102,29 +288,150 @@ INSTANTIATE_TEST_CASE_P(
{"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.self_cast.frag", "main"},
{"hlsl.snorm.uav.comp", "main"},
{"hlsl.staticMemberFunction.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.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.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.void.frag", "PixelShaderFunction"}
}),
FileNameAsCustomTestSuffix
);
// clang-format on
// clang-format off
INSTANTIATE_TEST_CASE_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"},
}),
FileNameAsCustomTestSuffix
);
// clang-format on
// clang-format off
INSTANTIATE_TEST_CASE_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_CASE_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.partialFlattenLocal.vert", "main"},
{"hlsl.partialFlattenMixed.vert", "main"}
}),
FileNameAsCustomTestSuffix
);
// clang-format on
#endif
} // anonymous namespace
} // namespace glslangtest

View File

@ -40,46 +40,14 @@
namespace glslangtest {
// Initializes glslang on creation, and destroys it on completion.
// And provides .Acquire() as a way to reinitialize glslang if semantics change.
// This object is expected to be a singleton, so that internal glslang state
// can be correctly handled.
//
// TODO(antiagainst): It's a known bug that some of the internal states need to
// be reset if semantics change:
// https://github.com/KhronosGroup/glslang/issues/166
// Therefore, the following mechanism is needed. Remove this once the above bug
// gets fixed.
class GlslangInitializer {
public:
GlslangInitializer() : lastMessages(EShMsgCascadingErrors)
{
glslang::InitializeProcess();
}
GlslangInitializer() { glslang::InitializeProcess(); }
~GlslangInitializer() { glslang::FinalizeProcess(); }
// A token indicates that the glslang is reinitialized (if necessary) to the
// required semantics. And that won't change until the token is destroyed.
class InitializationToken {
};
// Re-initializes glsl state iff the previous messages and the current
// messages are incompatible. We assume external synchronization, i.e.
// there is at most one acquired token at any one time.
InitializationToken acquire(EShMessages new_messages)
{
if ((lastMessages ^ new_messages) &
(EShMsgVulkanRules | EShMsgSpvRules | EShMsgReadHlsl)) {
glslang::FinalizeProcess();
glslang::InitializeProcess();
}
lastMessages = new_messages;
return InitializationToken();
}
private:
EShMessages lastMessages;
};
} // namespace glslangtest

View File

@ -0,0 +1,114 @@
//
// 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;
// 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 (success && (controls & EShMsgSpvRules)) {
spv::SpvBuildLogger logger;
std::vector<uint32_t> spirv_binary;
glslang::SpvOptions options;
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();
}
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_CASE_P(
Glsl, LinkTestVulkan,
::testing::ValuesIn(std::vector<std::vector<std::string>>({
{"link1.vk.frag", "link2.vk.frag"},
})),
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest

View File

@ -55,7 +55,7 @@ TEST_P(LinkTest, FromFile)
std::vector<std::unique_ptr<glslang::TShader>> shaders;
for (size_t i = 0; i < fileCount; ++i) {
std::string contents;
tryLoadFile(GLSLANG_TEST_DIRECTORY "/" + fileNames[i],
tryLoadFile(GlobalTestSettings.testRoot + "/" + fileNames[i],
"input", &contents);
shaders.emplace_back(
new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i]))));
@ -77,7 +77,7 @@ TEST_P(LinkTest, FromFile)
// Check with expected results.
const std::string expectedOutputFname =
GLSLANG_TEST_DIRECTORY "/baseResults/" + fileNames.front() + ".out";
GlobalTestSettings.testRoot + "/baseResults/" + fileNames.front() + ".out";
std::string expectedOutput;
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
@ -99,6 +99,7 @@ INSTANTIATE_TEST_CASE_P(
{"150.tesc", "150.tese", "400.tesc", "400.tese", "410.tesc", "420.tesc", "420.tese"},
{"max_vertices_0.geom"},
{"es-link1.frag", "es-link2.frag"},
{"missingBodies.vert"}
})),
);
// clang-format on

View File

@ -43,7 +43,7 @@ using PreprocessingTest = GlslangTest<::testing::TestWithParam<std::string>>;
TEST_P(PreprocessingTest, FromFile)
{
loadFilePreprocessAndCheck(GLSLANG_TEST_DIRECTORY, GetParam());
loadFilePreprocessAndCheck(GlobalTestSettings.testRoot, GetParam());
}
// clang-format off

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_CASE_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

View File

@ -36,6 +36,16 @@
namespace glslangtest {
GTestSettings GlobalTestSettings = {nullptr, false};
// 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

View File

@ -35,6 +35,8 @@
#ifndef GLSLANG_GTESTS_SETTINGS_H
#define GLSLANG_GTESTS_SETTINGS_H
#include <string>
namespace glslangtest {
class GlslangInitializer;
@ -45,6 +47,8 @@ struct GTestSettings {
// 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;

274
Externals/glslang/gtests/Spv.FromFile.cpp vendored Normal file → Executable file
View File

@ -1,4 +1,4 @@
//
//
// Copyright (C) 2016 Google, Inc.
//
// All rights reserved.
@ -41,18 +41,56 @@
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 CompileVulkan1_1ToSpirvTest = 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>>;
#ifdef AMD_EXTENSIONS
using CompileVulkanToSpirvTestAMD = GlslangTest<::testing::TestWithParam<std::string>>;
#endif
#ifdef NV_EXTENSIONS
using CompileVulkanToSpirvTestNV = GlslangTest<::testing::TestWithParam<std::string>>;
#endif
using CompileUpgradeTextureToSampledTextureAndDropSamplersTest = GlslangTest<::testing::TestWithParam<std::string>>;
// Compiling GLSL to SPIR-V under Vulkan semantics. Expected to successfully
// generate SPIR-V.
TEST_P(CompileVulkanToSpirvTest, FromFile)
{
loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(),
Source::GLSL, Semantics::Vulkan,
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0,
Target::Spv);
}
TEST_P(CompileVulkan1_1ToSpirvTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_1,
Target::Spv);
}
@ -60,8 +98,8 @@ TEST_P(CompileVulkanToSpirvTest, FromFile)
// generate SPIR-V.
TEST_P(CompileOpenGLToSpirvTest, FromFile)
{
loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(),
Source::GLSL, Semantics::OpenGL,
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::OpenGL, glslang::EShTargetVulkan_1_0,
Target::Spv);
}
@ -69,28 +107,89 @@ TEST_P(CompileOpenGLToSpirvTest, FromFile)
// SPIR-V.
TEST_P(VulkanSemantics, FromFile)
{
loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(),
Source::GLSL, Semantics::Vulkan,
Target::Spv);
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0,
Target::Spv, false);
}
// GLSL-level Vulkan semantics test. Expected to error out before generating
// SPIR-V.
TEST_P(OpenGLSemantics, FromFile)
{
loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(),
Source::GLSL, Semantics::OpenGL,
Target::Spv);
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::OpenGL, glslang::EShTargetVulkan_1_0,
Target::Spv, false);
}
// GLSL-level Vulkan semantics test that need to see the AST for validation.
TEST_P(VulkanAstSemantics, FromFile)
{
loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(),
Source::GLSL, Semantics::Vulkan,
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan, glslang::EShTargetVulkan_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);
}
#ifdef AMD_EXTENSIONS
// 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,
Target::Spv);
}
#endif
#ifdef NV_EXTENSIONS
// 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,
Target::Spv);
}
#endif
TEST_P(CompileUpgradeTextureToSampledTextureAndDropSamplersTest, FromFile)
{
loadCompileUpgradeTextureToSampledTextureAndDropSamplersAndCheck(GlobalTestSettings.testRoot,
GetParam(),
Source::GLSL,
Semantics::Vulkan,
Target::Spv);
}
// clang-format off
INSTANTIATE_TEST_CASE_P(
Glsl, CompileVulkanToSpirvTest,
@ -98,6 +197,7 @@ INSTANTIATE_TEST_CASE_P(
// 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",
@ -129,15 +229,22 @@ INSTANTIATE_TEST_CASE_P(
"spv.430.frag",
"spv.430.vert",
"spv.450.tesc",
"spv.450.geom",
"spv.450.noRedecl.tesc",
"spv.accessChain.frag",
"spv.aggOps.frag",
"spv.always-discard.frag",
"spv.always-discard2.frag",
"spv.arbPostDepthCoverage.frag",
"spv.arbPostDepthCoverage_Error.frag",
"spv.bitCast.frag",
"spv.bool.vert",
"spv.boolInBlock.frag",
"spv.branch-return.vert",
"spv.builtInXFB.vert",
"spv.conditionalDiscard.frag",
"spv.constStruct.vert",
"spv.controlFlowAttributes.frag",
"spv.conversion.frag",
"spv.dataOut.frag",
"spv.dataOutIndirect.frag",
@ -147,13 +254,19 @@ INSTANTIATE_TEST_CASE_P(
"spv.discard-dce.frag",
"spv.doWhileLoop.frag",
"spv.earlyReturnDiscard.frag",
"spv.extPostDepthCoverage.frag",
"spv.extPostDepthCoverage_Error.frag",
"spv.flowControl.frag",
"spv.forLoop.frag",
"spv.forwardFun.frag",
"spv.fullyCovered.frag",
"spv.functionCall.frag",
"spv.functionNestedOpaque.vert",
"spv.functionSemantics.frag",
"spv.GeometryShaderPassthrough.geom",
"spv.interpOps.frag",
"spv.int64.frag",
"spv.intOps.vert",
"spv.layoutNested.vert",
"spv.length.frag",
"spv.localAggregates.frag",
@ -164,16 +277,28 @@ INSTANTIATE_TEST_CASE_P(
"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.noWorkgroup.comp",
"spv.offsets.frag",
"spv.Operations.frag",
"spv.intOps.vert",
"spv.paramMemory.frag",
"spv.precision.frag",
"spv.precisionNonESSamp.frag",
"spv.prepost.frag",
"spv.qualifiers.vert",
"spv.sample.frag",
"spv.sampleId.frag",
"spv.samplePosition.frag",
"spv.sampleMaskOverrideCoverage.frag",
"spv.shaderBallot.comp",
"spv.shaderDrawParams.vert",
"spv.shaderGroupVote.comp",
"spv.shaderStencilExport.frag",
"spv.shiftOps.frag",
"spv.simpleFunctionCall.frag",
"spv.simpleMat.vert",
@ -184,10 +309,12 @@ INSTANTIATE_TEST_CASE_P(
"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.types.frag",
"spv.uint.frag",
@ -195,6 +322,7 @@ INSTANTIATE_TEST_CASE_P(
"spv.variableArrayIndex.frag",
"spv.varyingArray.frag",
"spv.varyingArrayIndirect.frag",
"spv.vecMatConstruct.frag",
"spv.voidFunction.frag",
"spv.whileLoop.frag",
"spv.AofA.frag",
@ -202,24 +330,99 @@ INSTANTIATE_TEST_CASE_P(
"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.storageBuffer.vert",
"spv.precise.tese",
"spv.precise.tesc",
"spv.vulkan100.subgroupArithmetic.comp",
"spv.vulkan100.subgroupPartitioned.comp",
"spv.xfb.vert",
"spv.xfb2.vert",
"spv.xfb3.vert",
})),
FileNameAsCustomTestSuffix
);
// clang-format off
INSTANTIATE_TEST_CASE_P(
Glsl, CompileVulkan1_1ToSpirvTest,
::testing::ValuesIn(std::vector<std::string>({
"spv.deviceGroup.frag",
"spv.drawParams.vert",
"spv.int8.frag",
"spv.vulkan110.int16.frag",
"spv.int32.frag",
"spv.explicittypes.frag",
"spv.float32.frag",
"spv.float64.frag",
"spv.multiView.frag",
"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.subgroupClustered.comp",
"spv.subgroupClusteredNeg.comp",
"spv.subgroupPartitioned.comp",
"spv.subgroupShuffle.comp",
"spv.subgroupShuffleRelative.comp",
"spv.subgroupQuad.comp",
"spv.subgroupVote.comp",
"spv.vulkan110.storageBuffer.vert",
})),
FileNameAsCustomTestSuffix
);
// clang-format off
INSTANTIATE_TEST_CASE_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_CASE_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_CASE_P(
Glsl, CompileOpenGLToSpirvTest,
::testing::ValuesIn(std::vector<std::string>({
"spv.460.frag",
"spv.460.vert",
"spv.460.comp",
"spv.atomic.comp",
"spv.glFragColor.frag",
"spv.rankShift.comp",
"spv.specConst.vert",
"spv.OVR_multiview.vert",
})),
FileNameAsCustomTestSuffix
);
@ -253,6 +456,49 @@ INSTANTIATE_TEST_CASE_P(
})),
FileNameAsCustomTestSuffix
);
#ifdef AMD_EXTENSIONS
INSTANTIATE_TEST_CASE_P(
Glsl, CompileVulkanToSpirvTestAMD,
::testing::ValuesIn(std::vector<std::string>({
"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
);
#endif
#ifdef NV_EXTENSIONS
INSTANTIATE_TEST_CASE_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",
})),
FileNameAsCustomTestSuffix
);
#endif
INSTANTIATE_TEST_CASE_P(
Glsl, CompileUpgradeTextureToSampledTextureAndDropSamplersTest,
::testing::ValuesIn(std::vector<std::string>({
"spv.texture.sampler.transform.frag",
})),
FileNameAsCustomTestSuffix
);
// clang-format on
} // anonymous namespace

View File

@ -74,7 +74,7 @@ EShMessages DeriveOptions(Source source, Semantics semantics, Target target)
case Source::GLSL:
break;
case Source::HLSL:
result = EShMsgReadHlsl;
result = static_cast<EShMessages>(result | EShMsgReadHlsl);
break;
}
@ -84,9 +84,11 @@ EShMessages DeriveOptions(Source source, Semantics semantics, Target target)
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;
};
@ -98,6 +100,8 @@ EShMessages DeriveOptions(Source source, Semantics semantics, Target target)
break;
}
result = static_cast<EShMessages>(result | EShMsgHlslLegalization);
return result;
}
@ -116,6 +120,32 @@ std::pair<bool, std::string> ReadFile(const std::string& path)
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);

View File

@ -35,31 +35,25 @@
#ifndef GLSLANG_GTESTS_TEST_FIXTURE_H
#define GLSLANG_GTESTS_TEST_FIXTURE_H
#include <stdint.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 "StandAlone/ResourceLimits.h"
#include "glslang/Public/ShaderLang.h"
#include "Initializer.h"
#include "Settings.h"
// 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.
#ifndef GLSLANG_TEST_DIRECTORY
#error \
"GLSLANG_TEST_DIRECTORY needs to be defined for gtest to locate test files."
#endif
namespace glslangtest {
// This function is used to provide custom test name suffixes based on the
@ -76,7 +70,7 @@ enum class Source {
// Enum for shader compilation semantics.
enum class Semantics {
OpenGL,
Vulkan,
Vulkan
};
// Enum for compilation target.
@ -93,6 +87,7 @@ 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.
@ -128,6 +123,16 @@ public:
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,
@ -179,8 +184,6 @@ public:
shader->setStringsWithLengths(&shaderStrings, &shaderLengths, 1);
if (!entryPointName.empty()) shader->setEntryPoint(entryPointName.c_str());
// Reinitialize glslang if the semantics change.
GlobalTestSettings.initializer->acquire(controls);
return shader->parse(
(resources ? resources : &glslang::DefaultTBuiltInResource),
defaultVersion, isForwardCompatible, controls);
@ -193,11 +196,41 @@ public:
// the result and returns disassembly text.
GlslangResult compileAndLink(
const std::string shaderName, const std::string& code,
const std::string& entryPointName, EShMessages controls)
const std::string& entryPointName, EShMessages controls,
glslang::EShTargetClientVersion clientTargetVersion,
bool flattenUniformArrays = false,
EShTextureSamplerTransformMode texSampTransMode = EShTexSampTransKeep,
bool enableOptimizer = false,
bool automap = true)
{
const EShLanguage kind = GetShaderStage(GetSuffix(shaderName));
const EShLanguage stage = GetShaderStage(GetSuffix(shaderName));
glslang::TShader shader(stage);
if (automap) {
shader.setAutoMapLocations(true);
shader.setAutoMapBindings(true);
}
shader.setTextureSamplerTransformMode(texSampTransMode);
shader.setFlattenUniformArrays(flattenUniformArrays);
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,
clientTargetVersion == glslang::EShTargetVulkan_1_1 ? glslang::EShTargetSpv_1_3
: glslang::EShTargetSpv_1_0);
} 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);
}
}
glslang::TShader shader(kind);
bool success = compile(&shader, code, entryPointName, controls);
glslang::TProgram program;
@ -208,7 +241,64 @@ public:
if (success && (controls & EShMsgSpvRules)) {
std::vector<uint32_t> spirv_binary;
glslang::GlslangToSpv(*program.getIntermediate(kind),
glslang::SpvOptions options;
options.disableOptimizer = !enableOptimizer;
glslang::GlslangToSpv(*program.getIntermediate(stage),
spirv_binary, &logger, &options);
std::ostringstream disassembly_stream;
spv::Parameterize();
spv::Disassemble(disassembly_stream, spirv_binary);
return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},},
program.getInfoLog(), program.getInfoDebugLog(),
logger.getAllMessages(), disassembly_stream.str()};
} else {
return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},},
program.getInfoLog(), program.getInfoDebugLog(), "", ""};
}
}
// 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);
shader.setFlattenUniformArrays(flattenUniformArrays);
bool success = compile(&shader, code, entryPointName, controls);
glslang::TProgram program;
program.addShader(&shader);
success &= program.link(controls);
success &= program.mapIO();
spv::SpvBuildLogger logger;
if (success && (controls & EShMsgSpvRules)) {
std::vector<uint32_t> spirv_binary;
glslang::GlslangToSpv(*program.getIntermediate(stage),
spirv_binary, &logger);
std::ostringstream disassembly_stream;
@ -223,6 +313,71 @@ public:
}
}
// 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);
spv::SpvBuildLogger logger;
if (success && (controls & EShMsgSpvRules)) {
std::vector<uint32_t> spirv_binary;
glslang::GlslangToSpv(*program.getIntermediate(stage),
spirv_binary, &logger);
spv::spirvbin_t(0 /*verbosity*/).remap(spirv_binary, remapOptions);
std::ostringstream disassembly_stream;
spv::Parameterize();
spv::Disassemble(disassembly_stream, spirv_binary);
return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},},
program.getInfoLog(), program.getInfoDebugLog(),
logger.getAllMessages(), disassembly_stream.str()};
} else {
return {{{shaderName, shader.getInfoLog(), shader.getInfoDebugLog()},},
program.getInfoLog(), program.getInfoDebugLog(), "", ""};
}
}
// 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
spv::spirvbin_t(0 /*verbosity*/).remap(spirv_binary, remapOptions);
std::ostringstream disassembly_stream;
spv::Parameterize();
spv::Disassemble(disassembly_stream, spirv_binary);
return {{{shaderName, "", ""},},
"", "",
"", disassembly_stream.str()};
} else {
return {{{shaderName, "", ""},}, "", "", "", ""};
}
}
void outputResultToStream(std::ostringstream* stream,
const GlslangResult& result,
EShMessages controls)
@ -252,8 +407,41 @@ public:
const std::string& testName,
Source source,
Semantics semantics,
glslang::EShTargetClientVersion clientTargetVersion,
Target target,
const std::string& entryPointName="")
bool automap = true,
const std::string& entryPointName="",
const std::string& baseDir="/baseResults/",
const bool enableOptimizer = 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);
GlslangResult result = compileAndLink(testName, input, entryPointName, controls, clientTargetVersion, false,
EShTexSampTransKeep, enableOptimizer, 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 =
@ -264,7 +452,99 @@ public:
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
const EShMessages controls = DeriveOptions(source, semantics, target);
GlslangResult result = compileAndLink(testName, input, entryPointName, controls);
GlslangResult result = compileAndLink(testName, input, entryPointName, controls,
glslang::EShTargetVulkan_1_0, true);
// Generate the hybrid output in the way of glslangValidator.
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(),
expectedOutputFname);
}
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);
}
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);
}
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;
@ -286,7 +566,7 @@ public:
glslang::TShader shader(EShLangVertex);
shader.setStringsWithLengths(&shaderStrings, &shaderLengths, 1);
std::string ppShader;
glslang::TShader::ForbidInclude includer;
glslang::TShader::ForbidIncluder includer;
const bool success = shader.preprocess(
&glslang::DefaultTBuiltInResource, defaultVersion, defaultProfile,
forceVersionProfile, isForwardCompatible, (EShMessages)(EShMsgOnlyPreprocessor | EShMsgCascadingErrors),
@ -327,6 +607,33 @@ public:
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, false,
EShTexSampTransUpgradeTextureRemoveSampler);
// Generate the hybrid output in the way of glslangValidator.
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(),
expectedOutputFname);
}
private:
const int defaultVersion;
const EProfile defaultProfile;

View File

@ -33,6 +33,7 @@
// POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <string>
#include <gtest/gtest.h>
@ -49,9 +50,24 @@ int main(int argc, char** argv)
glslangtest::GlobalTestSettings.initializer = initializer.get();
for (int i = 1; i < argc; ++i) {
if (!strncmp("--update-mode", argv[i], 13)) {
if (std::string("--update-mode") == argv[i]) {
glslangtest::GlobalTestSettings.updateMode = true;
break;
}
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");
}
}