Path: blob/main/libshaderc/src/shaderc_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 "shaderc/shaderc.h"1516#include <gmock/gmock.h>17#include <gtest/gtest.h>1819#include <memory>20#include <thread>21#include <unordered_map>2223#include "common_shaders_for_test.h"24#include "spirv/unified1/spirv.hpp"2526namespace {2728using testing::Each;29using testing::HasSubstr;30using testing::Not;3132TEST(Init, MultipleCalls) {33shaderc_compiler_t compiler1, compiler2, compiler3;34EXPECT_NE(nullptr, compiler1 = shaderc_compiler_initialize());35EXPECT_NE(nullptr, compiler2 = shaderc_compiler_initialize());36EXPECT_NE(nullptr, compiler3 = shaderc_compiler_initialize());37shaderc_compiler_release(compiler1);38shaderc_compiler_release(compiler2);39shaderc_compiler_release(compiler3);40}4142#ifndef SHADERC_DISABLE_THREADED_TESTS43TEST(Init, MultipleThreadsCalling) {44shaderc_compiler_t compiler1, compiler2, compiler3;45std::thread t1([&compiler1]() { compiler1 = shaderc_compiler_initialize(); });46std::thread t2([&compiler2]() { compiler2 = shaderc_compiler_initialize(); });47std::thread t3([&compiler3]() { compiler3 = shaderc_compiler_initialize(); });48t1.join();49t2.join();50t3.join();51EXPECT_NE(nullptr, compiler1);52EXPECT_NE(nullptr, compiler2);53EXPECT_NE(nullptr, compiler3);54shaderc_compiler_release(compiler1);55shaderc_compiler_release(compiler2);56shaderc_compiler_release(compiler3);57}58#endif5960TEST(Init, SPVVersion) {61unsigned int version = 0;62unsigned int revision = 0;63shaderc_get_spv_version(&version, &revision);64EXPECT_EQ(spv::Version, version);65EXPECT_EQ(spv::Revision, revision);66}6768// Determines the kind of output required from the compiler.69enum class OutputType {70SpirvBinary,71SpirvAssemblyText,72PreprocessedText,73};7475// Generate a compilation result object with the given compile,76// shader source, shader kind, input file name, entry point name, options,77// and for the specified output type. The entry point name is only significant78// for HLSL compilation.79shaderc_compilation_result_t MakeCompilationResult(80const shaderc_compiler_t compiler, const std::string& shader,81shaderc_shader_kind kind, const char* input_file_name,82const char* entry_point_name, const shaderc_compile_options_t options,83OutputType output_type) {84switch (output_type) {85case OutputType::SpirvBinary:86return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(),87kind, input_file_name, entry_point_name,88options);89break;90case OutputType::SpirvAssemblyText:91return shaderc_compile_into_spv_assembly(92compiler, shader.c_str(), shader.size(), kind, input_file_name,93entry_point_name, options);94break;95case OutputType::PreprocessedText:96return shaderc_compile_into_preprocessed_text(97compiler, shader.c_str(), shader.size(), kind, input_file_name,98entry_point_name, options);99break;100}101// We shouldn't reach here. But some compilers might not know that.102// Be a little defensive and produce something.103return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(), kind,104input_file_name, entry_point_name, options);105}106107// RAII class for shaderc_compilation_result. Used for shader compilation.108class Compilation {109public:110// Compiles shader and keeps the result.111Compilation(const shaderc_compiler_t compiler, const std::string& shader,112shaderc_shader_kind kind, const char* input_file_name,113const char* entry_point_name,114const shaderc_compile_options_t options = nullptr,115OutputType output_type = OutputType::SpirvBinary)116: compiled_result_(117MakeCompilationResult(compiler, shader, kind, input_file_name,118entry_point_name, options, output_type)) {}119120~Compilation() { shaderc_result_release(compiled_result_); }121122shaderc_compilation_result_t result() const { return compiled_result_; }123124private:125shaderc_compilation_result_t compiled_result_;126};127128// RAII class for shaderc_compilation_result. Used for shader assembling.129class Assembling {130public:131// Assembles shader and keeps the result.132Assembling(const shaderc_compiler_t compiler, const std::string& assembly,133const shaderc_compile_options_t options = nullptr)134: compiled_result_(shaderc_assemble_into_spv(compiler, assembly.data(),135assembly.size(), options)) {}136137~Assembling() { shaderc_result_release(compiled_result_); }138139shaderc_compilation_result_t result() const { return compiled_result_; }140141private:142shaderc_compilation_result_t compiled_result_;143};144145struct CleanupOptions {146void operator()(shaderc_compile_options_t options) const {147shaderc_compile_options_release(options);148}149};150151typedef std::unique_ptr<shaderc_compile_options, CleanupOptions>152compile_options_ptr;153154// RAII class for shaderc_compiler_t155class Compiler {156public:157Compiler() { compiler = shaderc_compiler_initialize(); }158~Compiler() { shaderc_compiler_release(compiler); }159shaderc_compiler_t get_compiler_handle() { return compiler; }160161private:162shaderc_compiler_t compiler;163};164165// RAII class for shader_compiler_options_t166class Options {167public:168Options() : options_(shaderc_compile_options_initialize()) {}169~Options() { shaderc_compile_options_release(options_); }170shaderc_compile_options_t get() { return options_; }171172private:173shaderc_compile_options_t options_;174};175176// Helper function to check if the compilation result indicates a successful177// compilation.178bool CompilationResultIsSuccess(const shaderc_compilation_result_t result) {179return shaderc_result_get_compilation_status(result) ==180shaderc_compilation_status_success;181}182183// Returns true if the given result contains a SPIR-V module that contains184// at least the number of bytes of the header and the correct magic number.185bool ResultContainsValidSpv(shaderc_compilation_result_t result) {186if (!CompilationResultIsSuccess(result)) return false;187size_t length = shaderc_result_get_length(result);188if (length < 20) return false;189const uint32_t* bytes = static_cast<const uint32_t*>(190static_cast<const void*>(shaderc_result_get_bytes(result)));191return bytes[0] == spv::MagicNumber;192}193194// Compiles a shader and returns true if the result is valid SPIR-V.195bool CompilesToValidSpv(Compiler& compiler, const std::string& shader,196shaderc_shader_kind kind,197const shaderc_compile_options_t options = nullptr) {198const Compilation comp(compiler.get_compiler_handle(), shader, kind, "shader",199"main", options, OutputType::SpirvBinary);200return ResultContainsValidSpv(comp.result());201}202203// A testing class to test the compilation of a string with or without options.204// This class wraps the initailization of compiler and compiler options and205// groups the result checking methods. Subclass tests can access the compiler206// object and compiler option object to set their properties. Input file names207// are set to "shader".208class CompileStringTest : public testing::Test {209protected:210// Compiles a shader and returns true on success, false on failure.211bool CompilationSuccess(const std::string& shader, shaderc_shader_kind kind,212shaderc_compile_options_t options = nullptr,213OutputType output_type = OutputType::SpirvBinary) {214return CompilationResultIsSuccess(215Compilation(compiler_.get_compiler_handle(), shader, kind, "shader",216"main", options, output_type)217.result());218}219220// Compiles a shader, expects compilation success, and returns the warning221// messages.222const std::string CompilationWarnings(223const std::string& shader, shaderc_shader_kind kind,224const shaderc_compile_options_t options = nullptr,225OutputType output_type = OutputType::SpirvBinary) {226const Compilation comp(compiler_.get_compiler_handle(), shader, kind,227"shader", "main", options, output_type);228EXPECT_TRUE(CompilationResultIsSuccess(comp.result())) << kind << '\n'229<< shader;230return shaderc_result_get_error_message(comp.result());231}232233// Compiles a shader, expects compilation failure, and returns the messages.234const std::string CompilationErrors(235const std::string& shader, shaderc_shader_kind kind,236const shaderc_compile_options_t options = nullptr,237OutputType output_type = OutputType::SpirvBinary,238const char* source_name = "shader") {239const Compilation comp(compiler_.get_compiler_handle(), shader, kind,240source_name, "main", options, output_type);241EXPECT_FALSE(CompilationResultIsSuccess(comp.result())) << kind << '\n'242<< shader;243EXPECT_EQ(0u, shaderc_result_get_length(comp.result()));244return shaderc_result_get_error_message(comp.result());245}246247// Compiles a shader and returns the messages.248const std::string CompilationMessages(249const std::string& shader, shaderc_shader_kind kind,250const shaderc_compile_options_t options = nullptr,251OutputType output_type = OutputType::SpirvBinary) {252const Compilation comp(compiler_.get_compiler_handle(), shader, kind,253"shader", "main", options, output_type);254return shaderc_result_get_error_message(comp.result());255}256257// Compiles a shader, expects compilation success, and returns the output258// bytes.259const std::string CompilationOutput(260const std::string& shader, shaderc_shader_kind kind,261const shaderc_compile_options_t options = nullptr,262OutputType output_type = OutputType::SpirvBinary) {263const Compilation comp(compiler_.get_compiler_handle(), shader, kind,264"shader", "main", options, output_type);265EXPECT_TRUE(CompilationResultIsSuccess(comp.result()))266<< "shader kind: " << kind << "\nerror message: "267<< shaderc_result_get_error_message(comp.result())268<< "\nshader source code: \n"269<< shader;270// Use string(const char* s, size_t n) constructor instead of271// string(const char* s) to make sure the string has complete binary data.272// string(const char* s) assumes a null-terminated C-string, which will cut273// the binary data when it sees a '\0' byte.274return std::string(shaderc_result_get_bytes(comp.result()),275shaderc_result_get_length(comp.result()));276}277278Compiler compiler_;279compile_options_ptr options_;280281public:282CompileStringTest() : options_(shaderc_compile_options_initialize()) {}283};284285// A testing class to test the assembling of a string.286// This class wraps the initailization of compiler and groups the result287// checking methods. Subclass tests can access the compiler object to set their288// properties.289class AssembleStringTest : public testing::Test {290public:291AssembleStringTest() : options_(shaderc_compile_options_initialize()) {}292~AssembleStringTest() { shaderc_compile_options_release(options_); }293294protected:295// Assembles the given assembly and returns true on success.296bool AssemblingSuccess(const std::string& assembly) {297return CompilationResultIsSuccess(298Assembling(compiler_.get_compiler_handle(), assembly, options_)299.result());300}301302bool AssemblingValid(const std::string& assembly) {303const auto assembling =304Assembling(compiler_.get_compiler_handle(), assembly);305return ResultContainsValidSpv(assembling.result());306}307308Compiler compiler_;309shaderc_compile_options_t options_;310};311312// Name holders so that we have test cases being grouped with only one real313// compilation class.314using CompileStringWithOptionsTest = CompileStringTest;315using CompileKindsTest = CompileStringTest;316317TEST_F(CompileStringTest, EmptyString) {318ASSERT_NE(nullptr, compiler_.get_compiler_handle());319EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_vertex_shader));320EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_fragment_shader));321}322323TEST_F(AssembleStringTest, EmptyString) {324ASSERT_NE(nullptr, compiler_.get_compiler_handle());325EXPECT_TRUE(AssemblingSuccess(""));326}327328TEST_F(CompileStringTest, GarbageString) {329ASSERT_NE(nullptr, compiler_.get_compiler_handle());330EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_vertex_shader));331EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_fragment_shader));332}333334TEST_F(AssembleStringTest, GarbageString) {335ASSERT_NE(nullptr, compiler_.get_compiler_handle());336auto assembling = Assembling(compiler_.get_compiler_handle(), "jfalkds");337EXPECT_FALSE(CompilationResultIsSuccess(assembling.result()));338EXPECT_EQ(1u, shaderc_result_get_num_errors(assembling.result()));339EXPECT_EQ(0u, shaderc_result_get_num_warnings(assembling.result()));340}341342// TODO(antiagainst): right now there is no assembling difference for all the343// target environments exposed by shaderc. So the following is just testing the344// target environment is accepted.345TEST_F(AssembleStringTest, AcceptTargetEnv) {346ASSERT_NE(nullptr, compiler_.get_compiler_handle());347shaderc_compile_options_set_target_env(options_, shaderc_target_env_opengl,348/* version = */ 0);349EXPECT_TRUE(AssemblingSuccess("OpCapability Shader"));350}351352TEST_F(CompileStringTest, ReallyLongShader) {353ASSERT_NE(nullptr, compiler_.get_compiler_handle());354std::string minimal_shader = "";355minimal_shader += "#version 140\n";356minimal_shader += "void foo(){}";357minimal_shader.append(1024 * 1024 * 8, ' '); // 8MB of spaces.358minimal_shader += "void main(){}";359EXPECT_TRUE(CompilesToValidSpv(compiler_, minimal_shader,360shaderc_glsl_vertex_shader));361EXPECT_TRUE(CompilesToValidSpv(compiler_, minimal_shader,362shaderc_glsl_fragment_shader));363}364365TEST_F(CompileStringTest, MinimalShader) {366ASSERT_NE(nullptr, compiler_.get_compiler_handle());367EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,368shaderc_glsl_vertex_shader));369EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,370shaderc_glsl_fragment_shader));371}372373TEST_F(AssembleStringTest, MinimalShader) {374ASSERT_NE(nullptr, compiler_.get_compiler_handle());375EXPECT_TRUE(AssemblingValid(kMinimalShaderAssembly));376}377378TEST_F(CompileStringTest, WorksWithCompileOptions) {379ASSERT_NE(nullptr, compiler_.get_compiler_handle());380EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,381shaderc_glsl_vertex_shader, options_.get()));382}383384TEST_F(CompileStringTest, GetNumErrors) {385Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader,386shaderc_glsl_vertex_shader, "shader", "main");387// Expects compilation failure and two errors.388EXPECT_FALSE(CompilationResultIsSuccess(comp.result()));389EXPECT_EQ(2u, shaderc_result_get_num_errors(comp.result()));390// Expects the number of warnings to be zero.391EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp.result()));392}393394TEST_F(CompileStringTest, GetNumWarnings) {395Compilation comp(compiler_.get_compiler_handle(), kTwoWarningsShader,396shaderc_glsl_vertex_shader, "shader", "main");397// Expects compilation success with two warnings.398EXPECT_TRUE(CompilationResultIsSuccess(comp.result()));399EXPECT_EQ(2u, shaderc_result_get_num_warnings(comp.result()));400// Expects the number of errors to be zero.401EXPECT_EQ(0u, shaderc_result_get_num_errors(comp.result()));402}403404TEST_F(CompileStringTest, ZeroErrorsZeroWarnings) {405Compilation comp(compiler_.get_compiler_handle(), kMinimalShader,406shaderc_glsl_vertex_shader, "shader", "main");407// Expects compilation success with zero warnings.408EXPECT_TRUE(CompilationResultIsSuccess(comp.result()));409EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp.result()));410// Expects the number of errors to be zero.411EXPECT_EQ(0u, shaderc_result_get_num_errors(comp.result()));412}413414TEST_F(CompileStringTest, ErrorTypeUnknownShaderStage) {415// The shader kind/stage can not be determined, the error type field should416// indicate the error type is shaderc_shader_kind_error.417Compilation comp(compiler_.get_compiler_handle(), kMinimalShader,418shaderc_glsl_infer_from_source, "shader", "main");419EXPECT_EQ(shaderc_compilation_status_invalid_stage,420shaderc_result_get_compilation_status(comp.result()));421}422TEST_F(CompileStringTest, ErrorTypeCompilationError) {423// The shader kind is valid, the result object's error type field should424// indicate this compilaion fails due to compilation errors.425Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader,426shaderc_glsl_vertex_shader, "shader", "main");427EXPECT_EQ(shaderc_compilation_status_compilation_error,428shaderc_result_get_compilation_status(comp.result()));429}430431TEST_F(CompileStringWithOptionsTest, CloneCompilerOptions) {432ASSERT_NE(nullptr, compiler_.get_compiler_handle());433compile_options_ptr options_(shaderc_compile_options_initialize());434EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,435shaderc_glsl_vertex_shader, options_.get()));436compile_options_ptr cloned_options(437shaderc_compile_options_clone(options_.get()));438EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,439shaderc_glsl_vertex_shader,440cloned_options.get()));441}442443TEST_F(CompileStringWithOptionsTest, MacroCompileOptions) {444ASSERT_NE(nullptr, compiler_.get_compiler_handle());445shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, "main",4464u);447const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}";448const std::string kMinimalDoubleExpandedShader = "#version 140\nF E(){}";449EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader,450shaderc_glsl_vertex_shader, options_.get()));451compile_options_ptr cloned_options(452shaderc_compile_options_clone(options_.get()));453// The simplest should still compile with the cloned options.454EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader,455shaderc_glsl_vertex_shader,456cloned_options.get()));457EXPECT_FALSE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader,458shaderc_glsl_vertex_shader,459cloned_options.get()));460461shaderc_compile_options_add_macro_definition(cloned_options.get(), "F", 1u,462"void", 4u);463// This should still not work with the original options.464EXPECT_FALSE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader,465shaderc_glsl_vertex_shader, options_.get()));466// This should work with the cloned options that have the additional467// parameter.468EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader,469shaderc_glsl_vertex_shader,470cloned_options.get()));471}472473TEST_F(CompileStringWithOptionsTest, MacroCompileOptionsNotNullTerminated) {474ASSERT_NE(nullptr, compiler_.get_compiler_handle());475shaderc_compile_options_add_macro_definition(options_.get(), "EFGH", 1u,476"mainnnnnn", 4u);477const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}";478EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader,479shaderc_glsl_vertex_shader, options_.get()));480}481482TEST_F(CompileStringWithOptionsTest, ValuelessMacroCompileOptionsZeroLength) {483ASSERT_NE(nullptr, compiler_.get_compiler_handle());484shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u,485"somthing", 0u);486EXPECT_TRUE(CompilesToValidSpv(compiler_, kValuelessPredefinitionShader,487shaderc_glsl_vertex_shader, options_.get()));488}489490TEST_F(CompileStringWithOptionsTest, ValuelessMacroCompileOptionsNullPointer) {491ASSERT_NE(nullptr, compiler_.get_compiler_handle());492shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, nullptr,493100u);494EXPECT_TRUE(CompilesToValidSpv(compiler_, kValuelessPredefinitionShader,495shaderc_glsl_vertex_shader, options_.get()));496}497498TEST_F(CompileStringWithOptionsTest, DisassemblyOption) {499ASSERT_NE(nullptr, compiler_.get_compiler_handle());500// This should work with both the glslang assembly format and the501// SPIR-V tools assembly format.502const std::string disassembly_text =503CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,504options_.get(), OutputType::SpirvAssemblyText);505EXPECT_THAT(disassembly_text, HasSubstr("Capability Shader"));506EXPECT_THAT(disassembly_text, HasSubstr("MemoryModel"));507}508509TEST_F(CompileStringWithOptionsTest, DisassembleMinimalShader) {510ASSERT_NE(nullptr, compiler_.get_compiler_handle());511const std::string disassembly_text =512CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,513options_.get(), OutputType::SpirvAssemblyText);514for (const auto& substring : kMinimalShaderDisassemblySubstrings) {515EXPECT_THAT(disassembly_text, HasSubstr(substring));516}517}518519TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileCorrectStd) {520// Forces the version and profile to 450core, which fixes the missing521// #version.522shaderc_compile_options_set_forced_version_profile(options_.get(), 450,523shaderc_profile_core);524ASSERT_NE(nullptr, compiler_.get_compiler_handle());525EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion,526shaderc_glsl_vertex_shader, options_.get()));527}528529TEST_F(CompileStringWithOptionsTest,530ForcedVersionProfileCorrectStdClonedOptions) {531// Forces the version and profile to 450core, which fixes the missing532// #version.533shaderc_compile_options_set_forced_version_profile(options_.get(), 450,534shaderc_profile_core);535// This mode should be carried to any clone of the original options object.536compile_options_ptr cloned_options(537shaderc_compile_options_clone(options_.get()));538ASSERT_NE(nullptr, compiler_.get_compiler_handle());539EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion,540shaderc_glsl_vertex_shader,541cloned_options.get()));542}543544TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileInvalidModule) {545// Forces the version and profile to 310es, while the source module is invalid546// for this version of GLSL. Compilation should fail.547shaderc_compile_options_set_forced_version_profile(options_.get(), 310,548shaderc_profile_es);549ASSERT_NE(nullptr, compiler_.get_compiler_handle());550EXPECT_THAT(CompilationErrors(kCoreVertShaderWithoutVersion,551shaderc_glsl_vertex_shader, options_.get()),552HasSubstr("error: 'gl_ClipDistance' : undeclared identifier\n"));553}554555TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileConflictingStd) {556// Forces the version and profile to 450core, which is in conflict with the557// #version in shader.558shaderc_compile_options_set_forced_version_profile(options_.get(), 450,559shaderc_profile_core);560const std::string kVertexShader =561std::string("#version 310 es\n") + kCoreVertShaderWithoutVersion;562ASSERT_NE(nullptr, compiler_.get_compiler_handle());563EXPECT_THAT(CompilationWarnings(kVertexShader, shaderc_glsl_vertex_shader,564options_.get()),565HasSubstr("warning: (version, profile) forced to be (450, core), "566"while in source code it is (310, es)\n"));567}568569TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileUnknownVersionStd) {570// Forces the version and profile to 4242core, which is an unknown version.571shaderc_compile_options_set_forced_version_profile(572options_.get(), 4242 /*unknown version*/, shaderc_profile_core);573ASSERT_NE(nullptr, compiler_.get_compiler_handle());574// Warning message should complain about the unknown version.575//576// Also, Glslang errors out on unkown versions, due to commit:577// https://github.com/KhronosGroup/glslang/commit/9353f1afab8d1c2b1811c6acd807675128eaabc5578const auto errs = CompilationErrors(579kMinimalShader, shaderc_glsl_vertex_shader, options_.get());580EXPECT_THAT(581errs, HasSubstr("warning: (version, profile) forced to be (4242, core), "582"while in source code it is (140, none)\n"));583EXPECT_THAT(errs, HasSubstr("error: version not supported\n"));584}585586TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileVersionsBefore150) {587// Versions before 150 do not allow a profile token, shaderc_profile_none588// should be passed down as the profile parameter.589shaderc_compile_options_set_forced_version_profile(options_.get(), 140,590shaderc_profile_none);591ASSERT_NE(nullptr, compiler_.get_compiler_handle());592EXPECT_TRUE(CompilationSuccess(kMinimalShaderWithoutVersion,593shaderc_glsl_vertex_shader, options_.get()));594}595596TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileRedundantProfileStd) {597// Forces the version and profile to 100core. But versions before 150 do not598// allow a profile token, compilation should fail.599shaderc_compile_options_set_forced_version_profile(options_.get(), 100,600shaderc_profile_core);601ASSERT_NE(nullptr, compiler_.get_compiler_handle());602EXPECT_THAT(CompilationErrors(kMinimalShader, shaderc_glsl_vertex_shader,603options_.get()),604HasSubstr("error: #version: versions before 150 do not allow a "605"profile token\n"));606}607608TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoBinary) {609shaderc_compile_options_set_generate_debug_info(options_.get());610ASSERT_NE(nullptr, compiler_.get_compiler_handle());611const std::string binary_output =612CompilationOutput(kMinimalDebugInfoShader,613shaderc_glsl_vertex_shader, options_.get());614// The binary output should contain the name of the vector (debug_info_sample)615// null-terminated, as well as the whole original source.616std::string vector_name("debug_info_sample");617vector_name.resize(vector_name.size() + 1);618EXPECT_THAT(binary_output, HasSubstr(vector_name));619EXPECT_THAT(binary_output, HasSubstr(kMinimalDebugInfoShader));620}621622TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoBinaryClonedOptions) {623shaderc_compile_options_set_generate_debug_info(options_.get());624compile_options_ptr cloned_options(625shaderc_compile_options_clone(options_.get()));626ASSERT_NE(nullptr, compiler_.get_compiler_handle());627const std::string binary_output =628CompilationOutput(kMinimalDebugInfoShader,629shaderc_glsl_vertex_shader, cloned_options.get());630// The binary output should contain the name of the vector (debug_info_sample)631// null-terminated, as well as the whole original source.632std::string vector_name("debug_info_sample");633vector_name.resize(vector_name.size() + 1);634EXPECT_THAT(binary_output, HasSubstr(vector_name));635EXPECT_THAT(binary_output, HasSubstr(kMinimalDebugInfoShader));636}637638TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoDisassembly) {639shaderc_compile_options_set_generate_debug_info(options_.get());640ASSERT_NE(nullptr, compiler_.get_compiler_handle());641// Generate assembly text we can compare its output as a string.642// The disassembly output should contain the name of the vector:643// debug_info_sample.644EXPECT_THAT(645CompilationOutput(kMinimalDebugInfoShader, shaderc_glsl_vertex_shader,646options_.get(), OutputType::SpirvAssemblyText),647HasSubstr("debug_info_sample"));648}649650TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelZero) {651shaderc_compile_options_set_optimization_level(652options_.get(), shaderc_optimization_level_zero);653const std::string disassembly_text =654CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,655options_.get(), OutputType::SpirvAssemblyText);656for (const auto& substring : kMinimalShaderDisassemblySubstrings) {657EXPECT_THAT(disassembly_text, HasSubstr(substring));658}659// Check that we still have debug instructions.660EXPECT_THAT(disassembly_text, HasSubstr("OpName"));661EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));662}663664TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelPerformance) {665shaderc_compile_options_set_optimization_level(666options_.get(), shaderc_optimization_level_performance);667const std::string disassembly_text =668CompilationOutput(kGlslMultipleFnShader, shaderc_glsl_fragment_shader,669options_.get(), OutputType::SpirvAssemblyText);670// Check that we do not have function calls anymore.671EXPECT_THAT(disassembly_text, Not(HasSubstr("OpFunctionCall")));672}673674TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelSize) {675shaderc_compile_options_set_optimization_level(676options_.get(), shaderc_optimization_level_size);677const std::string disassembly_text =678CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,679options_.get(), OutputType::SpirvAssemblyText);680for (const auto& substring : kMinimalShaderDisassemblySubstrings) {681EXPECT_THAT(disassembly_text, HasSubstr(substring));682}683// Check that we do not have debug instructions.684EXPECT_THAT(disassembly_text, Not(HasSubstr("OpName")));685EXPECT_THAT(disassembly_text, Not(HasSubstr("OpSource")));686}687688TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeForVulkan10Failure) {689shaderc_compile_options_set_source_language(options_.get(),690shaderc_source_language_hlsl);691shaderc_compile_options_set_target_env(options_.get(),692shaderc_target_env_vulkan,693shaderc_env_version_vulkan_1_0);694shaderc_compile_options_set_optimization_level(695options_.get(), shaderc_optimization_level_performance);696697EXPECT_FALSE(CompilesToValidSpv(compiler_, kHlslWaveActiveSumeComputeShader,698shaderc_compute_shader, options_.get()));699}700701TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeForVulkan11Success) {702shaderc_compile_options_set_source_language(options_.get(),703shaderc_source_language_hlsl);704shaderc_compile_options_set_target_env(options_.get(),705shaderc_target_env_vulkan,706shaderc_env_version_vulkan_1_1);707shaderc_compile_options_set_optimization_level(708options_.get(), shaderc_optimization_level_performance);709710const std::string disassembly_text = CompilationOutput(711kHlslWaveActiveSumeComputeShader, shaderc_compute_shader, options_.get(),712OutputType::SpirvAssemblyText);713EXPECT_THAT(disassembly_text, HasSubstr("OpGroupNonUniformIAdd"));714}715716TEST_F(CompileStringWithOptionsTest, FollowingOptLevelOverridesPreviousOne) {717shaderc_compile_options_set_optimization_level(718options_.get(), shaderc_optimization_level_size);719// Optimization level settings overridden by720shaderc_compile_options_set_optimization_level(721options_.get(), shaderc_optimization_level_zero);722const std::string disassembly_text =723CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,724options_.get(), OutputType::SpirvAssemblyText);725for (const auto& substring : kMinimalShaderDisassemblySubstrings) {726EXPECT_THAT(disassembly_text, HasSubstr(substring));727}728// Check that we still have debug instructions.729EXPECT_THAT(disassembly_text, HasSubstr("OpName"));730EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));731}732733TEST_F(CompileStringWithOptionsTest,734GenerateDebugInfoOverridesOptimizationLevel) {735shaderc_compile_options_set_optimization_level(736options_.get(), shaderc_optimization_level_size);737// Optimization level settings overridden by738shaderc_compile_options_set_generate_debug_info(options_.get());739const std::string disassembly_text =740CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,741options_.get(), OutputType::SpirvAssemblyText);742for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) {743EXPECT_THAT(disassembly_text, HasSubstr(substring));744}745// Check that we still have debug instructions.746EXPECT_THAT(disassembly_text, HasSubstr("OpName"));747EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));748}749750TEST_F(CompileStringWithOptionsTest,751GenerateDebugInfoProhibitsOptimizationLevel) {752// Setting generate debug info first also works.753shaderc_compile_options_set_generate_debug_info(options_.get());754shaderc_compile_options_set_optimization_level(755options_.get(), shaderc_optimization_level_size);756const std::string disassembly_text =757CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,758options_.get(), OutputType::SpirvAssemblyText);759for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) {760EXPECT_THAT(disassembly_text, HasSubstr(substring));761}762// Check that we still have debug instructions.763EXPECT_THAT(disassembly_text, HasSubstr("OpName"));764EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));765}766767TEST_F(CompileStringWithOptionsTest, PreprocessingOnlyOption) {768ASSERT_NE(nullptr, compiler_.get_compiler_handle());769const std::string kMinimalShaderWithMacro =770"#version 150\n"771"#define E main\n"772"void E(){}\n";773const std::string preprocessed_text =774CompilationOutput(kMinimalShaderWithMacro, shaderc_glsl_vertex_shader,775options_.get(), OutputType::PreprocessedText);776EXPECT_THAT(preprocessed_text, HasSubstr("void main() { }"));777778const std::string kMinimalShaderWithMacroCloneOption =779"#version 150\n"780"#define E_CLONE_OPTION main\n"781"void E_CLONE_OPTION(){}\n";782compile_options_ptr cloned_options(783shaderc_compile_options_clone(options_.get()));784const std::string preprocessed_text_cloned_options = CompilationOutput(785kMinimalShaderWithMacroCloneOption, shaderc_glsl_vertex_shader,786options_.get(), OutputType::PreprocessedText);787EXPECT_THAT(preprocessed_text_cloned_options, HasSubstr("void main() { }"));788}789790// A shader kind test cases needs: 1) A shader text with or without #pragma791// annotation, 2) shader_kind.792struct ShaderKindTestCase {793const char* shader_;794shaderc_shader_kind shader_kind_;795};796797// Test the shader kind deduction process. If the shader kind is one of the798// forced ones, the compiler will just try to compile the source code in that799// specified shader kind. If the shader kind is shaderc_glsl_deduce_from_pragma,800// the compiler will determine the shader kind from #pragma annotation in the801// source code and emit error if none such annotation is found. When the shader802// kind is one of the default ones, the compiler will fall back to use the803// specified shader kind if and only if #pragma annoation is not found.804805// Valid shader kind settings should generate valid SPIR-V code.806using ValidShaderKind = testing::TestWithParam<ShaderKindTestCase>;807808TEST_P(ValidShaderKind, ValidSpvCode) {809const ShaderKindTestCase& test_case = GetParam();810Compiler compiler;811EXPECT_TRUE(812CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_));813}814815INSTANTIATE_TEST_SUITE_P(816CompileStringTest, ValidShaderKind,817testing::ValuesIn(std::vector<ShaderKindTestCase>{818// Valid default shader kinds.819{kEmpty310ESShader, shaderc_glsl_default_vertex_shader},820{kEmpty310ESShader, shaderc_glsl_default_fragment_shader},821{kEmpty310ESShader, shaderc_glsl_default_compute_shader},822{kGeometryOnlyShader, shaderc_glsl_default_geometry_shader},823{kTessControlOnlyShader, shaderc_glsl_default_tess_control_shader},824{kTessEvaluationOnlyShader,825shaderc_glsl_default_tess_evaluation_shader},826{kNVMeshShader, shaderc_glsl_default_mesh_shader},827{kNVTaskShader, shaderc_glsl_default_task_shader},828829// #pragma annotation overrides default shader kinds.830{kVertexOnlyShaderWithPragma, shaderc_glsl_default_compute_shader},831{kFragmentOnlyShaderWithPragma, shaderc_glsl_default_vertex_shader},832{kTessControlOnlyShaderWithPragma,833shaderc_glsl_default_fragment_shader},834{kTessEvaluationOnlyShaderWithPragma,835shaderc_glsl_default_tess_control_shader},836{kGeometryOnlyShaderWithPragma,837shaderc_glsl_default_tess_evaluation_shader},838{kComputeOnlyShaderWithPragma, shaderc_glsl_default_geometry_shader},839{kNVMeshShaderWithPragma, shaderc_glsl_default_geometry_shader},840{kNVTaskShaderWithPragma, shaderc_glsl_default_geometry_shader},841842// Infer from source843{kVertexOnlyShaderWithPragma, shaderc_glsl_infer_from_source},844{kNVMeshShaderWithPragma, shaderc_glsl_infer_from_source},845{kNVTaskShaderWithPragma, shaderc_glsl_infer_from_source},846847// Specified non-default shader kind overrides #pragma annotation.848{kVertexOnlyShaderWithInvalidPragma, shaderc_glsl_vertex_shader},849}));850851using InvalidShaderKind = testing::TestWithParam<ShaderKindTestCase>;852853// Invalid shader kind settings should generate errors.854TEST_P(InvalidShaderKind, CompilationShouldFail) {855const ShaderKindTestCase& test_case = GetParam();856Compiler compiler;857EXPECT_FALSE(858CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_));859}860861INSTANTIATE_TEST_SUITE_P(862CompileStringTest, InvalidShaderKind,863testing::ValuesIn(std::vector<ShaderKindTestCase>{864// Invalid default shader kind.865{kVertexOnlyShader, shaderc_glsl_default_fragment_shader},866// Sets to deduce shader kind from #pragma, but #pragma is defined in867// the source code.868{kVertexOnlyShader, shaderc_glsl_infer_from_source},869// Invalid #pragma cause errors, even though default shader kind is set870// to valid shader kind.871{kVertexOnlyShaderWithInvalidPragma,872shaderc_glsl_default_vertex_shader},873}));874875// To test file inclusion, use an unordered_map as a fake file system to store876// fake files to be included. The unordered_map represents a filesystem by877// mapping filename (or path) string to the contents of that file as a string.878using FakeFS = std::unordered_map<std::string, std::string>;879880// An includer test case needs: 1) A fake file system which is actually an881// unordered_map, so that we can resolve the content given a string. A valid882// fake file system must have one entry with key:'root' to specify the start883// shader file for compilation. 2) An string that we expect to see in the884// compilation output.885class IncluderTestCase {886public:887IncluderTestCase(FakeFS fake_fs, std::string expected_substring)888: fake_fs_(fake_fs), expected_substring_(expected_substring) {889assert(fake_fs_.find("root") != fake_fs_.end() &&890"Valid fake file system needs a 'root' file\n");891}892893const FakeFS& fake_fs() const { return fake_fs_; }894const std::string& expected_substring() const { return expected_substring_; }895896private:897FakeFS fake_fs_;898std::string expected_substring_;899};900901// A mock class that simulate an includer. C API needs two function pointers902// each for get including data and release the data. This class defined two903// static functions, which wrap their matching member functions, to be passed to904// libshaderc C API.905class TestIncluder {906public:907explicit TestIncluder(const FakeFS& fake_fs)908: fake_fs_(fake_fs), responses_({}) {}909910// Get path and content from the fake file system.911shaderc_include_result* GetInclude(const char* filename) {912responses_.emplace_back(shaderc_include_result{913filename, strlen(filename), fake_fs_.at(std::string(filename)).c_str(),914fake_fs_.at(std::string(filename)).size()});915return &responses_.back();916}917918// Response data is owned as private property, no need to release explicitly.919void ReleaseInclude(shaderc_include_result*) {}920921// Wrapper for the corresponding member function.922static shaderc_include_result* GetIncluderResponseWrapper(923void* user_data, const char* filename, int, const char* includer,924size_t include_depth) {925return static_cast<TestIncluder*>(user_data)->GetInclude(filename);926}927928// Wrapper for the corresponding member function.929static void ReleaseIncluderResponseWrapper(void* user_data,930shaderc_include_result* data) {931return static_cast<TestIncluder*>(user_data)->ReleaseInclude(data);932}933934private:935// Includer response data is stored as private property.936const FakeFS& fake_fs_;937std::vector<shaderc_include_result> responses_;938};939940using IncluderTests = testing::TestWithParam<IncluderTestCase>;941942// Parameterized tests for includer.943TEST_P(IncluderTests, SetIncluderCallbacks) {944const IncluderTestCase& test_case = GetParam();945const FakeFS& fs = test_case.fake_fs();946const std::string& shader = fs.at("root");947TestIncluder includer(fs);948Compiler compiler;949compile_options_ptr options(shaderc_compile_options_initialize());950shaderc_compile_options_set_include_callbacks(951options.get(), TestIncluder::GetIncluderResponseWrapper,952TestIncluder::ReleaseIncluderResponseWrapper, &includer);953954const Compilation comp(compiler.get_compiler_handle(), shader,955shaderc_glsl_vertex_shader, "shader", "main",956options.get(), OutputType::PreprocessedText);957// Checks the existence of the expected string.958EXPECT_THAT(shaderc_result_get_bytes(comp.result()),959HasSubstr(test_case.expected_substring()));960}961962TEST_P(IncluderTests, SetIncluderCallbacksClonedOptions) {963const IncluderTestCase& test_case = GetParam();964const FakeFS& fs = test_case.fake_fs();965const std::string& shader = fs.at("root");966TestIncluder includer(fs);967Compiler compiler;968compile_options_ptr options(shaderc_compile_options_initialize());969shaderc_compile_options_set_include_callbacks(970options.get(), TestIncluder::GetIncluderResponseWrapper,971TestIncluder::ReleaseIncluderResponseWrapper, &includer);972973// Cloned options should have all the settings.974compile_options_ptr cloned_options(975shaderc_compile_options_clone(options.get()));976977const Compilation comp(compiler.get_compiler_handle(), shader,978shaderc_glsl_vertex_shader, "shader", "main",979cloned_options.get(), OutputType::PreprocessedText);980// Checks the existence of the expected string.981EXPECT_THAT(shaderc_result_get_bytes(comp.result()),982HasSubstr(test_case.expected_substring()));983}984985INSTANTIATE_TEST_SUITE_P(CompileStringTest, IncluderTests,986testing::ValuesIn(std::vector<IncluderTestCase>{987IncluderTestCase(988// Fake file system.989{990{"root",991"#version 150\n"992"void foo() {}\n"993"#include \"path/to/file_1\"\n"},994{"path/to/file_1", "content of file_1\n"},995},996// Expected output.997"#line 0 \"path/to/file_1\"\n"998" content of file_1\n"999"#line 3"),1000IncluderTestCase(1001// Fake file system.1002{{"root",1003"#version 150\n"1004"void foo() {}\n"1005"#include \"path/to/file_1\"\n"},1006{"path/to/file_1",1007"#include \"path/to/file_2\"\n"1008"content of file_1\n"},1009{"path/to/file_2", "content of file_2\n"}},1010// Expected output.1011"#line 0 \"path/to/file_1\"\n"1012"#line 0 \"path/to/file_2\"\n"1013" content of file_2\n"1014"#line 1 \"path/to/file_1\"\n"1015" content of file_1\n"1016"#line 3"),10171018}));10191020TEST_F(CompileStringWithOptionsTest, WarningsOnLine) {1021// Some versions of Glslang will return an error, some will return just1022// warnings.1023EXPECT_THAT(1024CompilationMessages(kDeprecatedAttributeShader,1025shaderc_glsl_vertex_shader, options_.get()),1026HasSubstr(":2: warning: attribute deprecated in version 130; may be "1027"removed in future release\n"));1028}10291030TEST_F(CompileStringWithOptionsTest, WarningsOnLineAsErrors) {1031shaderc_compile_options_set_warnings_as_errors(options_.get());1032ASSERT_NE(nullptr, compiler_.get_compiler_handle());1033EXPECT_THAT(1034CompilationErrors(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader,1035options_.get()),1036HasSubstr(":2: error: attribute deprecated in version 130; may be "1037"removed in future release\n"));1038}10391040TEST_F(CompileStringWithOptionsTest, SuppressWarningsOnLine) {1041ASSERT_NE(nullptr, compiler_.get_compiler_handle());1042shaderc_compile_options_set_suppress_warnings(options_.get());1043EXPECT_THAT(1044CompilationMessages(kDeprecatedAttributeShader,1045shaderc_glsl_vertex_shader, options_.get()),1046Not(HasSubstr(":2: warning: attribute deprecated in version 130; may be "1047"removed in future release\n")));1048}10491050TEST_F(CompileStringWithOptionsTest, GlobalWarnings) {1051ASSERT_NE(nullptr, compiler_.get_compiler_handle());1052shaderc_compile_options_set_forced_version_profile(options_.get(), 400,1053shaderc_profile_core);1054EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader,1055shaderc_glsl_vertex_shader, options_.get()),1056HasSubstr("(version, profile) forced to be (400, core),"1057" while in source code it is (550, none)\n"));1058}10591060TEST_F(CompileStringWithOptionsTest, GlobalWarningsAsErrors) {1061shaderc_compile_options_set_warnings_as_errors(options_.get());1062ASSERT_NE(nullptr, compiler_.get_compiler_handle());1063shaderc_compile_options_set_forced_version_profile(options_.get(), 400,1064shaderc_profile_core);1065EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader,1066shaderc_glsl_vertex_shader, options_.get()),1067HasSubstr("(version, profile) forced to be (400, core),"1068" while in source code it is (550, none)\n"));1069}10701071TEST_F(CompileStringWithOptionsTest, SuppressGlobalWarnings) {1072ASSERT_NE(nullptr, compiler_.get_compiler_handle());1073shaderc_compile_options_set_suppress_warnings(options_.get());1074shaderc_compile_options_set_forced_version_profile(options_.get(), 400,1075shaderc_profile_core);1076EXPECT_EQ("",1077CompilationWarnings(kMinimalUnknownVersionShader,1078shaderc_glsl_vertex_shader, options_.get()));1079}10801081TEST_F(CompileStringWithOptionsTest,1082SuppressWarningsModeFirstOverridesWarningsAsErrorsMode) {1083// Sets suppress-warnings mode first, then sets warnings-as-errors mode.1084// suppress-warnings mode should override warnings-as-errors mode.1085shaderc_compile_options_set_suppress_warnings(options_.get());1086shaderc_compile_options_set_warnings_as_errors(options_.get());1087ASSERT_NE(nullptr, compiler_.get_compiler_handle());10881089// Warnings on particular lines should be inhibited.1090Compilation comp_line(compiler_.get_compiler_handle(),1091kDeprecatedAttributeShader, shaderc_glsl_vertex_shader,1092"shader", "main", options_.get());1093EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result()));10941095// Global warnings should be inhibited.1096Compilation comp_global(1097compiler_.get_compiler_handle(), kMinimalUnknownVersionShader,1098shaderc_glsl_vertex_shader, "shader", "main", options_.get());1099EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result()));1100}11011102TEST_F(CompileStringWithOptionsTest,1103SuppressWarningsModeSecondOverridesWarningsAsErrorsMode) {1104// Sets suppress-warnings mode first, then sets warnings-as-errors mode.1105// suppress-warnings mode should override warnings-as-errors mode.1106shaderc_compile_options_set_warnings_as_errors(options_.get());1107shaderc_compile_options_set_suppress_warnings(options_.get());1108ASSERT_NE(nullptr, compiler_.get_compiler_handle());11091110// Warnings on particular lines should be inhibited.1111Compilation comp_line(compiler_.get_compiler_handle(),1112kDeprecatedAttributeShader, shaderc_glsl_vertex_shader,1113"shader", "main", options_.get());1114EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result()));11151116// Global warnings should be inhibited.1117Compilation comp_global(1118compiler_.get_compiler_handle(), kMinimalUnknownVersionShader,1119shaderc_glsl_vertex_shader, "shader", "main", options_.get());1120EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result()));1121}11221123TEST_F(CompileStringWithOptionsTest, IfDefCompileOption) {1124ASSERT_NE(nullptr, compiler_.get_compiler_handle());1125shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, nullptr,11260u);1127const std::string kMinimalExpandedShader =1128"#version 140\n"1129"#ifdef E\n"1130"void main(){}\n"1131"#else\n"1132"#error\n"1133"#endif";1134EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader,1135shaderc_glsl_vertex_shader, options_.get()));1136}11371138TEST_F(1139CompileStringWithOptionsTest,1140TargetEnvRespectedWhenCompilingOpenGLCompatibilityShaderToBinaryAndAlwaysFails) {1141// Glslang does not support generating SPIR-V for compatibility profile1142// shaders.11431144EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader,1145shaderc_glsl_fragment_shader,1146options_.get()));11471148shaderc_compile_options_set_target_env(options_.get(),1149shaderc_target_env_opengl_compat, 0);1150EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader,1151shaderc_glsl_fragment_shader,1152options_.get()));11531154shaderc_compile_options_set_target_env(options_.get(),1155shaderc_target_env_opengl, 0);1156EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader,1157shaderc_glsl_fragment_shader,1158options_.get()));11591160shaderc_compile_options_set_target_env(options_.get(),1161shaderc_target_env_vulkan, 0);1162EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader,1163shaderc_glsl_fragment_shader,1164options_.get()));1165}11661167TEST_F(CompileStringWithOptionsTest, CompilingFailsWhenTargetingOpenGLCompat) {1168// Confirm that kOpenGLVertexShader fails when targeting OpenGL1169// compatibility profile.11701171shaderc_compile_options_set_target_env(options_.get(),1172shaderc_target_env_opengl_compat, 0);1173EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLVertexShader,1174shaderc_glsl_vertex_shader, options_.get()));1175const std::string errors = CompilationErrors(1176kOpenGLVertexShader, shaderc_glsl_vertex_shader, options_.get());1177EXPECT_EQ(errors, "error: OpenGL compatibility profile is not supported");1178}11791180TEST_F(CompileStringWithOptionsTest,1181TargetEnvRespectedWhenCompilingOpenGLCoreShaderToBinary) {1182// Confirm that kOpenGLVertexShader compiles when targeting OpenGL core1183// profile.11841185shaderc_compile_options_set_target_env(options_.get(),1186shaderc_target_env_opengl, 0);1187EXPECT_TRUE(CompilesToValidSpv(compiler_, kOpenGLVertexShader,1188shaderc_glsl_vertex_shader, options_.get()));1189}11901191TEST_F(CompileStringWithOptionsTest,1192TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_0Succeeds) {1193shaderc_compile_options_set_target_env(options_.get(),1194shaderc_target_env_vulkan,1195shaderc_env_version_vulkan_1_0);1196EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeBarrier,1197shaderc_glsl_compute_shader, options_.get()));1198}11991200TEST_F(CompileStringWithOptionsTest,1201TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_1Succeeds) {1202shaderc_compile_options_set_target_env(options_.get(),1203shaderc_target_env_vulkan,1204shaderc_env_version_vulkan_1_1);1205EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeBarrier,1206shaderc_glsl_compute_shader, options_.get()));1207}12081209TEST_F(CompileStringWithOptionsTest,1210TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_0Fails) {1211shaderc_compile_options_set_target_env(options_.get(),1212shaderc_target_env_vulkan,1213shaderc_env_version_vulkan_1_0);1214EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderComputeSubgroupBarrier,1215shaderc_glsl_compute_shader, options_.get()));1216}12171218TEST_F(CompileStringWithOptionsTest,1219TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_1Succeeds) {1220shaderc_compile_options_set_target_env(options_.get(),1221shaderc_target_env_vulkan,1222shaderc_env_version_vulkan_1_1);1223EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeSubgroupBarrier,1224shaderc_glsl_compute_shader, options_.get()));1225}12261227// task shader1228TEST_F(CompileStringWithOptionsTest,1229TargetEnvRespectedWhenCompilingVulkan1_0TaskShaderToVulkan1_0Succeeds) {1230shaderc_compile_options_set_target_env(options_.get(),1231shaderc_target_env_vulkan,1232shaderc_env_version_vulkan_1_0);1233EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskBarrier,1234shaderc_glsl_task_shader, options_.get()));1235}12361237TEST_F(CompileStringWithOptionsTest,1238TargetEnvRespectedWhenCompilingVulkan1_0TaskShaderToVulkan1_1Succeeds) {1239shaderc_compile_options_set_target_env(options_.get(),1240shaderc_target_env_vulkan,1241shaderc_env_version_vulkan_1_1);1242EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskBarrier,1243shaderc_glsl_task_shader, options_.get()));1244}12451246TEST_F(CompileStringWithOptionsTest,1247TargetEnvRespectedWhenCompilingVulkan1_1TaskShaderToVulkan1_0Fails) {1248shaderc_compile_options_set_target_env(options_.get(),1249shaderc_target_env_vulkan,1250shaderc_env_version_vulkan_1_0);1251EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderTaskSubgroupBarrier,1252shaderc_glsl_task_shader, options_.get()));1253}12541255TEST_F(CompileStringWithOptionsTest,1256TargetEnvRespectedWhenCompilingVulkan1_1TaskShaderToVulkan1_1Succeeds) {1257shaderc_compile_options_set_target_env(options_.get(),1258shaderc_target_env_vulkan,1259shaderc_env_version_vulkan_1_1);1260EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskSubgroupBarrier,1261shaderc_glsl_task_shader, options_.get()));1262}12631264// mesh shader1265TEST_F(CompileStringWithOptionsTest,1266TargetEnvRespectedWhenCompilingVulkan1_0MeshShaderToVulkan1_0Succeeds) {1267shaderc_compile_options_set_target_env(options_.get(),1268shaderc_target_env_vulkan,1269shaderc_env_version_vulkan_1_0);1270EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshBarrier,1271shaderc_glsl_mesh_shader, options_.get()));1272}12731274TEST_F(CompileStringWithOptionsTest,1275TargetEnvRespectedWhenCompilingVulkan1_0MeshShaderToVulkan1_1Succeeds) {1276shaderc_compile_options_set_target_env(options_.get(),1277shaderc_target_env_vulkan,1278shaderc_env_version_vulkan_1_1);1279EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshBarrier,1280shaderc_glsl_mesh_shader, options_.get()));1281}12821283TEST_F(CompileStringWithOptionsTest,1284TargetEnvRespectedWhenCompilingVulkan1_1MeshShaderToVulkan1_0Fails) {1285shaderc_compile_options_set_target_env(options_.get(),1286shaderc_target_env_vulkan,1287shaderc_env_version_vulkan_1_0);1288EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderMeshSubgroupBarrier,1289shaderc_glsl_mesh_shader, options_.get()));1290}12911292TEST_F(CompileStringWithOptionsTest,1293TargetEnvRespectedWhenCompilingVulkan1_1MeshShaderToVulkan1_1Succeeds) {1294shaderc_compile_options_set_target_env(options_.get(),1295shaderc_target_env_vulkan,1296shaderc_env_version_vulkan_1_1);1297EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshSubgroupBarrier,1298shaderc_glsl_mesh_shader, options_.get()));1299}13001301TEST_F(CompileStringWithOptionsTest,1302DISABLED_TargetEnvIgnoredWhenPreprocessing) {1303// This test is disabled since some versions of glslang may refuse to compile1304// very old shaders to SPIR-V with OpenGL target. Re-enable and rewrite this1305// test once we have a differential set of environments to test.1306const auto output_type = OutputType::PreprocessedText;13071308EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader,1309shaderc_glsl_fragment_shader, options_.get(),1310output_type));13111312shaderc_compile_options_set_target_env(options_.get(),1313shaderc_target_env_opengl_compat, 0);1314EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader,1315shaderc_glsl_fragment_shader, options_.get(),1316output_type));13171318shaderc_compile_options_set_target_env(options_.get(),1319shaderc_target_env_opengl, 0);1320EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader,1321shaderc_glsl_fragment_shader, options_.get(),1322output_type));13231324shaderc_compile_options_set_target_env(options_.get(),1325shaderc_target_env_vulkan, 0);1326EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader,1327shaderc_glsl_fragment_shader, options_.get(),1328output_type));1329}13301331TEST_F(CompileStringTest, ShaderKindRespected) {1332ASSERT_NE(nullptr, compiler_.get_compiler_handle());1333const std::string kVertexShader =1334"#version 140\nvoid main(){ gl_Position = vec4(0);}";1335EXPECT_TRUE(CompilationSuccess(kVertexShader, shaderc_glsl_vertex_shader));1336EXPECT_FALSE(CompilationSuccess(kVertexShader, shaderc_glsl_fragment_shader));1337}13381339TEST_F(CompileStringTest, ErrorsReported) {1340ASSERT_NE(nullptr, compiler_.get_compiler_handle());1341EXPECT_THAT(CompilationErrors("int f(){return wrongname;}",1342shaderc_glsl_vertex_shader),1343HasSubstr("wrongname"));1344}13451346#ifndef SHADERC_DISABLE_THREADED_TESTS1347TEST_F(CompileStringTest, MultipleThreadsCalling) {1348ASSERT_NE(nullptr, compiler_.get_compiler_handle());1349bool results[10];1350std::vector<std::thread> threads;1351for (auto& r : results) {1352threads.emplace_back([&r, this]() {1353r = CompilationSuccess("#version 140\nvoid main(){}",1354shaderc_glsl_vertex_shader);1355});1356}1357for (auto& t : threads) {1358t.join();1359}1360EXPECT_THAT(results, Each(true));1361}1362#endif13631364TEST_F(CompileKindsTest, Vertex) {1365ASSERT_NE(nullptr, compiler_.get_compiler_handle());1366const std::string kVertexShader =1367"#version 140\nvoid main(){ gl_Position = vec4(0);}";1368EXPECT_TRUE(CompilationSuccess(kVertexShader, shaderc_glsl_vertex_shader));1369}13701371TEST_F(CompileKindsTest, Fragment) {1372ASSERT_NE(nullptr, compiler_.get_compiler_handle());1373const std::string kFragShader =1374"#version 140\nvoid main(){ gl_FragColor = vec4(0);}";1375EXPECT_TRUE(CompilationSuccess(kFragShader, shaderc_glsl_fragment_shader));1376}13771378TEST_F(CompileKindsTest, Compute) {1379ASSERT_NE(nullptr, compiler_.get_compiler_handle());1380const std::string kCompShader =1381R"(#version 310 es1382void main() {}1383)";1384EXPECT_TRUE(CompilationSuccess(kCompShader, shaderc_glsl_compute_shader));1385}13861387TEST_F(CompileKindsTest, Geometry) {1388ASSERT_NE(nullptr, compiler_.get_compiler_handle());1389const std::string kGeoShader =13901391R"(#version 310 es1392#extension GL_OES_geometry_shader : enable1393layout(points) in;1394layout(points, max_vertices=1) out;1395void main() {1396gl_Position = vec4(1.0);1397EmitVertex();1398EndPrimitive();1399}1400)";1401EXPECT_TRUE(CompilationSuccess(kGeoShader, shaderc_glsl_geometry_shader));1402}14031404TEST_F(CompileKindsTest, TessControl) {1405ASSERT_NE(nullptr, compiler_.get_compiler_handle());1406const std::string kTessControlShader =1407R"(#version 310 es1408#extension GL_OES_tessellation_shader : enable1409layout(vertices=1) out;1410void main() {}1411)";1412EXPECT_TRUE(1413CompilationSuccess(kTessControlShader, shaderc_glsl_tess_control_shader));1414}14151416TEST_F(CompileKindsTest, TessEvaluation) {1417ASSERT_NE(nullptr, compiler_.get_compiler_handle());1418const std::string kTessEvaluationShader =1419R"(#version 310 es1420#extension GL_OES_tessellation_shader : enable1421layout(triangles, equal_spacing, ccw) in;1422void main() {1423gl_Position = vec4(gl_TessCoord, 1.0);1424}1425)";1426EXPECT_TRUE(CompilationSuccess(kTessEvaluationShader,1427shaderc_glsl_tess_evaluation_shader));1428}14291430// A test case for ParseVersionProfileTest needs: 1) the input string, 2)1431// expected parsing results, including 'succeed' flag, version value, and1432// profile enum.1433struct ParseVersionProfileTestCase {1434ParseVersionProfileTestCase(1435const std::string& input_string, bool expected_succeed,1436int expected_version = 0,1437shaderc_profile expected_profile = shaderc_profile_none)1438: input_string_(input_string),1439expected_succeed_(expected_succeed),1440expected_version_(expected_version),1441expected_profile_(expected_profile) {}1442std::string input_string_;1443bool expected_succeed_;1444int expected_version_;1445shaderc_profile expected_profile_;1446};14471448// Test for a helper function to parse version and profile from string.1449using ParseVersionProfileTest =1450testing::TestWithParam<ParseVersionProfileTestCase>;14511452TEST_P(ParseVersionProfileTest, FromNullTerminatedString) {1453const ParseVersionProfileTestCase& test_case = GetParam();1454int version;1455shaderc_profile profile;1456bool succeed = shaderc_parse_version_profile(test_case.input_string_.c_str(),1457&version, &profile);1458EXPECT_EQ(test_case.expected_succeed_, succeed);1459// check the return version and profile only when the parsing succeeds.1460if (succeed) {1461EXPECT_EQ(test_case.expected_version_, version);1462EXPECT_EQ(test_case.expected_profile_, profile);1463}1464}14651466INSTANTIATE_TEST_SUITE_P(1467HelperMethods, ParseVersionProfileTest,1468testing::ValuesIn(std::vector<ParseVersionProfileTestCase>{1469// Valid version profiles1470ParseVersionProfileTestCase("450core", true, 450, shaderc_profile_core),1471ParseVersionProfileTestCase("450compatibility", true, 450,1472shaderc_profile_compatibility),1473ParseVersionProfileTestCase("310es", true, 310, shaderc_profile_es),1474ParseVersionProfileTestCase("100", true, 100, shaderc_profile_none),14751476// Invalid version profiles, the expected_version and expected_profile1477// doesn't matter as they won't be checked if the tests pass correctly.1478ParseVersionProfileTestCase("totally_wrong", false),1479ParseVersionProfileTestCase("111core", false),1480ParseVersionProfileTestCase("450wrongprofile", false),1481ParseVersionProfileTestCase("", false),1482}));14831484TEST_F(CompileStringTest, NullSourceNameFailsCompilingToBinary) {1485EXPECT_THAT(CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader,1486nullptr, OutputType::SpirvBinary, nullptr),1487HasSubstr("Input file name string was null."));1488}14891490TEST_F(CompileStringTest, NullSourceNameFailsCompilingToAssemblyText) {1491EXPECT_THAT(1492CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader, nullptr,1493OutputType::SpirvAssemblyText, nullptr),1494HasSubstr("Input file name string was null."));1495}14961497TEST_F(CompileStringTest, NullSourceNameFailsCompilingToPreprocessedText) {1498EXPECT_THAT(CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader,1499nullptr, OutputType::PreprocessedText, nullptr),1500HasSubstr("Input file name string was null."));1501}15021503const char kGlslVertexShader[] =1504"#version 140\nvoid main(){ gl_Position = vec4(0);}";15051506const char kHlslVertexShader[] =1507"float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION\n"1508"{ return float4(1.0, 2.0, 3.0, 4.0); }";15091510TEST_F(CompileStringTest, LangGlslOnGlslVertexSucceeds) {1511shaderc_compile_options_set_source_language(options_.get(),1512shaderc_source_language_glsl);1513EXPECT_TRUE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader,1514options_.get()));1515}15161517TEST_F(CompileStringTest, LangGlslOnHlslVertexFails) {1518shaderc_compile_options_set_source_language(options_.get(),1519shaderc_source_language_glsl);1520EXPECT_FALSE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader,1521options_.get()));1522}15231524TEST_F(CompileStringTest, LangHlslOnGlslVertexFails) {1525shaderc_compile_options_set_source_language(options_.get(),1526shaderc_source_language_hlsl);1527EXPECT_FALSE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader,1528options_.get()));1529}15301531TEST_F(CompileStringTest, LangHlslOnHlslVertexSucceeds) {1532shaderc_compile_options_set_source_language(options_.get(),1533shaderc_source_language_hlsl);1534EXPECT_TRUE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader,1535options_.get()));1536}15371538TEST(EntryPointTest,1539LangGlslOnHlslVertexSucceedsButAssumesEntryPointNameIsMain) {1540Compiler compiler;1541Options options;1542auto compilation =1543Compilation(compiler.get_compiler_handle(), kGlslVertexShader,1544shaderc_glsl_vertex_shader, "shader", "blah blah blah",1545options.get(), OutputType::SpirvAssemblyText);15461547EXPECT_THAT(shaderc_result_get_bytes(compilation.result()),1548HasSubstr("OpEntryPoint Vertex %main \"main\""))1549<< std::string(shaderc_result_get_bytes(compilation.result()));1550}15511552TEST(EntryPointTest, LangHlslOnHlslVertexSucceedsWithGivenEntryPointName) {1553Compiler compiler;1554Options options;1555shaderc_compile_options_set_source_language(options.get(),1556shaderc_source_language_hlsl);1557auto compilation =1558Compilation(compiler.get_compiler_handle(), kHlslVertexShader,1559shaderc_glsl_vertex_shader, "shader", "EntryPoint",1560options.get(), OutputType::SpirvAssemblyText);15611562EXPECT_THAT(shaderc_result_get_bytes(compilation.result()),1563HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""))1564<< std::string(shaderc_result_get_bytes(compilation.result()));1565}15661567// Returns a fragment shader accessing a texture with the given1568// offset.1569std::string ShaderWithTexOffset(int offset) {1570std::ostringstream oss;1571oss << "#version 450\n"1572"layout (binding=0) uniform sampler1D tex;\n"1573"void main() { vec4 x = textureOffset(tex, 1.0, "1574<< offset << "); }\n";1575return oss.str();1576}15771578// Ensure compilation is sensitive to limit setting. Sample just1579// two particular limits.1580TEST_F(CompileStringTest, LimitsTexelOffsetDefault) {1581EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(),1582shaderc_glsl_fragment_shader,1583options_.get()));1584EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(),1585shaderc_glsl_fragment_shader, options_.get()));1586EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(),1587shaderc_glsl_fragment_shader, options_.get()));1588EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(),1589shaderc_glsl_fragment_shader,1590options_.get()));1591}15921593TEST_F(CompileStringTest, LimitsTexelOffsetLowerMinimum) {1594shaderc_compile_options_set_limit(1595options_.get(), shaderc_limit_min_program_texel_offset, -99);1596EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(),1597shaderc_glsl_fragment_shader,1598options_.get()));1599EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(),1600shaderc_glsl_fragment_shader, options_.get()));1601}16021603TEST_F(CompileStringTest, LimitsTexelOffsetHigherMaximum) {1604shaderc_compile_options_set_limit(options_.get(),1605shaderc_limit_max_program_texel_offset, 10);1606EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(),1607shaderc_glsl_fragment_shader, options_.get()));1608EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(),1609shaderc_glsl_fragment_shader,1610options_.get()));1611}16121613TEST_F(CompileStringWithOptionsTest, UniformsWithoutBindingsFailCompilation) {1614const std::string errors =1615CompilationErrors(kShaderWithUniformsWithoutBindings,1616shaderc_glsl_vertex_shader, options_.get());1617EXPECT_THAT(errors,1618HasSubstr("sampler/texture/image requires layout(binding=X)"));1619}16201621TEST_F(CompileStringWithOptionsTest,1622UniformsWithoutBindingsOptionSetAutoBindingsAssignsBindings) {1623shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1624const std::string disassembly_text = CompilationOutput(1625kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,1626options_.get(), OutputType::SpirvAssemblyText);1627EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));1628EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));1629EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2"));1630EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3"));1631EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4"));1632}16331634TEST_F(CompileStringWithOptionsTest, AutoBindUniformsOptionsSurvivesCloning) {1635shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1636compile_options_ptr cloned_options(1637shaderc_compile_options_clone(options_.get()));1638const std::string disassembly_text = CompilationOutput(1639kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,1640cloned_options.get(), OutputType::SpirvAssemblyText);1641EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));1642EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));1643EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2"));1644EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3"));1645EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4"));1646}16471648TEST_F(CompileStringWithOptionsTest,1649SetBindingBaseForTextureAdjustsTextureBindingsOnly) {1650shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1651shaderc_compile_options_set_binding_base(options_.get(),1652shaderc_uniform_kind_texture, 44);1653const std::string disassembly_text = CompilationOutput(1654kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,1655options_.get(), OutputType::SpirvAssemblyText);1656EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 44"));1657EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 0"));1658EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1"));1659EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2"));1660EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3"));1661}16621663TEST_F(CompileStringWithOptionsTest,1664SetBindingBaseForSamplerAdjustsSamplerBindingsOnly) {1665shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1666shaderc_compile_options_set_binding_base(options_.get(),1667shaderc_uniform_kind_sampler, 44);1668const std::string disassembly_text = CompilationOutput(1669kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,1670options_.get(), OutputType::SpirvAssemblyText);1671EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));1672EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 44"));1673EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1"));1674EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2"));1675EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3"));1676}16771678TEST_F(CompileStringWithOptionsTest,1679SetBindingBaseForImageAdjustsImageBindingsOnly) {1680shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1681shaderc_compile_options_set_binding_base(options_.get(),1682shaderc_uniform_kind_image, 44);1683const std::string disassembly_text = CompilationOutput(1684kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,1685options_.get(), OutputType::SpirvAssemblyText);1686EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));1687EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));1688EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 44"));1689EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 45"));1690EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 2"));1691}16921693TEST_F(CompileStringWithOptionsTest,1694SetBindingBaseForBufferAdjustsBufferBindingsOnly) {1695shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1696shaderc_compile_options_set_binding_base(options_.get(),1697shaderc_uniform_kind_buffer, 44);1698const std::string disassembly_text = CompilationOutput(1699kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,1700options_.get(), OutputType::SpirvAssemblyText);1701EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));1702EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));1703EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2"));1704EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3"));1705EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 44"));1706}17071708TEST_F(CompileStringWithOptionsTest, SetBindingBaseSurvivesCloning) {1709shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1710shaderc_compile_options_set_binding_base(options_.get(),1711shaderc_uniform_kind_texture, 40);1712shaderc_compile_options_set_binding_base(options_.get(),1713shaderc_uniform_kind_sampler, 50);1714shaderc_compile_options_set_binding_base(options_.get(),1715shaderc_uniform_kind_image, 60);1716shaderc_compile_options_set_binding_base(options_.get(),1717shaderc_uniform_kind_buffer, 70);1718compile_options_ptr cloned_options(1719shaderc_compile_options_clone(options_.get()));1720const std::string disassembly_text = CompilationOutput(1721kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,1722cloned_options.get(), OutputType::SpirvAssemblyText);1723EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 40"));1724EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 50"));1725EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 60"));1726EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 61"));1727EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 70"));1728}17291730TEST(Compiler, IncludeWithoutOptionsReturnsValidError) {1731auto compiler = shaderc_compiler_initialize();1732const char source[] = "#version 450\n#include \"no where\"";1733auto result = shaderc_compile_into_spv(compiler, source, strlen(source),1734shaderc_glsl_vertex_shader, "file",1735"main", nullptr);1736EXPECT_EQ(shaderc_compilation_status_compilation_error,1737shaderc_result_get_compilation_status(result));1738EXPECT_THAT(shaderc_result_get_error_message(result),1739HasSubstr("error: '#include' : #error unexpected include "1740"directive for header name: no where"));17411742shaderc_result_release(result);1743shaderc_compiler_release(compiler);1744}17451746TEST_F(1747CompileStringWithOptionsTest,1748SetBindingBaseForTextureForVertexAdjustsTextureBindingsOnlyCompilingAsVertex) {1749shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1750shaderc_compile_options_set_binding_base_for_stage(1751options_.get(), shaderc_vertex_shader, shaderc_uniform_kind_texture, 100);1752const std::string disassembly_text = CompilationOutput(1753kShaderWithUniformsWithoutBindings, shaderc_vertex_shader, options_.get(),1754OutputType::SpirvAssemblyText);1755EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 100"))1756<< disassembly_text;1757EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 0"));1758EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1"));1759EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2"));1760EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3"));1761}17621763TEST_F(CompileStringWithOptionsTest,1764SetBindingBaseForTextureForVertexIgnoredWhenCompilingAsFragment) {1765shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1766// This is ignored since we're compiling as a different stage.1767shaderc_compile_options_set_binding_base_for_stage(1768options_.get(), shaderc_vertex_shader, shaderc_uniform_kind_texture, 100);1769const std::string disassembly_text = CompilationOutput(1770kShaderWithUniformsWithoutBindings, shaderc_fragment_shader,1771options_.get(), OutputType::SpirvAssemblyText);1772EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));1773EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));1774EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2"));1775EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3"));1776EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4"));1777}17781779TEST_F(CompileStringWithOptionsTest, GlslDefaultPackingUsed) {1780const std::string disassembly_text =1781CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader,1782options_.get(), OutputType::SpirvAssemblyText);1783EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16"));1784}17851786TEST_F(CompileStringWithOptionsTest, HlslOffsetsOptionDisableRespected) {1787shaderc_compile_options_set_hlsl_offsets(options_.get(), false);1788const std::string disassembly_text =1789CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader,1790options_.get(), OutputType::SpirvAssemblyText);1791EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16"));1792}17931794TEST_F(CompileStringWithOptionsTest, HlslOffsetsOptionEnableRespected) {1795shaderc_compile_options_set_hlsl_offsets(options_.get(), true);1796const std::string disassembly_text =1797CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader,1798options_.get(), OutputType::SpirvAssemblyText);1799EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 4"));1800}18011802TEST_F(CompileStringWithOptionsTest, HlslFunctionality1OffByDefault) {1803shaderc_compile_options_set_source_language(options_.get(),1804shaderc_source_language_hlsl);1805// The counter should automatically get a binding.1806shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1807const std::string disassembly_text =1808CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader,1809options_.get(), OutputType::SpirvAssemblyText);1810EXPECT_THAT(disassembly_text, Not(HasSubstr("OpDecorateString")))1811<< disassembly_text;1812}18131814TEST_F(CompileStringWithOptionsTest, HlslFunctionality1Respected) {1815shaderc_compile_options_set_source_language(options_.get(),1816shaderc_source_language_hlsl);1817shaderc_compile_options_set_hlsl_functionality1(options_.get(), true);1818// The counter should automatically get a binding.1819shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1820const std::string disassembly_text =1821CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader,1822options_.get(), OutputType::SpirvAssemblyText);1823EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateString"));1824}18251826TEST_F(CompileStringWithOptionsTest, HlslFunctionality1SurvivesCloning) {1827shaderc_compile_options_set_source_language(options_.get(),1828shaderc_source_language_hlsl);1829shaderc_compile_options_set_hlsl_functionality1(options_.get(), true);1830// The counter should automatically get a binding.1831shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1832compile_options_ptr cloned_options(1833shaderc_compile_options_clone(options_.get()));1834const std::string disassembly_text =1835CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader,1836cloned_options.get(), OutputType::SpirvAssemblyText);1837EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateString"));1838}18391840TEST_F(CompileStringWithOptionsTest, HlslFlexibleMemoryLayoutAllowed) {1841shaderc_compile_options_set_source_language(options_.get(),1842shaderc_source_language_hlsl);1843shaderc_compile_options_set_optimization_level(1844options_.get(), shaderc_optimization_level_performance);1845// There is no way to set the counter's binding, so set it automatically.1846// See https://github.com/KhronosGroup/glslang/issues/16161847shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);1848EXPECT_TRUE(CompilesToValidSpv(compiler_, kHlslMemLayoutResourceSelect,1849shaderc_fragment_shader, options_.get()));1850}18511852TEST_F(CompileStringWithOptionsTest, ClampMapsToFClampByDefault) {1853const std::string disassembly_text =1854CompilationOutput(kGlslShaderWithClamp, shaderc_fragment_shader,1855options_.get(), OutputType::SpirvAssemblyText);1856EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 FClamp"));1857}18581859TEST_F(CompileStringWithOptionsTest, ClampMapsToNClampWithNanClamp) {1860shaderc_compile_options_set_nan_clamp(options_.get(), true);1861const std::string disassembly_text =1862CompilationOutput(kGlslShaderWithClamp, shaderc_fragment_shader,1863options_.get(), OutputType::SpirvAssemblyText);1864EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 NClamp"));1865}18661867TEST_F(CompileStringWithOptionsTest, NanClampSurvivesCloning) {1868shaderc_compile_options_set_nan_clamp(options_.get(), true);1869compile_options_ptr cloned_options(1870shaderc_compile_options_clone(options_.get()));1871const std::string disassembly_text =1872CompilationOutput(kGlslShaderWithClamp, shaderc_fragment_shader,1873cloned_options.get(), OutputType::SpirvAssemblyText);1874EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 NClamp"));1875}18761877} // anonymous namespace187818791880