Path: blob/main/libshaderc/src/shaderc_cpp_test.cc
1558 views
// Copyright 2015 The Shaderc Authors. All rights reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314#include <gmock/gmock.h>15#include <gtest/gtest.h>1617#include <memory>18#include <thread>19#include <unordered_map>2021#include "common_shaders_for_test.h"22#include "shaderc/shaderc.hpp"23#include "spirv-tools/libspirv.hpp"24#include "spirv/unified1/spirv.hpp"2526namespace {2728using shaderc::AssemblyCompilationResult;29using shaderc::CompileOptions;30using shaderc::PreprocessedSourceCompilationResult;31using shaderc::SpvCompilationResult;32using testing::Each;33using testing::Eq;34using testing::HasSubstr;35using testing::Not;3637// Helper function to check if the compilation result indicates a successful38// compilation.39template <typename T>40bool CompilationResultIsSuccess(const shaderc::CompilationResult<T>& result) {41return result.GetCompilationStatus() == shaderc_compilation_status_success;42}4344// Examines whether a compilation result has valid SPIR-V code, by checking the45// magic number in the fixed postion of the byte array in the result object.46// Returns true if the magic number is found at the correct postion, otherwise47// returns false.48bool IsValidSpv(const SpvCompilationResult& result) {49if (!CompilationResultIsSuccess(result)) return false;50size_t length_in_words = result.cend() - result.cbegin();51if (length_in_words < 5) return false;52const uint32_t* bytes = result.cbegin();53return bytes[0] == spv::MagicNumber;54}5556// Compiles a shader and returns true if the result is valid SPIR-V. The57// input_file_name is set to "shader".58bool CompilesToValidSpv(const shaderc::Compiler& compiler,59const std::string& shader, shaderc_shader_kind kind) {60return IsValidSpv(compiler.CompileGlslToSpv(shader, kind, "shader"));61}6263// Compiles a shader with options and returns true if the result is valid64// SPIR-V. The input_file_name is set to "shader".65bool CompilesToValidSpv(const shaderc::Compiler& compiler,66const std::string& shader, shaderc_shader_kind kind,67const CompileOptions& options) {68return IsValidSpv(compiler.CompileGlslToSpv(shader, kind, "shader", options));69}7071// Returns the compiler's output from a compilation result as a string.72template <typename T>73std::string CompilerOutputAsString(74const shaderc::CompilationResult<T>& result) {75return std::string(reinterpret_cast<const char*>(result.cbegin()),76reinterpret_cast<const char*>(result.cend()));77}7879class CppInterface : public testing::Test {80protected:81// Compiles a shader and returns true on success, false on failure.82// The input file name is set to "shader" by default.83bool CompilationSuccess(const std::string& shader,84shaderc_shader_kind kind) const {85return compiler_86.CompileGlslToSpv(shader.c_str(), shader.length(), kind,87"shader")88.GetCompilationStatus() == shaderc_compilation_status_success;89}9091// Compiles a shader with options and returns true on success, false on92// failure.93// The input file name is set to "shader" by default.94bool CompilationSuccess(const std::string& shader, shaderc_shader_kind kind,95const CompileOptions& options) const {96return compiler_97.CompileGlslToSpv(shader.c_str(), shader.length(), kind,98"shader", options)99.GetCompilationStatus() == shaderc_compilation_status_success;100}101102// Compiles a shader, asserts compilation success, and returns the warning103// messages.104// The input file name is set to "shader" by default.105std::string CompilationWarnings(106const std::string& shader, shaderc_shader_kind kind,107// This could default to options_, but that can108// be easily confused with a no-options-provided109// case:110const CompileOptions& options) {111const auto compilation_result =112compiler_.CompileGlslToSpv(shader, kind, "shader", options);113EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)) << kind << '\n'114<< shader;115return compilation_result.GetErrorMessage();116}117118// Compiles a shader, asserts compilation fail, and returns the error119// messages.120std::string CompilationErrors(const std::string& shader,121shaderc_shader_kind kind,122// This could default to options_, but that can123// be easily confused with a no-options-provided124// case:125const CompileOptions& options) {126const auto compilation_result =127compiler_.CompileGlslToSpv(shader, kind, "shader", options);128EXPECT_FALSE(CompilationResultIsSuccess(compilation_result)) << kind << '\n'129<< shader;130return compilation_result.GetErrorMessage();131}132133// Assembles the given SPIR-V assembly and returns true on success.134bool AssemblingSuccess(const std::string& shader,135const CompileOptions& options) const {136return compiler_.AssembleToSpv(shader, options).GetCompilationStatus() ==137shaderc_compilation_status_success;138}139140// Assembles the given SPIR-V assembly and returns true if the result contains141// a valid SPIR-V module.142bool AssemblingValid(const std::string& shader,143const CompileOptions& options) const {144return IsValidSpv(compiler_.AssembleToSpv(shader, options));145}146147// Compiles a shader, expects compilation success, and returns the output148// bytes.149// The input file name is set to "shader" by default.150std::string CompilationOutput(const std::string& shader,151shaderc_shader_kind kind,152const CompileOptions& options) const {153const auto compilation_result =154compiler_.CompileGlslToSpv(shader, kind, "shader", options);155EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)) << kind << '\n';156// Need to make sure you get complete binary data, including embedded nulls.157return CompilerOutputAsString(compilation_result);158}159160// Compiles a shader to SPIR-V assembly, expects compilation success, and161// returns the output bytes.162// The input file name is set to "shader" by default.163std::string AssemblyOutput(const std::string& shader,164shaderc_shader_kind kind,165const CompileOptions& options) const {166const auto compilation_result =167compiler_.CompileGlslToSpvAssembly(shader, kind, "shader", options);168EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)) << kind << '\n';169// Need to make sure you get complete binary data, including embedded nulls.170return CompilerOutputAsString(compilation_result);171}172173// For compiling shaders in subclass tests:174shaderc::Compiler compiler_;175CompileOptions options_;176};177178TEST_F(CppInterface, CompilerValidUponConstruction) {179EXPECT_TRUE(compiler_.IsValid());180}181182TEST_F(CppInterface, MultipleCalls) {183shaderc::Compiler compiler1, compiler2, compiler3;184EXPECT_TRUE(compiler1.IsValid());185EXPECT_TRUE(compiler2.IsValid());186EXPECT_TRUE(compiler3.IsValid());187}188189#ifndef SHADERC_DISABLE_THREADED_TESTS190TEST_F(CppInterface, MultipleThreadsInitializing) {191std::unique_ptr<shaderc::Compiler> compiler1;192std::unique_ptr<shaderc::Compiler> compiler2;193std::unique_ptr<shaderc::Compiler> compiler3;194std::thread t1([&compiler1]() {195compiler1 = std::unique_ptr<shaderc::Compiler>(new shaderc::Compiler());196});197std::thread t2([&compiler2]() {198compiler2 = std::unique_ptr<shaderc::Compiler>(new shaderc::Compiler());199});200std::thread t3([&compiler3]() {201compiler3 = std::unique_ptr<shaderc::Compiler>(new shaderc::Compiler());202});203t1.join();204t2.join();205t3.join();206EXPECT_TRUE(compiler1->IsValid());207EXPECT_TRUE(compiler2->IsValid());208EXPECT_TRUE(compiler3->IsValid());209}210#endif211212TEST_F(CppInterface, CompilerMoves) {213shaderc::Compiler compiler2(std::move(compiler_));214ASSERT_FALSE(compiler_.IsValid());215ASSERT_TRUE(compiler2.IsValid());216}217218TEST_F(CppInterface, EmptyString) {219EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_vertex_shader));220EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_fragment_shader));221}222223TEST_F(CppInterface, AssembleEmptyString) {224EXPECT_TRUE(AssemblingSuccess("", options_));225}226227TEST_F(CppInterface, ResultObjectMoves) {228SpvCompilationResult result = compiler_.CompileGlslToSpv(229kMinimalShader, shaderc_glsl_vertex_shader, "shader");230EXPECT_TRUE(CompilationResultIsSuccess(result));231const SpvCompilationResult result2(std::move(result));232EXPECT_FALSE(CompilationResultIsSuccess(result));233EXPECT_TRUE(CompilationResultIsSuccess(result2));234}235236TEST_F(CppInterface, GarbageString) {237EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_vertex_shader));238EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_fragment_shader));239}240241TEST_F(CppInterface, AssembleGarbageString) {242const auto result = compiler_.AssembleToSpv("jfalkds", options_);243EXPECT_FALSE(CompilationResultIsSuccess(result));244EXPECT_EQ(0u, result.GetNumWarnings());245EXPECT_EQ(1u, result.GetNumErrors());246}247248// TODO(antiagainst): right now there is no assembling difference for all the249// target environments exposed by shaderc. So the following is just testing the250// target environment is accepted.251TEST_F(CppInterface, AssembleTargetEnv) {252options_.SetTargetEnvironment(shaderc_target_env_opengl, 0);253EXPECT_TRUE(AssemblingValid("OpCapability Shader", options_));254}255256TEST_F(CppInterface, MinimalShader) {257EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,258shaderc_glsl_vertex_shader));259EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,260shaderc_glsl_fragment_shader));261}262263TEST_F(CppInterface, AssembleMinimalShader) {264EXPECT_TRUE(AssemblingValid(kMinimalShaderAssembly, options_));265}266267TEST_F(CppInterface, BasicOptions) {268EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,269shaderc_glsl_vertex_shader, options_));270EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,271shaderc_glsl_fragment_shader, options_));272}273274TEST_F(CppInterface, CopiedOptions) {275EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,276shaderc_glsl_vertex_shader, options_));277CompileOptions copied_options(options_);278EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,279shaderc_glsl_fragment_shader, copied_options));280}281282TEST_F(CppInterface, MovedOptions) {283EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,284shaderc_glsl_vertex_shader, options_));285CompileOptions copied_options(std::move(options_));286EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,287shaderc_glsl_fragment_shader, copied_options));288}289290TEST_F(CppInterface, StdAndCString) {291const SpvCompilationResult result1 =292compiler_.CompileGlslToSpv(kMinimalShader, strlen(kMinimalShader),293shaderc_glsl_fragment_shader, "shader");294const SpvCompilationResult result2 = compiler_.CompileGlslToSpv(295std::string(kMinimalShader), shaderc_glsl_fragment_shader, "shader");296EXPECT_TRUE(CompilationResultIsSuccess(result1));297EXPECT_TRUE(CompilationResultIsSuccess(result2));298EXPECT_EQ(std::vector<uint32_t>(result1.cbegin(), result1.cend()),299std::vector<uint32_t>(result2.cbegin(), result2.cend()));300}301302TEST_F(CppInterface, ErrorsReported) {303const SpvCompilationResult result = compiler_.CompileGlslToSpv(304"int f(){return wrongname;}", shaderc_glsl_vertex_shader, "shader");305ASSERT_FALSE(CompilationResultIsSuccess(result));306EXPECT_THAT(result.GetErrorMessage(), HasSubstr("wrongname"));307}308309#ifndef SHADERC_DISABLE_THREADED_TESTS310TEST_F(CppInterface, MultipleThreadsCalling) {311bool results[10];312std::vector<std::thread> threads;313for (auto& r : results) {314threads.emplace_back([this, &r]() {315r = CompilationSuccess(kMinimalShader, shaderc_glsl_vertex_shader);316});317}318for (auto& t : threads) {319t.join();320}321EXPECT_THAT(results, Each(true));322}323#endif324325TEST_F(CppInterface, AccessorsOnNullResultObject) {326const SpvCompilationResult result(nullptr);327EXPECT_FALSE(CompilationResultIsSuccess(result));328EXPECT_EQ(std::string(), result.GetErrorMessage());329EXPECT_EQ(result.cend(), result.cbegin());330EXPECT_EQ(nullptr, result.cbegin());331EXPECT_EQ(nullptr, result.cend());332EXPECT_EQ(nullptr, result.begin());333EXPECT_EQ(nullptr, result.end());334}335336TEST_F(CppInterface, MacroCompileOptions) {337options_.AddMacroDefinition("E", "main");338const std::string kMinimalExpandedShader = "#version 150\nvoid E(){}";339const std::string kMinimalDoubleExpandedShader = "#version 150\nF E(){}";340EXPECT_TRUE(CompilationSuccess(kMinimalExpandedShader,341shaderc_glsl_vertex_shader, options_));342343CompileOptions cloned_options(options_);344// The simplest should still compile with the cloned options.345EXPECT_TRUE(CompilationSuccess(kMinimalExpandedShader,346shaderc_glsl_vertex_shader, cloned_options));347348EXPECT_FALSE(CompilationSuccess(kMinimalDoubleExpandedShader,349shaderc_glsl_vertex_shader, cloned_options));350351cloned_options.AddMacroDefinition("F", "void");352// This should still not work with the original options.353EXPECT_FALSE(CompilationSuccess(kMinimalDoubleExpandedShader,354shaderc_glsl_vertex_shader, options_));355// This should work with the cloned options that have the additional356// parameter.357EXPECT_TRUE(CompilationSuccess(kMinimalDoubleExpandedShader,358shaderc_glsl_vertex_shader, cloned_options));359}360361TEST_F(CppInterface, D_DisassemblyOption) {362const AssemblyCompilationResult result = compiler_.CompileGlslToSpvAssembly(363kMinimalShader, shaderc_glsl_vertex_shader, "shader", options_);364EXPECT_TRUE(CompilationResultIsSuccess(result));365// This should work with both the glslang disassembly format and the366// SPIR-V Tools assembly format.367EXPECT_THAT(CompilerOutputAsString(result), HasSubstr("Capability Shader"));368EXPECT_THAT(CompilerOutputAsString(result), HasSubstr("MemoryModel"));369370CompileOptions cloned_options(options_);371auto result_from_cloned_options = compiler_.CompileGlslToSpvAssembly(372kMinimalShader, shaderc_glsl_vertex_shader, "shader", cloned_options);373EXPECT_TRUE(CompilationResultIsSuccess(result_from_cloned_options));374// The mode should be carried into any clone of the original option object.375EXPECT_THAT(CompilerOutputAsString(result_from_cloned_options),376HasSubstr("Capability Shader"));377EXPECT_THAT(CompilerOutputAsString(result_from_cloned_options),378HasSubstr("MemoryModel"));379}380381TEST_F(CppInterface, DisassembleMinimalShader) {382const AssemblyCompilationResult result = compiler_.CompileGlslToSpvAssembly(383kMinimalShader, shaderc_glsl_vertex_shader, "shader", options_);384EXPECT_TRUE(CompilationResultIsSuccess(result));385for (const auto& substring : kMinimalShaderDisassemblySubstrings) {386EXPECT_THAT(CompilerOutputAsString(result), HasSubstr(substring));387}388}389390TEST_F(CppInterface, ForcedVersionProfileCorrectStd) {391// Forces the version and profile to 450core, which fixes the missing392// #version.393options_.SetForcedVersionProfile(450, shaderc_profile_core);394EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion,395shaderc_glsl_vertex_shader, options_));396}397398TEST_F(CppInterface, ForcedVersionProfileCorrectStdClonedOptions) {399// Forces the version and profile to 450core, which fixes the missing400// #version.401options_.SetForcedVersionProfile(450, shaderc_profile_core);402CompileOptions cloned_options(options_);403EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion,404shaderc_glsl_vertex_shader, cloned_options));405}406407TEST_F(CppInterface, ForcedVersionProfileInvalidModule) {408// Forces the version and profile to 310es, while the source module is invalid409// for this version of GLSL. Compilation should fail.410options_.SetForcedVersionProfile(310, shaderc_profile_es);411EXPECT_THAT(CompilationErrors(kCoreVertShaderWithoutVersion,412shaderc_glsl_vertex_shader, options_),413HasSubstr("error: 'gl_ClipDistance' : undeclared identifier\n"));414}415416TEST_F(CppInterface, ForcedVersionProfileConflictingStd) {417// Forces the version and profile to 450core, which is in conflict with the418// #version in shader.419const std::string kVertexShader =420std::string("#version 310 es\n") + kCoreVertShaderWithoutVersion;421options_.SetForcedVersionProfile(450, shaderc_profile_core);422EXPECT_THAT(423CompilationWarnings(kVertexShader, shaderc_glsl_vertex_shader, options_),424HasSubstr("warning: (version, profile) forced to be (450, core), "425"while in source code it is (310, es)\n"));426}427428TEST_F(CppInterface, ForcedVersionProfileUnknownVersionStd) {429// Forces the version and profile to 4242core, which is an unknown version.430options_.SetForcedVersionProfile(4242 /*unknown version*/,431shaderc_profile_core);432auto const errs =433CompilationErrors(kMinimalShader, shaderc_glsl_vertex_shader, options_);434EXPECT_THAT(errs,435HasSubstr("warning: (version, profile) forced to be (4242, core),"436" while in source code it is (140, none)\n"));437EXPECT_THAT(errs, HasSubstr("error: version not supported\n"));438}439440TEST_F(CppInterface, ForcedVersionProfileVersionsBefore150) {441// Versions before 150 do not allow a profile token, shaderc_profile_none442// should be passed down as the profile parameter.443options_.SetForcedVersionProfile(140, shaderc_profile_none);444EXPECT_TRUE(445CompilationSuccess(kMinimalShader, shaderc_glsl_vertex_shader, options_));446}447448TEST_F(CppInterface, ForcedVersionProfileRedundantProfileStd) {449// Forces the version and profile to 100core. But versions before 150 do not450// allow a profile token, compilation should fail.451options_.SetForcedVersionProfile(100, shaderc_profile_core);452EXPECT_THAT(453CompilationErrors(kMinimalShader, shaderc_glsl_vertex_shader, options_),454HasSubstr("error: #version: versions before 150 do not allow a profile "455"token\n"));456}457458TEST_F(CppInterface, GenerateDebugInfoBinary) {459options_.SetGenerateDebugInfo();460const std::string binary_output =461CompilationOutput(kMinimalDebugInfoShader,462shaderc_glsl_vertex_shader, options_);463// The binary output should contain the name of the vector (debug_info_sample)464// null-terminated, as well as the whole original source.465std::string vector_name("debug_info_sample");466vector_name.resize(vector_name.size() + 1);467EXPECT_THAT(binary_output, HasSubstr(vector_name));468EXPECT_THAT(binary_output, HasSubstr(kMinimalDebugInfoShader));469}470471TEST_F(CppInterface, GenerateDebugInfoBinaryClonedOptions) {472options_.SetGenerateDebugInfo();473CompileOptions cloned_options(options_);474const std::string binary_output =475CompilationOutput(kMinimalDebugInfoShader,476shaderc_glsl_vertex_shader, cloned_options);477// The binary output should contain the name of the vector (debug_info_sample)478// null-terminated, as well as the whole original source.479std::string vector_name("debug_info_sample");480vector_name.resize(vector_name.size() + 1);481EXPECT_THAT(binary_output, HasSubstr(vector_name));482EXPECT_THAT(binary_output, HasSubstr(kMinimalDebugInfoShader));483}484485TEST_F(CppInterface, GenerateDebugInfoDisassembly) {486options_.SetGenerateDebugInfo();487// Debug info should also be emitted in disassembly mode.488// The output disassembly should contain the name of the vector:489// debug_info_sample.490EXPECT_THAT(AssemblyOutput(kMinimalDebugInfoShader,491shaderc_glsl_vertex_shader, options_),492HasSubstr("debug_info_sample"));493}494495TEST_F(CppInterface, GenerateDebugInfoDisassemblyClonedOptions) {496options_.SetGenerateDebugInfo();497// Generate debug info mode should be carried to the cloned options.498CompileOptions cloned_options(options_);499EXPECT_THAT(CompilationOutput(kMinimalDebugInfoShader,500shaderc_glsl_vertex_shader, cloned_options),501HasSubstr("debug_info_sample"));502}503504TEST_F(CppInterface, CompileAndOptimizeWithLevelZero) {505options_.SetOptimizationLevel(shaderc_optimization_level_zero);506const std::string disassembly_text =507AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_);508for (const auto& substring : kMinimalShaderDisassemblySubstrings) {509EXPECT_THAT(disassembly_text, HasSubstr(substring));510}511// Check that we still have debug instructions.512EXPECT_THAT(disassembly_text, HasSubstr("OpName"));513EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));514}515516TEST_F(CppInterface, CompileAndOptimizeWithLevelPerformance) {517options_.SetOptimizationLevel(shaderc_optimization_level_performance);518const std::string disassembly_text = AssemblyOutput(519kGlslMultipleFnShader, shaderc_glsl_fragment_shader, options_);520// Check that we do not have function calls anymore.521EXPECT_THAT(disassembly_text, Not(HasSubstr("OpFunctionCall")));522}523524TEST_F(CppInterface, CompileAndOptimizeWithLevelSize) {525options_.SetOptimizationLevel(shaderc_optimization_level_size);526const std::string disassembly_text =527AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_);528for (const auto& substring : kMinimalShaderDisassemblySubstrings) {529EXPECT_THAT(disassembly_text, HasSubstr(substring));530}531// Check that we do not have debug instructions.532EXPECT_THAT(disassembly_text, Not(HasSubstr("OpName")));533EXPECT_THAT(disassembly_text, Not(HasSubstr("OpSource")));534}535536TEST_F(CppInterface, CompileAndOptimizeForVulkan10Failure) {537options_.SetSourceLanguage(shaderc_source_language_hlsl);538options_.SetTargetEnvironment(shaderc_target_env_vulkan,539shaderc_env_version_vulkan_1_0);540options_.SetOptimizationLevel(shaderc_optimization_level_performance);541542EXPECT_THAT(CompilationErrors(kHlslWaveActiveSumeComputeShader,543shaderc_compute_shader, options_),544// TODO(antiagainst): the error message can be improved to be more545// explicit regarding Vulkan 1.1546HasSubstr("compilation succeeded but failed to optimize: "547"Capability GroupNonUniform is not allowed by Vulkan "548"1.0 specification (or requires extension)"));549}550551TEST_F(CppInterface, CompileAndOptimizeForVulkan11Success) {552options_.SetSourceLanguage(shaderc_source_language_hlsl);553options_.SetTargetEnvironment(shaderc_target_env_vulkan,554shaderc_env_version_vulkan_1_1);555options_.SetOptimizationLevel(shaderc_optimization_level_performance);556557const std::string disassembly_text = AssemblyOutput(558kHlslWaveActiveSumeComputeShader, shaderc_compute_shader, options_);559EXPECT_THAT(disassembly_text, HasSubstr("OpGroupNonUniformIAdd"));560}561562TEST_F(CppInterface, FollowingOptLevelOverridesPreviousOne) {563options_.SetOptimizationLevel(shaderc_optimization_level_size);564// Optimization level settings overridden by565options_.SetOptimizationLevel(shaderc_optimization_level_zero);566const std::string disassembly_text =567AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_);568for (const auto& substring : kMinimalShaderDisassemblySubstrings) {569EXPECT_THAT(disassembly_text, HasSubstr(substring));570}571// Check that we still have debug instructions.572EXPECT_THAT(disassembly_text, HasSubstr("OpName"));573EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));574}575576TEST_F(CppInterface, GenerateDebugInfoOverridesOptimizationLevel) {577options_.SetOptimizationLevel(shaderc_optimization_level_size);578// Optimization level settings overridden by579options_.SetGenerateDebugInfo();580const std::string disassembly_text =581AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_);582for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) {583EXPECT_THAT(disassembly_text, HasSubstr(substring));584}585// Check that we still have debug instructions.586EXPECT_THAT(disassembly_text, HasSubstr("OpName"));587EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));588}589590TEST_F(CppInterface, GenerateDebugInfoProhibitsOptimizationLevel) {591// Setting generate debug info first also works.592options_.SetGenerateDebugInfo();593options_.SetOptimizationLevel(shaderc_optimization_level_size);594const std::string disassembly_text =595AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_);596for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) {597EXPECT_THAT(disassembly_text, HasSubstr(substring));598}599// Check that we still have debug instructions.600EXPECT_THAT(disassembly_text, HasSubstr("OpName"));601EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));602}603604TEST_F(CppInterface, GetNumErrors) {605std::string shader(kTwoErrorsShader);606const SpvCompilationResult compilation_result =607compiler_.CompileGlslToSpv(kTwoErrorsShader, strlen(kTwoErrorsShader),608shaderc_glsl_vertex_shader, "shader");609EXPECT_FALSE(CompilationResultIsSuccess(compilation_result));610EXPECT_EQ(2u, compilation_result.GetNumErrors());611EXPECT_EQ(0u, compilation_result.GetNumWarnings());612}613614TEST_F(CppInterface, GetNumWarnings) {615const SpvCompilationResult compilation_result =616compiler_.CompileGlslToSpv(kTwoWarningsShader, strlen(kTwoWarningsShader),617shaderc_glsl_vertex_shader, "shader");618EXPECT_TRUE(CompilationResultIsSuccess(compilation_result));619EXPECT_EQ(2u, compilation_result.GetNumWarnings());620EXPECT_EQ(0u, compilation_result.GetNumErrors());621}622623TEST_F(CppInterface, ZeroErrorsZeroWarnings) {624const SpvCompilationResult compilation_result =625compiler_.CompileGlslToSpv(kMinimalShader, strlen(kMinimalShader),626shaderc_glsl_vertex_shader, "shader");627EXPECT_TRUE(CompilationResultIsSuccess(compilation_result));628EXPECT_EQ(0u, compilation_result.GetNumErrors());629EXPECT_EQ(0u, compilation_result.GetNumWarnings());630}631632TEST_F(CppInterface, ErrorTypeUnknownShaderStage) {633// The shader kind/stage can not be determined, the error type field should634// indicate the error type is shaderc_shader_kind_error.635const SpvCompilationResult compilation_result =636compiler_.CompileGlslToSpv(kMinimalShader, strlen(kMinimalShader),637shaderc_glsl_infer_from_source, "shader");638EXPECT_EQ(shaderc_compilation_status_invalid_stage,639compilation_result.GetCompilationStatus());640}641642TEST_F(CppInterface, ErrorTypeCompilationError) {643// The shader kind is valid, the result object's error type field should644// indicate this compilaion fails due to compilation errors.645const SpvCompilationResult compilation_result = compiler_.CompileGlslToSpv(646kTwoErrorsShader, shaderc_glsl_vertex_shader, "shader");647EXPECT_EQ(shaderc_compilation_status_compilation_error,648compilation_result.GetCompilationStatus());649}650651TEST_F(CppInterface, ErrorTagIsInputFileName) {652std::string shader(kTwoErrorsShader);653const SpvCompilationResult compilation_result =654compiler_.CompileGlslToSpv(kTwoErrorsShader, strlen(kTwoErrorsShader),655shaderc_glsl_vertex_shader, "SampleInputFile");656// Expects compilation failure errors. The error tag should be657// 'SampleInputFile'658EXPECT_FALSE(CompilationResultIsSuccess(compilation_result));659EXPECT_THAT(compilation_result.GetErrorMessage(),660HasSubstr("SampleInputFile:3: error:"));661}662663TEST_F(CppInterface, PreprocessingOnlyOption) {664const PreprocessedSourceCompilationResult result = compiler_.PreprocessGlsl(665kMinimalShaderWithMacro, shaderc_glsl_vertex_shader, "shader", options_);666EXPECT_TRUE(CompilationResultIsSuccess(result));667EXPECT_THAT(CompilerOutputAsString(result), HasSubstr("void main() { }"));668669const std::string kMinimalShaderCloneOption =670"#version 140\n"671"#define E_CLONE_OPTION main\n"672"void E_CLONE_OPTION(){}\n";673CompileOptions cloned_options(options_);674const PreprocessedSourceCompilationResult result_from_cloned_options =675compiler_.PreprocessGlsl(kMinimalShaderCloneOption,676shaderc_glsl_vertex_shader, "shader",677cloned_options);678EXPECT_TRUE(CompilationResultIsSuccess(result_from_cloned_options));679EXPECT_THAT(CompilerOutputAsString(result_from_cloned_options),680HasSubstr("void main() { }"));681}682683// A shader kind test case needs: 1) A shader text with or without #pragma684// annotation, 2) shader_kind.685struct ShaderKindTestCase {686const char* shader_;687shaderc_shader_kind shader_kind_;688};689690// Test the shader kind deduction process. If the shader kind is one691// of the non-default ones, the compiler will just try to compile the692// source code in that specified shader kind. If the shader kind is693// shaderc_glsl_deduce_from_pragma, the compiler will determine the shader694// kind from #pragma annotation in the source code and emit error if none695// such annotation is found. When the shader kind is one of the default696// ones, the compiler will fall back to use the specified shader kind if697// and only if #pragma annoation is not found.698699// Valid shader kind settings should generate valid SPIR-V code.700using ValidShaderKind = testing::TestWithParam<ShaderKindTestCase>;701702TEST_P(ValidShaderKind, ValidSpvCode) {703const ShaderKindTestCase& test_case = GetParam();704shaderc::Compiler compiler;705EXPECT_TRUE(706CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_));707}708709INSTANTIATE_TEST_SUITE_P(710CompileStringTest, ValidShaderKind,711testing::ValuesIn(std::vector<ShaderKindTestCase>{712// Valid default shader kinds.713{kEmpty310ESShader, shaderc_glsl_default_vertex_shader},714{kEmpty310ESShader, shaderc_glsl_default_fragment_shader},715{kEmpty310ESShader, shaderc_glsl_default_compute_shader},716{kGeometryOnlyShader, shaderc_glsl_default_geometry_shader},717{kTessControlOnlyShader, shaderc_glsl_default_tess_control_shader},718{kTessEvaluationOnlyShader,719shaderc_glsl_default_tess_evaluation_shader},720721// #pragma annotation overrides default shader kinds.722{kVertexOnlyShaderWithPragma, shaderc_glsl_default_compute_shader},723{kFragmentOnlyShaderWithPragma, shaderc_glsl_default_vertex_shader},724{kTessControlOnlyShaderWithPragma,725shaderc_glsl_default_fragment_shader},726{kTessEvaluationOnlyShaderWithPragma,727shaderc_glsl_default_tess_control_shader},728{kGeometryOnlyShaderWithPragma,729shaderc_glsl_default_tess_evaluation_shader},730{kComputeOnlyShaderWithPragma, shaderc_glsl_default_geometry_shader},731732// Specified non-default shader kind overrides #pragma annotation.733{kVertexOnlyShaderWithInvalidPragma, shaderc_glsl_vertex_shader},734}));735736// Invalid shader kind settings should generate errors.737using InvalidShaderKind = testing::TestWithParam<ShaderKindTestCase>;738739TEST_P(InvalidShaderKind, CompilationShouldFail) {740const ShaderKindTestCase& test_case = GetParam();741shaderc::Compiler compiler;742EXPECT_FALSE(743CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_));744}745746INSTANTIATE_TEST_SUITE_P(747CompileStringTest, InvalidShaderKind,748testing::ValuesIn(std::vector<ShaderKindTestCase>{749// Invalid default shader kind.750{kVertexOnlyShader, shaderc_glsl_default_fragment_shader},751// Sets to deduce shader kind from #pragma, but #pragma is defined in752// the source code.753{kVertexOnlyShader, shaderc_glsl_infer_from_source},754// Invalid #pragma cause errors, even though default shader kind is set755// to valid shader kind.756{kVertexOnlyShaderWithInvalidPragma,757shaderc_glsl_default_vertex_shader},758}));759760// To test file inclusion, use an unordered_map as a fake file system to store761// fake files to be included. The unordered_map represents a filesystem by762// mapping filename (or path) string to the contents of that file as a string.763using FakeFS = std::unordered_map<std::string, std::string>;764765// An includer test case needs: 1) A fake file system which is actually an766// unordered_map, so that we can resolve the content given a string. A valid767// fake file system must have one entry with key:'root' to specify the start768// shader file for compilation. 2) An string that we expect to see in the769// compilation output.770class IncluderTestCase {771public:772IncluderTestCase(FakeFS fake_fs, std::string expected_substring)773: fake_fs_(fake_fs), expected_substring_(expected_substring) {774assert(fake_fs_.find("root") != fake_fs_.end() &&775"Valid fake file system needs a 'root' file\n");776}777778const FakeFS& fake_fs() const { return fake_fs_; }779const std::string& expected_substring() const { return expected_substring_; }780781private:782FakeFS fake_fs_;783std::string expected_substring_;784};785786// A mock class that simulates an includer. This class implements787// IncluderInterface to provide GetInclude() and ReleaseInclude() methods.788class TestIncluder : public shaderc::CompileOptions::IncluderInterface {789public:790explicit TestIncluder(const FakeFS& fake_fs)791: fake_fs_(fake_fs), responses_({}) {}792793// Get path and content from the fake file system.794shaderc_include_result* GetInclude(const char* requested_source,795shaderc_include_type type,796const char* requesting_source,797size_t include_depth) override {798responses_.emplace_back(shaderc_include_result{799requested_source, strlen(requested_source),800fake_fs_.at(std::string(requested_source)).c_str(),801fake_fs_.at(std::string(requested_source)).size()});802return &responses_.back();803}804805// Response data is owned as private property, no need to release explicitly.806void ReleaseInclude(shaderc_include_result*) override {}807808private:809const FakeFS& fake_fs_;810std::vector<shaderc_include_result> responses_;811};812813using IncluderTests = testing::TestWithParam<IncluderTestCase>;814815// Parameterized tests for includer.816TEST_P(IncluderTests, SetIncluder) {817const IncluderTestCase& test_case = GetParam();818const FakeFS& fs = test_case.fake_fs();819const std::string& shader = fs.at("root");820shaderc::Compiler compiler;821CompileOptions options;822options.SetIncluder(std::unique_ptr<TestIncluder>(new TestIncluder(fs)));823const auto compilation_result = compiler.PreprocessGlsl(824shader.c_str(), shaderc_glsl_vertex_shader, "shader", options);825// Checks the existence of the expected string.826EXPECT_THAT(CompilerOutputAsString(compilation_result),827HasSubstr(test_case.expected_substring()));828}829830TEST_P(IncluderTests, SetIncluderClonedOptions) {831const IncluderTestCase& test_case = GetParam();832const FakeFS& fs = test_case.fake_fs();833const std::string& shader = fs.at("root");834shaderc::Compiler compiler;835CompileOptions options;836options.SetIncluder(std::unique_ptr<TestIncluder>(new TestIncluder(fs)));837838// Cloned options should have all the settings.839CompileOptions cloned_options(options);840const auto compilation_result = compiler.PreprocessGlsl(841shader.c_str(), shaderc_glsl_vertex_shader, "shader", cloned_options);842// Checks the existence of the expected string.843EXPECT_THAT(CompilerOutputAsString(compilation_result),844HasSubstr(test_case.expected_substring()));845}846847INSTANTIATE_TEST_SUITE_P(CppInterface, IncluderTests,848testing::ValuesIn(std::vector<IncluderTestCase>{849IncluderTestCase(850// Fake file system.851{852{"root",853"#version 150\n"854"void foo() {}\n"855"#include \"path/to/file_1\"\n"},856{"path/to/file_1", "content of file_1\n"},857},858// Expected output.859"#line 0 \"path/to/file_1\"\n"860" content of file_1\n"861"#line 3"),862IncluderTestCase(863// Fake file system.864{{"root",865"#version 150\n"866"void foo() {}\n"867"#include \"path/to/file_1\"\n"},868{"path/to/file_1",869"#include \"path/to/file_2\"\n"870"content of file_1\n"},871{"path/to/file_2", "content of file_2\n"}},872// Expected output.873"#line 0 \"path/to/file_1\"\n"874"#line 0 \"path/to/file_2\"\n"875" content of file_2\n"876"#line 1 \"path/to/file_1\"\n"877" content of file_1\n"878"#line 3"),879880}));881882TEST_F(CppInterface, WarningsOnLine) {883// By default the compiler will emit a warning on line 2 complaining884// that 'float' is a deprecated attribute in version 130.885EXPECT_THAT(886CompilationWarnings(kDeprecatedAttributeShader,887shaderc_glsl_vertex_shader, CompileOptions()),888HasSubstr(":2: warning: attribute deprecated in version 130; may be "889"removed in future release\n"));890}891892TEST_F(CppInterface, SuppressWarningsOnLine) {893// Sets the compiler to suppress warnings, so that the deprecated attribute894// warning won't be emitted.895options_.SetSuppressWarnings();896EXPECT_EQ("", CompilationWarnings(kDeprecatedAttributeShader,897shaderc_glsl_vertex_shader, options_));898}899900TEST_F(CppInterface, SuppressWarningsOnLineClonedOptions) {901// Sets the compiler to suppress warnings, so that the deprecated attribute902// warning won't be emitted, and the mode should be carried into any clone of903// the original option object.904options_.SetSuppressWarnings();905CompileOptions cloned_options(options_);906EXPECT_EQ("",907CompilationWarnings(kDeprecatedAttributeShader,908shaderc_glsl_vertex_shader, cloned_options));909}910911TEST_F(CppInterface, WarningsOnLineAsErrors) {912// Sets the compiler to make warnings into errors. So that the deprecated913// attribute warning will be emitted as an error and compilation should fail.914options_.SetWarningsAsErrors();915EXPECT_THAT(916CompilationErrors(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader,917options_),918HasSubstr(":2: error: attribute deprecated in version 130; may be "919"removed in future release\n"));920}921922TEST_F(CppInterface, WarningsOnLineAsErrorsClonedOptions) {923// Sets the compiler to make warnings into errors. So that the deprecated924// attribute warning will be emitted as an error and compilation should fail.925options_.SetWarningsAsErrors();926CompileOptions cloned_options(options_);927// The error message should show an error instead of a warning.928EXPECT_THAT(929CompilationErrors(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader,930cloned_options),931HasSubstr(":2: error: attribute deprecated in version 130; may be "932"removed in future release\n"));933}934935TEST_F(CppInterface, GlobalWarnings) {936// By default the compiler will emit a warning as version 550 is an unknown937// version.938options_.SetForcedVersionProfile(400, shaderc_profile_core);939EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader,940shaderc_glsl_vertex_shader, options_),941HasSubstr("(version, profile) forced to be (400, core),"942" while in source code it is (550, none)\n"));943}944945TEST_F(CppInterface, SuppressGlobalWarnings) {946// Sets the compiler to suppress warnings, so that the unknown version warning947// won't be emitted.948options_.SetSuppressWarnings();949options_.SetForcedVersionProfile(400, shaderc_profile_core);950EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader,951shaderc_glsl_vertex_shader, options_),952Eq(""));953}954955TEST_F(CppInterface, SuppressGlobalWarningsClonedOptions) {956// Sets the compiler to suppress warnings, so that the unknown version warning957// won't be emitted, and the mode should be carried into any clone of the958// original option object.959options_.SetSuppressWarnings();960options_.SetForcedVersionProfile(400, shaderc_profile_core);961CompileOptions cloned_options(options_);962EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader,963shaderc_glsl_vertex_shader, cloned_options),964Eq(""));965}966967TEST_F(CppInterface, GlobalWarningsAsErrors) {968// Sets the compiler to make warnings into errors. So that the unknown969// version warning will be emitted as an error and compilation should fail.970options_.SetWarningsAsErrors();971options_.SetForcedVersionProfile(400, shaderc_profile_core);972EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader,973shaderc_glsl_vertex_shader, options_),974HasSubstr("(version, profile) forced to be (400, core),"975" while in source code it is (550, none)\n"));976}977978TEST_F(CppInterface, GlobalWarningsAsErrorsClonedOptions) {979// Sets the compiler to make warnings into errors. This mode should be carried980// into any clone of the original option object.981options_.SetWarningsAsErrors();982options_.SetForcedVersionProfile(400, shaderc_profile_core);983CompileOptions cloned_options(options_);984EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader,985shaderc_glsl_vertex_shader, cloned_options),986HasSubstr("(version, profile) forced to be (400, core),"987" while in source code it is (550, none)\n"));988}989990TEST_F(CppInterface, SuppressWarningsModeFirstOverridesWarningsAsErrorsMode) {991// Sets suppress-warnings mode first, then sets warnings-as-errors mode.992// suppress-warnings mode should override warnings-as-errors mode, no993// error message should be output for this case.994options_.SetSuppressWarnings();995options_.SetWarningsAsErrors();996// Warnings on line should be inhibited.997EXPECT_EQ("", CompilationWarnings(kDeprecatedAttributeShader,998shaderc_glsl_vertex_shader, options_));9991000// Global warnings should be inhibited.1001// However, the unknown version will cause an error.1002EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader,1003shaderc_glsl_vertex_shader, options_),1004Eq("shader: error: version not supported\n"));1005}10061007TEST_F(CppInterface, SuppressWarningsModeSecondOverridesWarningsAsErrorsMode) {1008// Sets warnings-as-errors mode first, then sets suppress-warnings mode.1009// suppress-warnings mode should override warnings-as-errors mode, no1010// error message should be output for this case.1011options_.SetWarningsAsErrors();1012options_.SetSuppressWarnings();1013// Warnings on line should be inhibited.1014EXPECT_EQ("", CompilationWarnings(kDeprecatedAttributeShader,1015shaderc_glsl_vertex_shader, options_));10161017// Global warnings should be inhibited.1018// However, the unknown version will cause an error.1019EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader,1020shaderc_glsl_vertex_shader, options_),1021Eq("shader: error: version not supported\n"));1022}10231024TEST_F(CppInterface, TargetEnvCompileOptionsOpenGLCompatibilityShadersFail) {1025// Glslang does not support SPIR-V code generation for OpenGL compatibility1026// profile.1027options_.SetTargetEnvironment(shaderc_target_env_opengl_compat, 0);1028const std::string kGlslShader =1029R"(#version 150 compatibility1030uniform highp sampler2D tex;1031void main() {1032gl_FragColor = texture2D(tex, vec2(0.0,0.0));1033}1034)";10351036const auto errors =1037CompilationErrors(kGlslShader, shaderc_glsl_fragment_shader, options_);1038EXPECT_EQ(errors, "error: OpenGL compatibility profile is not supported");1039}10401041std::string BarrierComputeShader() {1042return R"(#version 4501043void main() { barrier(); })";1044}10451046std::string SubgroupBarrierComputeShader() {1047return R"(#version 4501048#extension GL_KHR_shader_subgroup_basic : enable1049void main() { subgroupBarrier(); })";1050}10511052TEST_F(CppInterface, TargetEnvCompileOptionsVulkanEnvVulkan1_0ShaderSucceeds) {1053options_.SetTargetEnvironment(shaderc_target_env_vulkan, 0);1054EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(),1055shaderc_glsl_compute_shader, options_));1056}10571058TEST_F(CppInterface, TargetEnvCompileOptionsVulkanEnvVulkan1_0ShaderFails) {1059options_.SetTargetEnvironment(shaderc_target_env_vulkan, 0);1060EXPECT_FALSE(CompilationSuccess(SubgroupBarrierComputeShader(),1061shaderc_glsl_compute_shader, options_));1062}10631064TEST_F(CppInterface,1065TargetEnvCompileOptionsVulkan1_0EnvVulkan1_0ShaderSucceeds) {1066options_.SetTargetEnvironment(shaderc_target_env_vulkan,1067shaderc_env_version_vulkan_1_0);1068EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(),1069shaderc_glsl_compute_shader, options_));1070}10711072TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_0EnvVulkan1_1ShaderFails) {1073options_.SetTargetEnvironment(shaderc_target_env_vulkan,1074shaderc_env_version_vulkan_1_0);1075EXPECT_FALSE(CompilationSuccess(SubgroupBarrierComputeShader(),1076shaderc_glsl_compute_shader, options_));1077}10781079TEST_F(CppInterface,1080TargetEnvCompileOptionsVulkan1_1EnvVulkan1_0ShaderSucceeds) {1081options_.SetTargetEnvironment(shaderc_target_env_vulkan,1082shaderc_env_version_vulkan_1_1);1083EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(),1084shaderc_glsl_compute_shader, options_));1085}10861087TEST_F(CppInterface,1088TargetEnvCompileOptionsVulkan1_1EnvVulkan1_1ShaderSucceeds) {1089options_.SetTargetEnvironment(shaderc_target_env_vulkan,1090shaderc_env_version_vulkan_1_1);1091EXPECT_TRUE(CompilationSuccess(SubgroupBarrierComputeShader(),1092shaderc_glsl_compute_shader, options_));1093}10941095TEST_F(CppInterface, BeginAndEndOnSpvCompilationResult) {1096const SpvCompilationResult compilation_result = compiler_.CompileGlslToSpv(1097kMinimalShader, shaderc_glsl_vertex_shader, "shader");1098EXPECT_TRUE(IsValidSpv(compilation_result));1099// Use range-based for to exercise begin() and end().1100std::vector<uint32_t> binary_words;1101for (const auto& element : compilation_result) {1102binary_words.push_back(element);1103}1104EXPECT_THAT(binary_words,1105Eq(std::vector<uint32_t>(compilation_result.cbegin(),1106compilation_result.cend())));1107}11081109TEST_F(CppInterface, BeginAndEndOnAssemblyCompilationResult) {1110const AssemblyCompilationResult compilation_result =1111compiler_.CompileGlslToSpvAssembly(1112kMinimalShader, shaderc_glsl_vertex_shader, "shader", options_);1113const std::string forced_to_be_a_string =1114CompilerOutputAsString(compilation_result);1115EXPECT_THAT(forced_to_be_a_string, HasSubstr("MemoryModel"));1116const std::string string_via_begin_end(compilation_result.begin(),1117compilation_result.end());1118EXPECT_THAT(string_via_begin_end, Eq(forced_to_be_a_string));1119}11201121TEST_F(CppInterface, BeginAndEndOnPreprocessedResult) {1122const PreprocessedSourceCompilationResult compilation_result =1123compiler_.PreprocessGlsl(kMinimalShader, shaderc_glsl_vertex_shader,1124"shader", options_);1125const std::string forced_to_be_a_string =1126CompilerOutputAsString(compilation_result);1127EXPECT_THAT(forced_to_be_a_string, HasSubstr("void main()"));1128const std::string string_via_begin_end(compilation_result.begin(),1129compilation_result.end());1130EXPECT_THAT(string_via_begin_end, Eq(forced_to_be_a_string));1131}11321133TEST_F(CppInterface, SourceLangGlslMinimalGlslVertexShaderSucceeds) {1134options_.SetSourceLanguage(shaderc_source_language_glsl);1135EXPECT_TRUE(CompilationSuccess(kVertexOnlyShader, shaderc_glsl_vertex_shader,1136options_));1137}11381139TEST_F(CppInterface, SourceLangGlslMinimalHlslVertexShaderFails) {1140options_.SetSourceLanguage(shaderc_source_language_glsl);1141EXPECT_FALSE(CompilationSuccess(kMinimalHlslShader,1142shaderc_glsl_vertex_shader, options_));1143}11441145TEST_F(CppInterface, SourceLangHlslMinimalGlslVertexShaderFails) {1146options_.SetSourceLanguage(shaderc_source_language_hlsl);1147EXPECT_FALSE(CompilationSuccess(kVertexOnlyShader, shaderc_glsl_vertex_shader,1148options_));1149}11501151TEST_F(CppInterface, SourceLangHlslMinimalHlslVertexShaderSucceeds) {1152options_.SetSourceLanguage(shaderc_source_language_hlsl);1153EXPECT_TRUE(CompilationSuccess(kMinimalHlslShader, shaderc_glsl_vertex_shader,1154options_));1155}11561157TEST(1158EntryPointTest,1159SourceLangHlslMinimalHlslVertexShaderAsConstCharPtrSucceedsWithEntryPointName) {1160shaderc::Compiler compiler;1161CompileOptions options;1162options.SetSourceLanguage(shaderc_source_language_hlsl);1163auto result = compiler.CompileGlslToSpv(1164kMinimalHlslShader, strlen(kMinimalHlslShader),1165shaderc_glsl_vertex_shader, "shader", "EntryPoint", options);1166std::vector<uint32_t> binary(result.begin(), result.end());1167std::string assembly;1168spvtools::SpirvTools(SPV_ENV_UNIVERSAL_1_0).Disassemble(binary, &assembly);1169EXPECT_THAT(assembly,1170HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""))1171<< assembly;1172}11731174TEST(1175EntryPointTest,1176SourceLangHlslMinimalHlslVertexShaderAsStdStringSucceedsWithEntryPointName) {1177shaderc::Compiler compiler;1178CompileOptions options;1179options.SetSourceLanguage(shaderc_source_language_hlsl);1180std::string shader(kMinimalHlslShader);1181auto result = compiler.CompileGlslToSpv(shader, shaderc_glsl_vertex_shader,1182"shader", "EntryPoint", options);1183std::vector<uint32_t> binary(result.begin(), result.end());1184std::string assembly;1185spvtools::SpirvTools(SPV_ENV_UNIVERSAL_1_0).Disassemble(binary, &assembly);1186EXPECT_THAT(assembly,1187HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""))1188<< assembly;1189}11901191TEST(1192EntryPointTest,1193SourceLangHlslMinimalHlslVertexShaderAsConstCharPtrSucceedsToAssemblyWithEntryPointName) {1194shaderc::Compiler compiler;1195CompileOptions options;1196options.SetSourceLanguage(shaderc_source_language_hlsl);1197auto assembly = compiler.CompileGlslToSpvAssembly(1198kMinimalHlslShader, strlen(kMinimalHlslShader),1199shaderc_glsl_vertex_shader, "shader", "EntryPoint", options);1200EXPECT_THAT(std::string(assembly.begin(), assembly.end()),1201HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""));1202}12031204TEST(1205EntryPointTest,1206SourceLangHlslMinimalHlslVertexShaderAsStdStringSucceedsToAssemblyWithEntryPointName) {1207shaderc::Compiler compiler;1208CompileOptions options;1209options.SetSourceLanguage(shaderc_source_language_hlsl);1210std::string shader(kMinimalHlslShader);1211auto assembly = compiler.CompileGlslToSpvAssembly(1212shader, shaderc_glsl_vertex_shader, "shader", "EntryPoint", options);1213EXPECT_THAT(std::string(assembly.begin(), assembly.end()),1214HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""));1215}12161217// Returns a fragment shader accessing a texture with the given1218// offset.1219std::string ShaderWithTexOffset(int offset) {1220std::ostringstream oss;1221oss << "#version 450\n"1222"layout (binding=0) uniform sampler1D tex;\n"1223"void main() { vec4 x = textureOffset(tex, 1.0, "1224<< offset << "); }\n";1225return oss.str();1226}12271228// Ensure compilation is sensitive to limit setting. Sample just1229// two particular limits.1230TEST_F(CppInterface, LimitsTexelOffsetDefault) {1231EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(),1232shaderc_glsl_fragment_shader, options_));1233EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(),1234shaderc_glsl_fragment_shader, options_));1235EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(),1236shaderc_glsl_fragment_shader, options_));1237EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(),1238shaderc_glsl_fragment_shader, options_));1239}12401241TEST_F(CppInterface, LimitsTexelOffsetLowerMinimum) {1242options_.SetLimit(shaderc_limit_min_program_texel_offset, -99);1243EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(),1244shaderc_glsl_fragment_shader, options_));1245EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(),1246shaderc_glsl_fragment_shader, options_));1247}12481249TEST_F(CppInterface, LimitsTexelOffsetHigherMaximum) {1250options_.SetLimit(shaderc_limit_max_program_texel_offset, 10);1251EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(),1252shaderc_glsl_fragment_shader, options_));1253EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(),1254shaderc_glsl_fragment_shader, options_));1255}12561257TEST_F(CppInterface, UniformsWithoutBindingsFailCompilation) {1258CompileOptions options;1259const std::string errors = CompilationErrors(1260kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options);1261EXPECT_THAT(errors,1262HasSubstr("sampler/texture/image requires layout(binding=X)"));1263}12641265TEST_F(CppInterface,1266UniformsWithoutBindingsOptionSetAutoBindingsAssignsBindings) {1267CompileOptions options;1268options.SetAutoBindUniforms(true);1269const std::string disassembly_text = AssemblyOutput(1270kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options);1271EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));1272EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));1273EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2"));1274EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3"));1275EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4"));1276}12771278TEST_F(CppInterface, SetBindingBaseForTextureAdjustsTextureBindingsOnly) {1279CompileOptions options;1280options.SetAutoBindUniforms(true);1281options.SetBindingBase(shaderc_uniform_kind_texture, 44);1282const std::string disassembly_text = AssemblyOutput(1283kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options);1284EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 44"));1285EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 0"));1286EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1"));1287EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2"));1288EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3"));1289}12901291TEST_F(CppInterface, SetBindingBaseForSamplerAdjustsSamplerBindingsOnly) {1292CompileOptions options;1293options.SetAutoBindUniforms(true);1294options.SetBindingBase(shaderc_uniform_kind_sampler, 44);1295const std::string disassembly_text = AssemblyOutput(1296kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options);1297EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));1298EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 44"));1299EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1"));1300EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2"));1301EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3"));1302}13031304TEST_F(CppInterface, SetBindingBaseForImageAdjustsImageBindingsOnly) {1305CompileOptions options;1306options.SetAutoBindUniforms(true);1307options.SetBindingBase(shaderc_uniform_kind_image, 44);1308const std::string disassembly_text = AssemblyOutput(1309kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options);1310EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));1311EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));1312EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 44"));1313EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 45"));1314EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 2"));1315}13161317TEST_F(CppInterface, SetBindingBaseForBufferAdjustsBufferBindingsOnly) {1318CompileOptions options;1319options.SetAutoBindUniforms(true);1320options.SetBindingBase(shaderc_uniform_kind_buffer, 44);1321const std::string disassembly_text = AssemblyOutput(1322kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options);1323EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));1324EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));1325EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2"));1326EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3"));1327EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 44"));1328}13291330TEST_F(CppInterface, SetBindingBaseSurvivesCloning) {1331CompileOptions options;1332options.SetAutoBindUniforms(true);1333options.SetBindingBase(shaderc_uniform_kind_texture, 40);1334options.SetBindingBase(shaderc_uniform_kind_sampler, 50);1335options.SetBindingBase(shaderc_uniform_kind_image, 60);1336options.SetBindingBase(shaderc_uniform_kind_buffer, 70);1337CompileOptions cloned_options(options);1338const std::string disassembly_text =1339AssemblyOutput(kShaderWithUniformsWithoutBindings,1340shaderc_glsl_vertex_shader, cloned_options);1341EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 40"));1342EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 50"));1343EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 60"));1344EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 61"));1345EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 70"));1346}13471348TEST_F(CppInterface, GlslDefaultPackingUsed) {1349CompileOptions options;1350const std::string disassembly_text = AssemblyOutput(1351kGlslShaderWeirdPacking, shaderc_glsl_vertex_shader, options);1352EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16"));1353}13541355TEST_F(CppInterface, HlslOffsetsOptionDisableRespected) {1356CompileOptions options;1357options.SetHlslOffsets(false);1358const std::string disassembly_text = AssemblyOutput(1359kGlslShaderWeirdPacking, shaderc_glsl_vertex_shader, options);1360EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16"));1361}13621363TEST_F(CppInterface, HlslOffsetsOptionEnableRespected) {1364CompileOptions options;1365options.SetHlslOffsets(true);1366const std::string disassembly_text = AssemblyOutput(1367kGlslShaderWeirdPacking, shaderc_glsl_vertex_shader, options);1368EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 4"));1369}13701371TEST_F(CppInterface, HlslRegSetBindingForFragmentRespected) {1372CompileOptions options;1373options.SetSourceLanguage(shaderc_source_language_hlsl);1374options.SetHlslRegisterSetAndBindingForStage(shaderc_fragment_shader, "t4",1375"9", "16");1376const std::string disassembly_text = AssemblyOutput(1377kHlslFragShaderWithRegisters, shaderc_glsl_fragment_shader, options);1378EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 DescriptorSet 9"));1379EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 Binding 16"));1380}13811382TEST_F(CppInterface, HlslRegSetBindingForDifferentStageIgnored) {1383CompileOptions options;1384options.SetSourceLanguage(shaderc_source_language_hlsl);1385options.SetHlslRegisterSetAndBindingForStage(shaderc_vertex_shader, "t4", "9",1386"16");1387const std::string disassembly_text = AssemblyOutput(1388kHlslFragShaderWithRegisters, shaderc_glsl_fragment_shader, options);1389EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 DescriptorSet 0"));1390EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 Binding 4"));1391}13921393TEST_F(CppInterface, HlslRegSetBindingForAllStagesRespected) {1394CompileOptions options;1395options.SetSourceLanguage(shaderc_source_language_hlsl);1396options.SetHlslRegisterSetAndBinding("t4", "9", "16");1397const std::string disassembly_text = AssemblyOutput(1398kHlslFragShaderWithRegisters, shaderc_glsl_fragment_shader, options);1399EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 DescriptorSet 9"));1400EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 Binding 16"));1401}14021403TEST_F(CppInterface, HlslFunctionality1OffByDefault) {1404CompileOptions options;1405options.SetSourceLanguage(shaderc_source_language_hlsl);1406// The counter needs a binding, and there is no way to set it in the shader1407// source.1408options.SetAutoBindUniforms(true);1409const std::string disassembly_text = AssemblyOutput(1410kHlslShaderWithCounterBuffer, shaderc_glsl_fragment_shader, options);1411EXPECT_THAT(disassembly_text, Not(HasSubstr("OpDecorateString")));1412}14131414TEST_F(CppInterface, HlslFunctionality1Respected) {1415CompileOptions options;1416options.SetSourceLanguage(shaderc_source_language_hlsl);1417// The counter needs a binding, and there is no way to set it in the shader1418// source. https://github.com/KhronosGroup/glslang/issues/16161419options.SetAutoBindUniforms(true);1420options.SetHlslFunctionality1(true);1421const std::string disassembly_text = AssemblyOutput(1422kHlslShaderWithCounterBuffer, shaderc_glsl_fragment_shader, options);1423EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateString"));1424}14251426TEST_F(CppInterface, HlslFunctionality1SurvivesCloning) {1427CompileOptions options;1428options.SetSourceLanguage(shaderc_source_language_hlsl);1429options.SetHlslFunctionality1(true);1430// The counter needs a binding, and there is no way to set it in the shader1431// source. https://github.com/KhronosGroup/glslang/issues/16161432options.SetAutoBindUniforms(true);1433CompileOptions cloned_options(options);1434const std::string disassembly_text = AssemblyOutput(1435kHlslShaderWithCounterBuffer, shaderc_glsl_fragment_shader, cloned_options);1436EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateString"));1437}14381439TEST_F(CppInterface, NanClampDefaultsOff) {1440CompileOptions options;1441const std::string disassembly_text = AssemblyOutput(1442kGlslShaderWithClamp, shaderc_glsl_fragment_shader, options);1443EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 FClamp"));1444}14451446TEST_F(CppInterface, NanClampMapsClampToNClamp) {1447CompileOptions options;1448options.SetNanClamp(true);1449const std::string disassembly_text = AssemblyOutput(1450kGlslShaderWithClamp, shaderc_glsl_fragment_shader, options);1451EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 NClamp"));1452}14531454TEST_F(CppInterface, NanClampSurvivesCloning) {1455CompileOptions options;1456options.SetNanClamp(true);1457CompileOptions cloned_options(options);1458const std::string disassembly_text = AssemblyOutput(1459kGlslShaderWithClamp, shaderc_glsl_fragment_shader, cloned_options);1460EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 NClamp"));1461}14621463} // anonymous namespace146414651466